diff --git a/.github/actions/build-bootstrap/action.yml b/.github/actions/build-bootstrap/action.yml new file mode 100644 index 00000000000..826063ff570 --- /dev/null +++ b/.github/actions/build-bootstrap/action.yml @@ -0,0 +1,30 @@ +name: "Build Bootstrap Images" +description: "Build Vitess bootstrap Docker images locally using docker buildx bake" + +inputs: + bootstrap-version: + description: "Bootstrap image version tag" + required: false + default: "ci" + bootstrap-flavor: + description: "Bootstrap image flavor (e.g. mysql84)" + required: false + default: "mysql84" + +runs: + using: "composite" + steps: + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 + + - name: Build bootstrap images + uses: docker/bake-action@5be5f02ff8819ecd3092ea6b2e6261c31774f2b4 # v6.10.0 + with: + files: docker/bootstrap/docker-bake.hcl + load: true + set: | + *.cache-from=type=gha,scope=bootstrap + *.cache-to=type=gha,scope=bootstrap,mode=max + env: + BOOTSTRAP_VERSION: ${{ inputs.bootstrap-version }} + BOOTSTRAP_FLAVOR: ${{ inputs.bootstrap-flavor }} diff --git a/.github/actions/setup-go/action.yml b/.github/actions/setup-go/action.yml new file mode 100644 index 00000000000..7cfc59898f9 --- /dev/null +++ b/.github/actions/setup-go/action.yml @@ -0,0 +1,30 @@ +name: "Set up Go" +description: "Set up Go with shared module caching" +inputs: + cache: + description: "Whether to cache Go modules" + default: "true" +runs: + using: "composite" + steps: + - name: Set up Go + id: setup-go + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 + with: + go-version-file: go.mod + # Disable built-in caching; its key includes ImageOS which + # creates duplicate cache entries across runner types. + cache: false + + - name: Cache Go modules + if: inputs.cache == 'true' && (github.base_ref == 'main' || (github.base_ref == '' && github.ref_name == 'main')) + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + # Same paths cached by actions/setup-go internally. + path: | + ~/go/pkg/mod + ~/.cache/go-build + # Cache by version/arch/hash. Construct hash using same method as actions/setup-go. + key: go-${{ steps.setup-go.outputs.go-version }}-${{ toLower(runner.os) }}-${{ toLower(runner.arch) }}-${{ hashFiles('go.sum') }} + restore-keys: | + go-${{ steps.setup-go.outputs.go-version }}-${{ toLower(runner.os) }}-${{ toLower(runner.arch) }}- diff --git a/.github/actions/setup-mysql/action.yml b/.github/actions/setup-mysql/action.yml index 444c2133a82..2698bd7e025 100644 --- a/.github/actions/setup-mysql/action.yml +++ b/.github/actions/setup-mysql/action.yml @@ -8,7 +8,7 @@ runs: using: "composite" steps: - name: Setup MySQL - shell: bash + shell: bash -e {0} run: | export DEBIAN_FRONTEND="noninteractive" sudo apt-get update @@ -24,7 +24,7 @@ runs: # We have to install this old version of libaio1. See also: # https://bugs.launchpad.net/ubuntu/+source/libaio/+bug/2067501 - wget http://mirrors.kernel.org/ubuntu/pool/main/liba/libaio/libaio1_0.3.112-13build1_amd64.deb && \ + wget http://archive.ubuntu.com/ubuntu/pool/main/liba/libaio/libaio1_0.3.112-13build1_amd64.deb && \ sudo dpkg -i libaio1_0.3.112-13build1_amd64.deb && \ rm libaio1_0.3.112-13build1_amd64.deb @@ -40,7 +40,7 @@ runs: sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get update # libtinfo5 is also needed for older MySQL 5.7 builds. - curl -L -O http://mirrors.kernel.org/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.1_amd64.deb + curl -L -O http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.1_amd64.deb sudo dpkg -i libtinfo5_6.3-2ubuntu0.1_amd64.deb sudo DEBIAN_FRONTEND="noninteractive" apt-get install -y mysql-client=5.7* mysql-community-server=5.7* mysql-server=5.7* libncurses6 elif [[ "${{ inputs.flavor }}" == "mysql-8.0" ]]; then diff --git a/.github/actions/tune-os/action.yml b/.github/actions/tune-os/action.yml index 618e3bfedd2..d3522c38d8a 100644 --- a/.github/actions/tune-os/action.yml +++ b/.github/actions/tune-os/action.yml @@ -4,7 +4,7 @@ runs: using: "composite" steps: - name: Tune the OS - shell: bash + shell: bash -e {0} run: | # Install eatmydata and ensure it's used for every operation sudo apt-get update && sudo apt-get install -y eatmydata diff --git a/.github/workflows/assign_milestone.yml b/.github/workflows/assign_milestone.yml index e0c0b100a74..2d42c849f26 100644 --- a/.github/workflows/assign_milestone.yml +++ b/.github/workflows/assign_milestone.yml @@ -13,6 +13,7 @@ env: jobs: build: + if: github.repository == 'vitessio/vitess' name: Assign Milestone runs-on: ubuntu-24.04 diff --git a/.github/workflows/check_make_vtadmin_authz_testgen.yml b/.github/workflows/check_make_vtadmin_authz_testgen.yml index 5b2c65dee94..7a7fd3336f2 100644 --- a/.github/workflows/check_make_vtadmin_authz_testgen.yml +++ b/.github/workflows/check_make_vtadmin_authz_testgen.yml @@ -52,6 +52,7 @@ jobs: if: steps.changes.outputs.vtadmin_changes == 'true' with: go-version-file: go.mod + cache: ${{ (github.base_ref == 'main' || (github.base_ref == '' && github.ref_name == 'main')) && 'true' || 'false' }} - name: Get dependencies if: steps.changes.outputs.vtadmin_changes == 'true' diff --git a/.github/workflows/check_make_vtadmin_web_proto.yml b/.github/workflows/check_make_vtadmin_web_proto.yml index d1f159e43de..b3fa70683ad 100644 --- a/.github/workflows/check_make_vtadmin_web_proto.yml +++ b/.github/workflows/check_make_vtadmin_web_proto.yml @@ -53,6 +53,7 @@ jobs: if: steps.changes.outputs.proto_changes == 'true' with: go-version-file: go.mod + cache: ${{ (github.base_ref == 'main' || (github.base_ref == '' && github.ref_name == 'main')) && 'true' || 'false' }} - name: Setup Node if: steps.changes.outputs.proto_changes == 'true' diff --git a/.github/workflows/cluster_endtoend.yml b/.github/workflows/cluster_endtoend.yml new file mode 100644 index 00000000000..ec9feca7a5f --- /dev/null +++ b/.github/workflows/cluster_endtoend.yml @@ -0,0 +1,263 @@ +name: Cluster End-to-End Tests + +on: + push: + branches: + - "main" + - "release-[0-9]+.[0-9]" + tags: "**" + pull_request: + branches: "**" + +concurrency: + group: format('{0}-{1}', ${{ github.ref }}, 'Cluster End-to-End Tests') + cancel-in-progress: true + +permissions: read-all + +env: + LAUNCHABLE_ORGANIZATION: "vitess" + LAUNCHABLE_WORKSPACE: "vitess-app" + GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" + +jobs: + generate-matrix: + runs-on: ubuntu-24.04 + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - name: Check out code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: "false" + + - name: Generate shard matrix + id: set-matrix + run: | + # Shards to exclude from this workflow. + # Modify this list to add or remove shards from the cluster end-to-end tests. + # These are either: + # - Run in other dedicated workflows + # - Not cluster tests (unit tests, examples, etc.) + # - Special upgrade/downgrade tests + EXCLUDE_SHARDS='[ + "", + "java", + "docker_cluster", + "5", + "28", + "onlineddl_flow" + ]' + + # Build matrix + matrix=$(jq -c -s --argjson exclude "$EXCLUDE_SHARDS" ' + map(.Tests) | add | to_entries + | group_by(.value.Shard) + | map(select(.[0].value.Shard as $s | ($s != null) and ($exclude | index($s) | not))) + | map({ + shard: .[0].value.Shard, + needs: ([.[].value.Needs // []] | add | unique // []), + buildTag: ([.[].value.BuildTag // null] | map(select(. != null)) | first // "") + }) + ' test/config.json test/config_partial_keyspace.json) + + echo "matrix={\"include\":$matrix}" >> $GITHUB_OUTPUT + + test: + needs: generate-matrix + if: needs.generate-matrix.outputs.matrix != '' + timeout-minutes: 60 + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }} + + name: Run endtoend tests on Cluster (${{ matrix.shard }}) + runs-on: ${{ github.repository == 'vitessio/vitess' && contains(matrix.needs, 'larger-runner') && 'gh-hosted-runners-16cores-1-24.04' || 'ubuntu-24.04' }} + + steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 + with: + egress-policy: audit + + - name: Skip CI + run: | + if [[ "${{ contains(github.event.pull_request.labels.*.name, 'Skip CI') }}" == "true" ]]; then + echo "skipping CI due to the 'Skip CI' label" + exit 1 + fi + + - name: Check Memory + if: contains(matrix.needs, 'memory-check') + run: | + totalMem=$(free -g | awk 'NR==2 {print $2}') + echo "total memory $totalMem GB" + if [[ "$totalMem" -lt 15 ]]; then + echo "Less memory than required" + exit 1 + fi + + - name: Check out code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: "false" + + - name: Check for changes in relevant files + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + id: changes + with: + token: "" + filters: | + end_to_end: + - 'test/config.json' + - 'test/config_partial_keyspace.json' + - 'go/**/*.go' + - 'go/vt/sidecardb/**/*.sql' + - 'go/test/endtoend/onlineddl/vrepl_suite/**' + - 'test.go' + - 'Makefile' + - 'build.env' + - 'go.sum' + - 'go.mod' + - 'proto/*.proto' + - 'tools/**' + - 'config/**' + - 'bootstrap.sh' + - '.github/workflows/cluster_endtoend.yml' + + - name: Set up Go + if: steps.changes.outputs.end_to_end == 'true' + uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + with: + go-version-file: go.mod + cache: ${{ (github.base_ref == 'main' || (github.base_ref == '' && github.ref_name == 'main')) && 'true' || 'false' }} + + - name: Set up python + if: steps.changes.outputs.end_to_end == 'true' + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + + - name: Tune the OS + if: steps.changes.outputs.end_to_end == 'true' + uses: ./.github/actions/tune-os + + - name: Setup MySQL + if: steps.changes.outputs.end_to_end == 'true' && !contains(matrix.needs, 'xtrabackup') + uses: ./.github/actions/setup-mysql + with: + flavor: mysql-8.0 + + - name: Setup Percona Server and XtraBackup + if: steps.changes.outputs.end_to_end == 'true' && contains(matrix.needs, 'xtrabackup') + run: | + sudo apt-get -qq update + sudo apt-get -qq install -y lsb-release gnupg2 + wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb + sudo DEBIAN_FRONTEND="noninteractive" dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb + sudo percona-release setup pdps8.0 + sudo percona-release setup pxb-80 + sudo percona-release enable ps-80 release + sudo apt-get -qq update + sudo apt-get -qq install -y percona-server-server percona-server-client + sudo service mysql stop + sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/ + sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld + sudo apt-get -qq install -y percona-xtrabackup-80 lz4 + + - name: Get dependencies + if: steps.changes.outputs.end_to_end == 'true' + timeout-minutes: 10 + run: | + # Install mysql-shell for non-XtraBackup shards + if [[ "${{ contains(matrix.needs, 'xtrabackup') }}" != "true" ]]; then + sudo apt-get -qq install -y mysql-shell + fi + + sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 + sudo service etcd stop + go mod download + + - name: Install Minio + if: steps.changes.outputs.end_to_end == 'true' && contains(matrix.needs, 'minio') + run: | + wget https://dl.min.io/server/minio/release/linux-amd64/minio + chmod +x minio + sudo mv minio /usr/local/bin + + - name: Install Consul and ZooKeeper + if: steps.changes.outputs.end_to_end == 'true' && contains(matrix.needs, 'consul') + run: make tools + + - name: Setup launchable dependencies + if: | + github.event_name == 'pull_request' && + github.event.pull_request.draft == false && + steps.changes.outputs.end_to_end == 'true' && + github.base_ref == 'main' + run: | + pip3 install --user launchable~=1.0 > /dev/null + launchable verify || true + launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . + + - name: Run cluster endtoend test + if: steps.changes.outputs.end_to_end == 'true' + timeout-minutes: 45 + run: | + export VTDATAROOT="/tmp/" + source build.env + set -exo pipefail + + # Apply resource limits for heavy shards + if [[ "${{ contains(matrix.needs, 'limit-resources') }}" == "true" ]]; then + ulimit -n 65536 + cat <<-EOF>>./config/mycnf/mysql84.cnf + innodb_buffer_pool_dump_at_shutdown=OFF + innodb_buffer_pool_in_core_file=OFF + innodb_buffer_pool_load_at_startup=OFF + innodb_buffer_pool_size=64M + innodb_doublewrite=OFF + innodb_flush_log_at_trx_commit=0 + innodb_flush_method=O_DIRECT + innodb_numa_interleave=ON + innodb_adaptive_hash_index=OFF + sync_binlog=0 + sync_relay_log=0 + performance_schema=OFF + slow-query-log=OFF + EOF + fi + + # Enable binlog compression for vreplication shards + if [[ "${{ contains(matrix.needs, 'binlog-compression') }}" == "true" ]]; then + cat <<-EOF>>./config/mycnf/mysql84.cnf + binlog-transaction-compression=ON + binlog-row-value-options=PARTIAL_JSON + EOF + fi + + # Build test command with optional flags + EXTRA_FLAGS="" + if [[ "${{ matrix.buildTag }}" != "" ]]; then + EXTRA_FLAGS="$EXTRA_FLAGS -build-tag=${{ matrix.buildTag }}" + fi + if [[ "${{ matrix.shard }}" == *"partial_keyspace"* ]]; then + EXTRA_FLAGS="$EXTRA_FLAGS -partial-keyspace=true" + fi + + go run test.go -docker=false -follow -shard "${{ matrix.shard }}" $EXTRA_FLAGS + + - name: Record test results in launchable + if: | + github.event_name == 'pull_request' && + github.event.pull_request.draft == false && + steps.changes.outputs.end_to_end == 'true' && + github.base_ref == 'main' && + !cancelled() + run: | + launchable record tests --build "$GITHUB_RUN_ID" go-test . || true + + - name: Test Summary + if: steps.changes.outputs.end_to_end == 'true' && failure() + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 + with: + paths: "_test/junit/*.xml" + show: "fail" diff --git a/.github/workflows/cluster_endtoend_12.yml b/.github/workflows/cluster_endtoend_12.yml deleted file mode 100644 index 3fb8f1cb026..00000000000 --- a/.github/workflows/cluster_endtoend_12.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (12) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (12)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (12) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_12.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard 12 | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_13.yml b/.github/workflows/cluster_endtoend_13.yml deleted file mode 100644 index 2543a21ff8d..00000000000 --- a/.github/workflows/cluster_endtoend_13.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (13) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (13)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (13) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_13.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard 13 | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_15.yml b/.github/workflows/cluster_endtoend_15.yml deleted file mode 100644 index 665b2182aeb..00000000000 --- a/.github/workflows/cluster_endtoend_15.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (15) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (15)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (15) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_15.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard 15 | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_18.yml b/.github/workflows/cluster_endtoend_18.yml deleted file mode 100644 index 023ef6b823a..00000000000 --- a/.github/workflows/cluster_endtoend_18.yml +++ /dev/null @@ -1,151 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (18) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (18)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (18) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_18.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Installing zookeeper and consul - if: steps.changes.outputs.end_to_end == 'true' - run: | - make tools - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard 18 | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_21.yml b/.github/workflows/cluster_endtoend_21.yml deleted file mode 100644 index f8072fa2149..00000000000 --- a/.github/workflows/cluster_endtoend_21.yml +++ /dev/null @@ -1,152 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (21) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (21)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (21) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_21.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Install Minio - run: | - wget https://dl.min.io/server/minio/release/linux-amd64/minio - chmod +x minio - mv minio /usr/local/bin - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard 21 | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_backup_pitr.yml b/.github/workflows/cluster_endtoend_backup_pitr.yml deleted file mode 100644 index 74b17c582d9..00000000000 --- a/.github/workflows/cluster_endtoend_backup_pitr.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (backup_pitr) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (backup_pitr)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (backup_pitr) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_backup_pitr.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard backup_pitr | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_backup_pitr_mysqlshell.yml b/.github/workflows/cluster_endtoend_backup_pitr_mysqlshell.yml deleted file mode 100644 index d3c221b1d0e..00000000000 --- a/.github/workflows/cluster_endtoend_backup_pitr_mysqlshell.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (backup_pitr_mysqlshell) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (backup_pitr_mysqlshell)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (backup_pitr_mysqlshell) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_backup_pitr_mysqlshell.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard backup_pitr_mysqlshell | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_backup_pitr_xtrabackup.yml b/.github/workflows/cluster_endtoend_backup_pitr_xtrabackup.yml deleted file mode 100644 index bea73382a26..00000000000 --- a/.github/workflows/cluster_endtoend_backup_pitr_xtrabackup.yml +++ /dev/null @@ -1,155 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (backup_pitr_xtrabackup) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (backup_pitr_xtrabackup)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (backup_pitr_xtrabackup) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_backup_pitr_xtrabackup.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - # Setup Percona Server for MySQL 8.0 - sudo apt-get -qq update - sudo apt-get -qq install -y lsb-release gnupg2 - wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb - sudo DEBIAN_FRONTEND="noninteractive" dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb - sudo percona-release setup ps80 - sudo apt-get -qq update - - sudo apt-get -qq install -y percona-server-server percona-server-client - - sudo service mysql stop - - sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/ - sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld - - sudo apt-get -qq install -y percona-xtrabackup-80 lz4 - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard backup_pitr_xtrabackup | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_ers_prs_newfeatures_heavy.yml b/.github/workflows/cluster_endtoend_ers_prs_newfeatures_heavy.yml deleted file mode 100644 index 83882adbbb9..00000000000 --- a/.github/workflows/cluster_endtoend_ers_prs_newfeatures_heavy.yml +++ /dev/null @@ -1,164 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (ers_prs_newfeatures_heavy) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (ers_prs_newfeatures_heavy)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (ers_prs_newfeatures_heavy) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_ers_prs_newfeatures_heavy.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Increase our open file descriptor limit as we could hit this - ulimit -n 65536 - cat <<-EOF>>./config/mycnf/mysql8026.cnf - innodb_buffer_pool_dump_at_shutdown=OFF - innodb_buffer_pool_in_core_file=OFF - innodb_buffer_pool_load_at_startup=OFF - innodb_buffer_pool_size=64M - innodb_doublewrite=OFF - innodb_flush_log_at_trx_commit=0 - innodb_flush_method=O_DIRECT - innodb_numa_interleave=ON - innodb_adaptive_hash_index=OFF - sync_binlog=0 - sync_relay_log=0 - performance_schema=OFF - slow-query-log=OFF - EOF - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard ers_prs_newfeatures_heavy | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_mysql80.yml b/.github/workflows/cluster_endtoend_mysql80.yml deleted file mode 100644 index 62a8049d0ff..00000000000 --- a/.github/workflows/cluster_endtoend_mysql80.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (mysql80) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (mysql80)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (mysql80) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_mysql80.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard mysql80 | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_mysql_server_vault.yml b/.github/workflows/cluster_endtoend_mysql_server_vault.yml deleted file mode 100644 index 917804cb4ce..00000000000 --- a/.github/workflows/cluster_endtoend_mysql_server_vault.yml +++ /dev/null @@ -1,151 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (mysql_server_vault) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (mysql_server_vault)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (mysql_server_vault) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_mysql_server_vault.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Installing zookeeper and consul - if: steps.changes.outputs.end_to_end == 'true' - run: | - make tools - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard mysql_server_vault | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_onlineddl_revert.yml b/.github/workflows/cluster_endtoend_onlineddl_revert.yml deleted file mode 100644 index 3472012c95a..00000000000 --- a/.github/workflows/cluster_endtoend_onlineddl_revert.yml +++ /dev/null @@ -1,147 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (onlineddl_revert) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (onlineddl_revert)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (onlineddl_revert) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_onlineddl_revert.yml' - - 'go/test/endtoend/onlineddl/vrepl_suite/testdata' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard onlineddl_revert | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_onlineddl_scheduler.yml b/.github/workflows/cluster_endtoend_onlineddl_scheduler.yml deleted file mode 100644 index bdbda12c328..00000000000 --- a/.github/workflows/cluster_endtoend_onlineddl_scheduler.yml +++ /dev/null @@ -1,147 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (onlineddl_scheduler) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (onlineddl_scheduler)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (onlineddl_scheduler) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_onlineddl_scheduler.yml' - - 'go/test/endtoend/onlineddl/vrepl_suite/testdata' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard onlineddl_scheduler | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_onlineddl_vrepl.yml b/.github/workflows/cluster_endtoend_onlineddl_vrepl.yml deleted file mode 100644 index 3facd241463..00000000000 --- a/.github/workflows/cluster_endtoend_onlineddl_vrepl.yml +++ /dev/null @@ -1,155 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (onlineddl_vrepl) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (onlineddl_vrepl)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (onlineddl_vrepl) - runs-on: ubuntu-latest-xl - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_onlineddl_vrepl.yml' - - 'go/test/endtoend/onlineddl/vrepl_suite/testdata' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-transaction-compression=ON - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-row-value-options=PARTIAL_JSON - EOF - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard onlineddl_vrepl | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_onlineddl_vrepl_stress.yml b/.github/workflows/cluster_endtoend_onlineddl_vrepl_stress.yml deleted file mode 100644 index 78ea4496723..00000000000 --- a/.github/workflows/cluster_endtoend_onlineddl_vrepl_stress.yml +++ /dev/null @@ -1,155 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (onlineddl_vrepl_stress) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (onlineddl_vrepl_stress)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (onlineddl_vrepl_stress) - runs-on: ubuntu-latest-xl - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_onlineddl_vrepl_stress.yml' - - 'go/test/endtoend/onlineddl/vrepl_suite/testdata' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-transaction-compression=ON - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-row-value-options=PARTIAL_JSON - EOF - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard onlineddl_vrepl_stress | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_onlineddl_vrepl_stress_suite.yml b/.github/workflows/cluster_endtoend_onlineddl_vrepl_stress_suite.yml deleted file mode 100644 index 10b16875e8e..00000000000 --- a/.github/workflows/cluster_endtoend_onlineddl_vrepl_stress_suite.yml +++ /dev/null @@ -1,155 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (onlineddl_vrepl_stress_suite) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (onlineddl_vrepl_stress_suite)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (onlineddl_vrepl_stress_suite) - runs-on: ubuntu-latest-xl - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_onlineddl_vrepl_stress_suite.yml' - - 'go/test/endtoend/onlineddl/vrepl_suite/testdata' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-transaction-compression=ON - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-row-value-options=PARTIAL_JSON - EOF - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard onlineddl_vrepl_stress_suite | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_onlineddl_vrepl_suite.yml b/.github/workflows/cluster_endtoend_onlineddl_vrepl_suite.yml deleted file mode 100644 index 3d18aebe0c0..00000000000 --- a/.github/workflows/cluster_endtoend_onlineddl_vrepl_suite.yml +++ /dev/null @@ -1,155 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (onlineddl_vrepl_suite) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (onlineddl_vrepl_suite)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (onlineddl_vrepl_suite) - runs-on: ubuntu-latest-xl - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_onlineddl_vrepl_suite.yml' - - 'go/test/endtoend/onlineddl/vrepl_suite/testdata' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-transaction-compression=ON - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-row-value-options=PARTIAL_JSON - EOF - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard onlineddl_vrepl_suite | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_schemadiff_vrepl.yml b/.github/workflows/cluster_endtoend_schemadiff_vrepl.yml deleted file mode 100644 index 49b27259095..00000000000 --- a/.github/workflows/cluster_endtoend_schemadiff_vrepl.yml +++ /dev/null @@ -1,155 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (schemadiff_vrepl) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (schemadiff_vrepl)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (schemadiff_vrepl) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_schemadiff_vrepl.yml' - - 'go/test/endtoend/onlineddl/vrepl_suite/testdata' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-transaction-compression=ON - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-row-value-options=PARTIAL_JSON - EOF - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard schemadiff_vrepl | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_tabletmanager_consul.yml b/.github/workflows/cluster_endtoend_tabletmanager_consul.yml deleted file mode 100644 index 1c556db961c..00000000000 --- a/.github/workflows/cluster_endtoend_tabletmanager_consul.yml +++ /dev/null @@ -1,151 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (tabletmanager_consul) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (tabletmanager_consul)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (tabletmanager_consul) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_tabletmanager_consul.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Installing zookeeper and consul - if: steps.changes.outputs.end_to_end == 'true' - run: | - make tools - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard tabletmanager_consul | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_tabletmanager_tablegc.yml b/.github/workflows/cluster_endtoend_tabletmanager_tablegc.yml deleted file mode 100644 index 72f85ea0f2f..00000000000 --- a/.github/workflows/cluster_endtoend_tabletmanager_tablegc.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (tabletmanager_tablegc) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (tabletmanager_tablegc)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (tabletmanager_tablegc) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_tabletmanager_tablegc.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard tabletmanager_tablegc | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_tabletmanager_throttler_topo.yml b/.github/workflows/cluster_endtoend_tabletmanager_throttler_topo.yml deleted file mode 100644 index 57152168dc2..00000000000 --- a/.github/workflows/cluster_endtoend_tabletmanager_throttler_topo.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (tabletmanager_throttler_topo) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (tabletmanager_throttler_topo)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (tabletmanager_throttler_topo) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_tabletmanager_throttler_topo.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard tabletmanager_throttler_topo | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_topo_connection_cache.yml b/.github/workflows/cluster_endtoend_topo_connection_cache.yml deleted file mode 100644 index 22c86f4d608..00000000000 --- a/.github/workflows/cluster_endtoend_topo_connection_cache.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (topo_connection_cache) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (topo_connection_cache)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (topo_connection_cache) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_topo_connection_cache.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard topo_connection_cache | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vreplication_across_db_versions.yml b/.github/workflows/cluster_endtoend_vreplication_across_db_versions.yml deleted file mode 100644 index 3b2967da6a4..00000000000 --- a/.github/workflows/cluster_endtoend_vreplication_across_db_versions.yml +++ /dev/null @@ -1,172 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vreplication_across_db_versions) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vreplication_across_db_versions)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vreplication_across_db_versions) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vreplication_across_db_versions.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Increase our open file descriptor limit as we could hit this - ulimit -n 65536 - cat <<-EOF>>./config/mycnf/mysql8026.cnf - innodb_buffer_pool_dump_at_shutdown=OFF - innodb_buffer_pool_in_core_file=OFF - innodb_buffer_pool_load_at_startup=OFF - innodb_buffer_pool_size=64M - innodb_doublewrite=OFF - innodb_flush_log_at_trx_commit=0 - innodb_flush_method=O_DIRECT - innodb_numa_interleave=ON - innodb_adaptive_hash_index=OFF - sync_binlog=0 - sync_relay_log=0 - performance_schema=OFF - slow-query-log=OFF - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-transaction-compression=ON - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-row-value-options=PARTIAL_JSON - EOF - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vreplication_across_db_versions | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vreplication_basic.yml b/.github/workflows/cluster_endtoend_vreplication_basic.yml deleted file mode 100644 index 982cb936937..00000000000 --- a/.github/workflows/cluster_endtoend_vreplication_basic.yml +++ /dev/null @@ -1,172 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vreplication_basic) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vreplication_basic)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vreplication_basic) - runs-on: ubuntu-latest-xl - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vreplication_basic.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Increase our open file descriptor limit as we could hit this - ulimit -n 65536 - cat <<-EOF>>./config/mycnf/mysql8026.cnf - innodb_buffer_pool_dump_at_shutdown=OFF - innodb_buffer_pool_in_core_file=OFF - innodb_buffer_pool_load_at_startup=OFF - innodb_buffer_pool_size=64M - innodb_doublewrite=OFF - innodb_flush_log_at_trx_commit=0 - innodb_flush_method=O_DIRECT - innodb_numa_interleave=ON - innodb_adaptive_hash_index=OFF - sync_binlog=0 - sync_relay_log=0 - performance_schema=OFF - slow-query-log=OFF - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-transaction-compression=ON - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-row-value-options=PARTIAL_JSON - EOF - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vreplication_basic | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vreplication_cellalias.yml b/.github/workflows/cluster_endtoend_vreplication_cellalias.yml deleted file mode 100644 index a0470ae933c..00000000000 --- a/.github/workflows/cluster_endtoend_vreplication_cellalias.yml +++ /dev/null @@ -1,172 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vreplication_cellalias) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vreplication_cellalias)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vreplication_cellalias) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vreplication_cellalias.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Increase our open file descriptor limit as we could hit this - ulimit -n 65536 - cat <<-EOF>>./config/mycnf/mysql8026.cnf - innodb_buffer_pool_dump_at_shutdown=OFF - innodb_buffer_pool_in_core_file=OFF - innodb_buffer_pool_load_at_startup=OFF - innodb_buffer_pool_size=64M - innodb_doublewrite=OFF - innodb_flush_log_at_trx_commit=0 - innodb_flush_method=O_DIRECT - innodb_numa_interleave=ON - innodb_adaptive_hash_index=OFF - sync_binlog=0 - sync_relay_log=0 - performance_schema=OFF - slow-query-log=OFF - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-transaction-compression=ON - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-row-value-options=PARTIAL_JSON - EOF - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vreplication_cellalias | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vreplication_copy_parallel.yml b/.github/workflows/cluster_endtoend_vreplication_copy_parallel.yml deleted file mode 100644 index fe9abe41a6f..00000000000 --- a/.github/workflows/cluster_endtoend_vreplication_copy_parallel.yml +++ /dev/null @@ -1,172 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vreplication_copy_parallel) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vreplication_copy_parallel)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vreplication_copy_parallel) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vreplication_copy_parallel.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Increase our open file descriptor limit as we could hit this - ulimit -n 65536 - cat <<-EOF>>./config/mycnf/mysql8026.cnf - innodb_buffer_pool_dump_at_shutdown=OFF - innodb_buffer_pool_in_core_file=OFF - innodb_buffer_pool_load_at_startup=OFF - innodb_buffer_pool_size=64M - innodb_doublewrite=OFF - innodb_flush_log_at_trx_commit=0 - innodb_flush_method=O_DIRECT - innodb_numa_interleave=ON - innodb_adaptive_hash_index=OFF - sync_binlog=0 - sync_relay_log=0 - performance_schema=OFF - slow-query-log=OFF - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-transaction-compression=ON - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-row-value-options=PARTIAL_JSON - EOF - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vreplication_copy_parallel | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vreplication_foreign_key_stress.yml b/.github/workflows/cluster_endtoend_vreplication_foreign_key_stress.yml deleted file mode 100644 index 5483535dff1..00000000000 --- a/.github/workflows/cluster_endtoend_vreplication_foreign_key_stress.yml +++ /dev/null @@ -1,172 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vreplication_foreign_key_stress) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vreplication_foreign_key_stress)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vreplication_foreign_key_stress) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vreplication_foreign_key_stress.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Increase our open file descriptor limit as we could hit this - ulimit -n 65536 - cat <<-EOF>>./config/mycnf/mysql8026.cnf - innodb_buffer_pool_dump_at_shutdown=OFF - innodb_buffer_pool_in_core_file=OFF - innodb_buffer_pool_load_at_startup=OFF - innodb_buffer_pool_size=64M - innodb_doublewrite=OFF - innodb_flush_log_at_trx_commit=0 - innodb_flush_method=O_DIRECT - innodb_numa_interleave=ON - innodb_adaptive_hash_index=OFF - sync_binlog=0 - sync_relay_log=0 - performance_schema=OFF - slow-query-log=OFF - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-transaction-compression=ON - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-row-value-options=PARTIAL_JSON - EOF - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vreplication_foreign_key_stress | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vreplication_mariadb_to_mysql.yml b/.github/workflows/cluster_endtoend_vreplication_mariadb_to_mysql.yml deleted file mode 100644 index dcd5d2976a2..00000000000 --- a/.github/workflows/cluster_endtoend_vreplication_mariadb_to_mysql.yml +++ /dev/null @@ -1,172 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vreplication_mariadb_to_mysql) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vreplication_mariadb_to_mysql)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vreplication_mariadb_to_mysql) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vreplication_mariadb_to_mysql.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Increase our open file descriptor limit as we could hit this - ulimit -n 65536 - cat <<-EOF>>./config/mycnf/mysql8026.cnf - innodb_buffer_pool_dump_at_shutdown=OFF - innodb_buffer_pool_in_core_file=OFF - innodb_buffer_pool_load_at_startup=OFF - innodb_buffer_pool_size=64M - innodb_doublewrite=OFF - innodb_flush_log_at_trx_commit=0 - innodb_flush_method=O_DIRECT - innodb_numa_interleave=ON - innodb_adaptive_hash_index=OFF - sync_binlog=0 - sync_relay_log=0 - performance_schema=OFF - slow-query-log=OFF - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-transaction-compression=ON - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-row-value-options=PARTIAL_JSON - EOF - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vreplication_mariadb_to_mysql | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vreplication_migrate.yml b/.github/workflows/cluster_endtoend_vreplication_migrate.yml deleted file mode 100644 index f09ddab1c30..00000000000 --- a/.github/workflows/cluster_endtoend_vreplication_migrate.yml +++ /dev/null @@ -1,172 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vreplication_migrate) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vreplication_migrate)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vreplication_migrate) - runs-on: ubuntu-latest-xl - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vreplication_migrate.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Increase our open file descriptor limit as we could hit this - ulimit -n 65536 - cat <<-EOF>>./config/mycnf/mysql8026.cnf - innodb_buffer_pool_dump_at_shutdown=OFF - innodb_buffer_pool_in_core_file=OFF - innodb_buffer_pool_load_at_startup=OFF - innodb_buffer_pool_size=64M - innodb_doublewrite=OFF - innodb_flush_log_at_trx_commit=0 - innodb_flush_method=O_DIRECT - innodb_numa_interleave=ON - innodb_adaptive_hash_index=OFF - sync_binlog=0 - sync_relay_log=0 - performance_schema=OFF - slow-query-log=OFF - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-transaction-compression=ON - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-row-value-options=PARTIAL_JSON - EOF - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vreplication_migrate | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vreplication_multi_tenant.yml b/.github/workflows/cluster_endtoend_vreplication_multi_tenant.yml deleted file mode 100644 index 80b48fb206b..00000000000 --- a/.github/workflows/cluster_endtoend_vreplication_multi_tenant.yml +++ /dev/null @@ -1,172 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vreplication_multi_tenant) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vreplication_multi_tenant)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vreplication_multi_tenant) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vreplication_multi_tenant.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Increase our open file descriptor limit as we could hit this - ulimit -n 65536 - cat <<-EOF>>./config/mycnf/mysql8026.cnf - innodb_buffer_pool_dump_at_shutdown=OFF - innodb_buffer_pool_in_core_file=OFF - innodb_buffer_pool_load_at_startup=OFF - innodb_buffer_pool_size=64M - innodb_doublewrite=OFF - innodb_flush_log_at_trx_commit=0 - innodb_flush_method=O_DIRECT - innodb_numa_interleave=ON - innodb_adaptive_hash_index=OFF - sync_binlog=0 - sync_relay_log=0 - performance_schema=OFF - slow-query-log=OFF - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-transaction-compression=ON - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-row-value-options=PARTIAL_JSON - EOF - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vreplication_multi_tenant | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vreplication_partial_movetables_and_materialize.yml b/.github/workflows/cluster_endtoend_vreplication_partial_movetables_and_materialize.yml deleted file mode 100644 index 04fb7caeb04..00000000000 --- a/.github/workflows/cluster_endtoend_vreplication_partial_movetables_and_materialize.yml +++ /dev/null @@ -1,172 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vreplication_partial_movetables_and_materialize) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vreplication_partial_movetables_and_materialize)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vreplication_partial_movetables_and_materialize) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vreplication_partial_movetables_and_materialize.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Increase our open file descriptor limit as we could hit this - ulimit -n 65536 - cat <<-EOF>>./config/mycnf/mysql8026.cnf - innodb_buffer_pool_dump_at_shutdown=OFF - innodb_buffer_pool_in_core_file=OFF - innodb_buffer_pool_load_at_startup=OFF - innodb_buffer_pool_size=64M - innodb_doublewrite=OFF - innodb_flush_log_at_trx_commit=0 - innodb_flush_method=O_DIRECT - innodb_numa_interleave=ON - innodb_adaptive_hash_index=OFF - sync_binlog=0 - sync_relay_log=0 - performance_schema=OFF - slow-query-log=OFF - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-transaction-compression=ON - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-row-value-options=PARTIAL_JSON - EOF - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vreplication_partial_movetables_and_materialize | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vreplication_v2.yml b/.github/workflows/cluster_endtoend_vreplication_v2.yml deleted file mode 100644 index 0a9dceee48a..00000000000 --- a/.github/workflows/cluster_endtoend_vreplication_v2.yml +++ /dev/null @@ -1,172 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vreplication_v2) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vreplication_v2)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vreplication_v2) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vreplication_v2.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Increase our open file descriptor limit as we could hit this - ulimit -n 65536 - cat <<-EOF>>./config/mycnf/mysql8026.cnf - innodb_buffer_pool_dump_at_shutdown=OFF - innodb_buffer_pool_in_core_file=OFF - innodb_buffer_pool_load_at_startup=OFF - innodb_buffer_pool_size=64M - innodb_doublewrite=OFF - innodb_flush_log_at_trx_commit=0 - innodb_flush_method=O_DIRECT - innodb_numa_interleave=ON - innodb_adaptive_hash_index=OFF - sync_binlog=0 - sync_relay_log=0 - performance_schema=OFF - slow-query-log=OFF - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-transaction-compression=ON - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-row-value-options=PARTIAL_JSON - EOF - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vreplication_v2 | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vreplication_vdiff2.yml b/.github/workflows/cluster_endtoend_vreplication_vdiff2.yml deleted file mode 100644 index e704ea9993f..00000000000 --- a/.github/workflows/cluster_endtoend_vreplication_vdiff2.yml +++ /dev/null @@ -1,172 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vreplication_vdiff2) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vreplication_vdiff2)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vreplication_vdiff2) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vreplication_vdiff2.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Increase our open file descriptor limit as we could hit this - ulimit -n 65536 - cat <<-EOF>>./config/mycnf/mysql8026.cnf - innodb_buffer_pool_dump_at_shutdown=OFF - innodb_buffer_pool_in_core_file=OFF - innodb_buffer_pool_load_at_startup=OFF - innodb_buffer_pool_size=64M - innodb_doublewrite=OFF - innodb_flush_log_at_trx_commit=0 - innodb_flush_method=O_DIRECT - innodb_numa_interleave=ON - innodb_adaptive_hash_index=OFF - sync_binlog=0 - sync_relay_log=0 - performance_schema=OFF - slow-query-log=OFF - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-transaction-compression=ON - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-row-value-options=PARTIAL_JSON - EOF - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vreplication_vdiff2 | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vreplication_vtctldclient_movetables_tz.yml b/.github/workflows/cluster_endtoend_vreplication_vtctldclient_movetables_tz.yml deleted file mode 100644 index 2a14f8cffb5..00000000000 --- a/.github/workflows/cluster_endtoend_vreplication_vtctldclient_movetables_tz.yml +++ /dev/null @@ -1,172 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vreplication_vtctldclient_movetables_tz) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vreplication_vtctldclient_movetables_tz)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vreplication_vtctldclient_movetables_tz) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vreplication_vtctldclient_movetables_tz.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Increase our open file descriptor limit as we could hit this - ulimit -n 65536 - cat <<-EOF>>./config/mycnf/mysql8026.cnf - innodb_buffer_pool_dump_at_shutdown=OFF - innodb_buffer_pool_in_core_file=OFF - innodb_buffer_pool_load_at_startup=OFF - innodb_buffer_pool_size=64M - innodb_doublewrite=OFF - innodb_flush_log_at_trx_commit=0 - innodb_flush_method=O_DIRECT - innodb_numa_interleave=ON - innodb_adaptive_hash_index=OFF - sync_binlog=0 - sync_relay_log=0 - performance_schema=OFF - slow-query-log=OFF - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-transaction-compression=ON - EOF - - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-row-value-options=PARTIAL_JSON - EOF - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vreplication_vtctldclient_movetables_tz | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vstream.yml b/.github/workflows/cluster_endtoend_vstream.yml deleted file mode 100644 index c51b78be5f5..00000000000 --- a/.github/workflows/cluster_endtoend_vstream.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vstream) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vstream)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vstream) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vstream.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vstream | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtbackup.yml b/.github/workflows/cluster_endtoend_vtbackup.yml deleted file mode 100644 index 06ce396bea2..00000000000 --- a/.github/workflows/cluster_endtoend_vtbackup.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtbackup) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtbackup)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtbackup) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtbackup.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtbackup | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtctlbackup_sharded_clustertest_heavy.yml b/.github/workflows/cluster_endtoend_vtctlbackup_sharded_clustertest_heavy.yml deleted file mode 100644 index 80eb4b3a6af..00000000000 --- a/.github/workflows/cluster_endtoend_vtctlbackup_sharded_clustertest_heavy.yml +++ /dev/null @@ -1,164 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtctlbackup_sharded_clustertest_heavy) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtctlbackup_sharded_clustertest_heavy)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtctlbackup_sharded_clustertest_heavy) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtctlbackup_sharded_clustertest_heavy.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Increase our open file descriptor limit as we could hit this - ulimit -n 65536 - cat <<-EOF>>./config/mycnf/mysql8026.cnf - innodb_buffer_pool_dump_at_shutdown=OFF - innodb_buffer_pool_in_core_file=OFF - innodb_buffer_pool_load_at_startup=OFF - innodb_buffer_pool_size=64M - innodb_doublewrite=OFF - innodb_flush_log_at_trx_commit=0 - innodb_flush_method=O_DIRECT - innodb_numa_interleave=ON - innodb_adaptive_hash_index=OFF - sync_binlog=0 - sync_relay_log=0 - performance_schema=OFF - slow-query-log=OFF - EOF - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtctlbackup_sharded_clustertest_heavy | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtgate_concurrentdml.yml b/.github/workflows/cluster_endtoend_vtgate_concurrentdml.yml deleted file mode 100644 index 386ba608a3c..00000000000 --- a/.github/workflows/cluster_endtoend_vtgate_concurrentdml.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtgate_concurrentdml) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtgate_concurrentdml)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtgate_concurrentdml) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtgate_concurrentdml.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtgate_concurrentdml | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtgate_foreignkey_stress.yml b/.github/workflows/cluster_endtoend_vtgate_foreignkey_stress.yml deleted file mode 100644 index af845571892..00000000000 --- a/.github/workflows/cluster_endtoend_vtgate_foreignkey_stress.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtgate_foreignkey_stress) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtgate_foreignkey_stress)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtgate_foreignkey_stress) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtgate_foreignkey_stress.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtgate_foreignkey_stress | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtgate_gen4.yml b/.github/workflows/cluster_endtoend_vtgate_gen4.yml deleted file mode 100644 index 1accf1e0511..00000000000 --- a/.github/workflows/cluster_endtoend_vtgate_gen4.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtgate_gen4) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtgate_gen4)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtgate_gen4) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtgate_gen4.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtgate_gen4 | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtgate_general_heavy.yml b/.github/workflows/cluster_endtoend_vtgate_general_heavy.yml deleted file mode 100644 index 5b667d4d78e..00000000000 --- a/.github/workflows/cluster_endtoend_vtgate_general_heavy.yml +++ /dev/null @@ -1,164 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtgate_general_heavy) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtgate_general_heavy)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtgate_general_heavy) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtgate_general_heavy.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Increase our open file descriptor limit as we could hit this - ulimit -n 65536 - cat <<-EOF>>./config/mycnf/mysql8026.cnf - innodb_buffer_pool_dump_at_shutdown=OFF - innodb_buffer_pool_in_core_file=OFF - innodb_buffer_pool_load_at_startup=OFF - innodb_buffer_pool_size=64M - innodb_doublewrite=OFF - innodb_flush_log_at_trx_commit=0 - innodb_flush_method=O_DIRECT - innodb_numa_interleave=ON - innodb_adaptive_hash_index=OFF - sync_binlog=0 - sync_relay_log=0 - performance_schema=OFF - slow-query-log=OFF - EOF - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtgate_general_heavy | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtgate_godriver.yml b/.github/workflows/cluster_endtoend_vtgate_godriver.yml deleted file mode 100644 index c614225700f..00000000000 --- a/.github/workflows/cluster_endtoend_vtgate_godriver.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtgate_godriver) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtgate_godriver)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtgate_godriver) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtgate_godriver.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtgate_godriver | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtgate_partial_keyspace.yml b/.github/workflows/cluster_endtoend_vtgate_partial_keyspace.yml deleted file mode 100644 index b4b3f61c5c3..00000000000 --- a/.github/workflows/cluster_endtoend_vtgate_partial_keyspace.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtgate_partial_keyspace) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtgate_partial_keyspace)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtgate_partial_keyspace) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtgate_partial_keyspace.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtgate_partial_keyspace -partial-keyspace=true | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtgate_plantests.yml b/.github/workflows/cluster_endtoend_vtgate_plantests.yml deleted file mode 100644 index e7f1d989b96..00000000000 --- a/.github/workflows/cluster_endtoend_vtgate_plantests.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtgate_plantests) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtgate_plantests)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtgate_plantests) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtgate_plantests.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtgate_plantests | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtgate_queries.yml b/.github/workflows/cluster_endtoend_vtgate_queries.yml deleted file mode 100644 index 9572843189b..00000000000 --- a/.github/workflows/cluster_endtoend_vtgate_queries.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtgate_queries) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtgate_queries)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtgate_queries) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtgate_queries.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtgate_queries | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtgate_readafterwrite.yml b/.github/workflows/cluster_endtoend_vtgate_readafterwrite.yml deleted file mode 100644 index c0f5bab58ca..00000000000 --- a/.github/workflows/cluster_endtoend_vtgate_readafterwrite.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtgate_readafterwrite) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtgate_readafterwrite)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtgate_readafterwrite) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtgate_readafterwrite.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtgate_readafterwrite | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtgate_reservedconn.yml b/.github/workflows/cluster_endtoend_vtgate_reservedconn.yml deleted file mode 100644 index e700168102d..00000000000 --- a/.github/workflows/cluster_endtoend_vtgate_reservedconn.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtgate_reservedconn) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtgate_reservedconn)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtgate_reservedconn) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtgate_reservedconn.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtgate_reservedconn | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtgate_schema.yml b/.github/workflows/cluster_endtoend_vtgate_schema.yml deleted file mode 100644 index 9e735524771..00000000000 --- a/.github/workflows/cluster_endtoend_vtgate_schema.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtgate_schema) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtgate_schema)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtgate_schema) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtgate_schema.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtgate_schema | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtgate_schema_tracker.yml b/.github/workflows/cluster_endtoend_vtgate_schema_tracker.yml deleted file mode 100644 index 0aa174c2009..00000000000 --- a/.github/workflows/cluster_endtoend_vtgate_schema_tracker.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtgate_schema_tracker) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtgate_schema_tracker)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtgate_schema_tracker) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtgate_schema_tracker.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtgate_schema_tracker | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtgate_tablet_healthcheck_cache.yml b/.github/workflows/cluster_endtoend_vtgate_tablet_healthcheck_cache.yml deleted file mode 100644 index d13c078eca0..00000000000 --- a/.github/workflows/cluster_endtoend_vtgate_tablet_healthcheck_cache.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtgate_tablet_healthcheck_cache) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtgate_tablet_healthcheck_cache)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtgate_tablet_healthcheck_cache) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtgate_tablet_healthcheck_cache.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtgate_tablet_healthcheck_cache | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtgate_topo.yml b/.github/workflows/cluster_endtoend_vtgate_topo.yml deleted file mode 100644 index 50d508351d8..00000000000 --- a/.github/workflows/cluster_endtoend_vtgate_topo.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtgate_topo) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtgate_topo)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtgate_topo) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtgate_topo.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtgate_topo | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtgate_topo_consul.yml b/.github/workflows/cluster_endtoend_vtgate_topo_consul.yml deleted file mode 100644 index 441173499ca..00000000000 --- a/.github/workflows/cluster_endtoend_vtgate_topo_consul.yml +++ /dev/null @@ -1,151 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtgate_topo_consul) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtgate_topo_consul)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtgate_topo_consul) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtgate_topo_consul.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Installing zookeeper and consul - if: steps.changes.outputs.end_to_end == 'true' - run: | - make tools - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtgate_topo_consul | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtgate_topo_etcd.yml b/.github/workflows/cluster_endtoend_vtgate_topo_etcd.yml deleted file mode 100644 index 42d83929d91..00000000000 --- a/.github/workflows/cluster_endtoend_vtgate_topo_etcd.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtgate_topo_etcd) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtgate_topo_etcd)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtgate_topo_etcd) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtgate_topo_etcd.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtgate_topo_etcd | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtgate_transaction.yml b/.github/workflows/cluster_endtoend_vtgate_transaction.yml deleted file mode 100644 index 7216b862189..00000000000 --- a/.github/workflows/cluster_endtoend_vtgate_transaction.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtgate_transaction) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtgate_transaction)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtgate_transaction) - runs-on: ubuntu-latest-xl - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtgate_transaction.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtgate_transaction -build-tag=debug2PC | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtgate_unsharded.yml b/.github/workflows/cluster_endtoend_vtgate_unsharded.yml deleted file mode 100644 index 9f74f03dffa..00000000000 --- a/.github/workflows/cluster_endtoend_vtgate_unsharded.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtgate_unsharded) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtgate_unsharded)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtgate_unsharded) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtgate_unsharded.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtgate_unsharded | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtgate_vindex_heavy.yml b/.github/workflows/cluster_endtoend_vtgate_vindex_heavy.yml deleted file mode 100644 index f3b211b07f5..00000000000 --- a/.github/workflows/cluster_endtoend_vtgate_vindex_heavy.yml +++ /dev/null @@ -1,164 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtgate_vindex_heavy) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtgate_vindex_heavy)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtgate_vindex_heavy) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtgate_vindex_heavy.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Increase our open file descriptor limit as we could hit this - ulimit -n 65536 - cat <<-EOF>>./config/mycnf/mysql8026.cnf - innodb_buffer_pool_dump_at_shutdown=OFF - innodb_buffer_pool_in_core_file=OFF - innodb_buffer_pool_load_at_startup=OFF - innodb_buffer_pool_size=64M - innodb_doublewrite=OFF - innodb_flush_log_at_trx_commit=0 - innodb_flush_method=O_DIRECT - innodb_numa_interleave=ON - innodb_adaptive_hash_index=OFF - sync_binlog=0 - sync_relay_log=0 - performance_schema=OFF - slow-query-log=OFF - EOF - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtgate_vindex_heavy | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtgate_vschema.yml b/.github/workflows/cluster_endtoend_vtgate_vschema.yml deleted file mode 100644 index 5c9e79d9d11..00000000000 --- a/.github/workflows/cluster_endtoend_vtgate_vschema.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtgate_vschema) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtgate_vschema)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtgate_vschema) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtgate_vschema.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtgate_vschema | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vtorc.yml b/.github/workflows/cluster_endtoend_vtorc.yml deleted file mode 100644 index 38d19debac8..00000000000 --- a/.github/workflows/cluster_endtoend_vtorc.yml +++ /dev/null @@ -1,155 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vtorc) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vtorc)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vtorc) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check Memory - run: | - totalMem=$(free -g | awk 'NR==2 {print $2}') - echo "total memory $totalMem GB" - if [[ "$totalMem" -lt 15 ]]; then - echo "Less memory than required" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vtorc.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vtorc | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_vttablet_prscomplex.yml b/.github/workflows/cluster_endtoend_vttablet_prscomplex.yml deleted file mode 100644 index 5901a0115e6..00000000000 --- a/.github/workflows/cluster_endtoend_vttablet_prscomplex.yml +++ /dev/null @@ -1,146 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (vttablet_prscomplex) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (vttablet_prscomplex)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (vttablet_prscomplex) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_vttablet_prscomplex.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - sudo apt-get -qq install -y mysql-shell - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard vttablet_prscomplex | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_xb_backup.yml b/.github/workflows/cluster_endtoend_xb_backup.yml deleted file mode 100644 index 22de31fcad1..00000000000 --- a/.github/workflows/cluster_endtoend_xb_backup.yml +++ /dev/null @@ -1,155 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (xb_backup) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (xb_backup)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (xb_backup) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_xb_backup.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - # Setup Percona Server for MySQL 8.0 - sudo apt-get -qq update - sudo apt-get -qq install -y lsb-release gnupg2 - wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb - sudo DEBIAN_FRONTEND="noninteractive" dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb - sudo percona-release setup ps80 - sudo apt-get -qq update - - sudo apt-get -qq install -y percona-server-server percona-server-client - - sudo service mysql stop - - sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/ - sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld - - sudo apt-get -qq install -y percona-xtrabackup-80 lz4 - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard xb_backup | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/cluster_endtoend_xb_recovery.yml b/.github/workflows/cluster_endtoend_xb_recovery.yml deleted file mode 100644 index ee2627f0b09..00000000000 --- a/.github/workflows/cluster_endtoend_xb_recovery.yml +++ /dev/null @@ -1,155 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Cluster (xb_recovery) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Cluster (xb_recovery)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on Cluster (xb_recovery) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/cluster_endtoend_xb_recovery.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - - # Setup Percona Server for MySQL 8.0 - sudo apt-get -qq update - sudo apt-get -qq install -y lsb-release gnupg2 - wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb - sudo DEBIAN_FRONTEND="noninteractive" dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb - sudo percona-release setup ps80 - sudo apt-get -qq update - - sudo apt-get -qq install -y percona-server-server percona-server-client - - sudo service mysql stop - - sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/ - sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld - - sudo apt-get -qq install -y percona-xtrabackup-80 lz4 - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker=false -follow -shard xb_recovery | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 69bfef8ce77..0880fc2a226 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -1,5 +1,7 @@ name: Code Coverage on: + schedule: + - cron: '0 0 * * 6' # Saturday midnight UTC push: branches: - "main" @@ -8,13 +10,14 @@ on: pull_request: branches: '**' concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Code Coverage') + group: format('{0}-{1}-{2}', ${{ github.ref }}, ${{ github.event_name }}, 'Code Coverage') cancel-in-progress: true permissions: read-all jobs: test: + if: github.repository == 'vitessio/vitess' && (github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'Backport')) name: Code Coverage runs-on: oracle-vm-8cpu-32gb-x86-64 @@ -22,10 +25,21 @@ jobs: - name: Check out code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: + fetch-depth: 0 persist-credentials: 'false' + - name: Determine run mode + id: mode + run: | + if [ "${{ github.event_name }}" = "schedule" ]; then + echo "is_full_run=true" >> "$GITHUB_OUTPUT" + else + echo "is_full_run=false" >> "$GITHUB_OUTPUT" + fi + - name: Check for changes in files relevant to code coverage - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 + if: steps.mode.outputs.is_full_run != 'true' + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 id: changes with: token: '' @@ -38,27 +52,64 @@ jobs: - Makefile - name: Set up Go - if: steps.changes.outputs.changed_files == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + if: steps.mode.outputs.is_full_run == 'true' || steps.changes.outputs.changed_files == 'true' + uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version-file: go.mod + cache: ${{ (github.base_ref == 'main' || (github.base_ref == '' && github.ref_name == 'main')) && 'true' || 'false' }} + + - name: Detect changed Go packages + if: steps.mode.outputs.is_full_run != 'true' && steps.changes.outputs.changed_files == 'true' + id: packages + run: | + BASE_SHA="${{ github.event.pull_request.base.sha }}" + HEAD_SHA="${{ github.event.pull_request.head.sha }}" + CHANGED_GO_FILES=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA" -- '*.go') + + if [ -z "$CHANGED_GO_FILES" ]; then + echo "BASE_SHA=$BASE_SHA" + echo "HEAD_SHA=$HEAD_SHA" + echo "packages=$PACKAGES" + + echo "packages=" >> "$GITHUB_OUTPUT" + exit 0 + fi + + PACKAGE_DIRS=$(echo "$CHANGED_GO_FILES" | xargs -n1 dirname | sort -u) + + # Validate as Go packages and exclude endtoend tests + PACKAGES="" + for dir in $PACKAGE_DIRS; do + case "$dir" in + */endtoend*|go/cmd/vttestserver*) continue ;; + esac + if go list "./$dir" >/dev/null 2>&1; then + PACKAGES="${PACKAGES:+$PACKAGES }$dir" + fi + done + + echo "BASE_SHA=$BASE_SHA" + echo "HEAD_SHA=$HEAD_SHA" + echo "packages=$PACKAGES" + + echo "packages=$PACKAGES" >> "$GITHUB_OUTPUT" - name: Set up python - if: steps.changes.outputs.changed_files == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 + if: steps.mode.outputs.is_full_run == 'true' || (steps.changes.outputs.changed_files == 'true' && steps.packages.outputs.packages != '') + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 - name: Tune the OS - if: steps.changes.outputs.changed_files == 'true' + if: steps.mode.outputs.is_full_run == 'true' || (steps.changes.outputs.changed_files == 'true' && steps.packages.outputs.packages != '') uses: ./.github/actions/tune-os - name: Setup MySQL - if: steps.changes.outputs.changed_files == 'true' + if: steps.mode.outputs.is_full_run == 'true' || (steps.changes.outputs.changed_files == 'true' && steps.packages.outputs.packages != '') uses: ./.github/actions/setup-mysql with: flavor: mysql-8.0 - name: Get dependencies - if: steps.changes.outputs.changed_files == 'true' + if: steps.mode.outputs.is_full_run == 'true' || (steps.changes.outputs.changed_files == 'true' && steps.packages.outputs.packages != '') run: | export DEBIAN_FRONTEND="noninteractive" sudo apt-get update @@ -73,35 +124,32 @@ jobs: go install golang.org/x/tools/cmd/goimports@latest - name: Run make tools - if: steps.changes.outputs.changed_files == 'true' + if: steps.mode.outputs.is_full_run == 'true' || (steps.changes.outputs.changed_files == 'true' && steps.packages.outputs.packages != '') run: | make tools - - name: Run unit tests and generate code coverage reports - if: steps.changes.outputs.changed_files == 'true' - timeout-minutes: 45 + - name: Run coverage tests + if: steps.mode.outputs.is_full_run == 'true' || (steps.changes.outputs.changed_files == 'true' && steps.packages.outputs.packages != '') + timeout-minutes: 60 run: | set -exo pipefail - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. export VTDATAROOT="/tmp/" - export NOVTADMINBUILD=1 + source build.env - # Exclude endtoend tests from the coverage report. - # TODO: figure out how best to include our endtoend tests in the coverage report. - rm -rf go/test/endtoend go/*/endtoend go/vt/*/endtoend go/cmd/vttestserver - - make unit_test_cover - - # Restore the files we deleted as codecov tries to fix their paths. - git reset --hard HEAD + if [ "${{ steps.mode.outputs.is_full_run }}" = "true" ]; then + make unit_test_cover + else + make COVERAGE_PACKAGES="${{ steps.packages.outputs.packages }}" unit_test_cover + fi - - name: Upload coverage reports to codecov.io - if: steps.changes.outputs.changed_files == 'true' - uses: codecov/codecov-action@015f24e6818733317a2da2edd6290ab26238649a # https://github.com/codecov/codecov-action/releases/tag/v5.0.7 + - name: Upload coverage reports + if: steps.mode.outputs.is_full_run == 'true' || (steps.changes.outputs.changed_files == 'true' && steps.packages.outputs.packages != '') + uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2 with: + files: coverage.out fail_ci_if_error: true verbose: true + flags: ${{ steps.mode.outputs.is_full_run == 'true' && '' || 'partial' }} env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/codeql_analysis.yml b/.github/workflows/codeql_analysis.yml index c98780ca527..0ed7fb32280 100644 --- a/.github/workflows/codeql_analysis.yml +++ b/.github/workflows/codeql_analysis.yml @@ -35,13 +35,14 @@ jobs: uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod + cache: ${{ (github.base_ref == 'main' || (github.base_ref == '' && github.ref_name == 'main')) && 'true' || 'false' }} - name: Tune the OS uses: ./.github/actions/tune-os # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@4bdb89f48054571735e3792627da6195c57459e2 # v3.28.18 with: languages: ${{ matrix.language }} # If you wish to specify cu stom queries, you can do so here or in a config file. @@ -62,12 +63,9 @@ jobs: sudo DEBIAN_FRONTEND="noninteractive" apt-get update # Install everything else we need, and configure sudo apt-get install -y make unzip g++ etcd-client etcd-server curl git wget - + sudo service etcd stop - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - + - name: Building binaries timeout-minutes: 30 run: | @@ -75,11 +73,11 @@ jobs: make build - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@4bdb89f48054571735e3792627da6195c57459e2 # v3.28.18 - name: Slack Workflow Notification if: ${{ failure() }} - uses: Gamesight/slack-workflow-status@master + uses: Gamesight/slack-workflow-status@68bf00d0dbdbcb206c278399aa1ef6c14f74347a # v1.3.0 with: repo_token: ${{secrets.GITHUB_TOKEN}} slack_webhook_url: ${{secrets.SLACK_WEBHOOK_URL}} diff --git a/.github/workflows/docker_ci.yml b/.github/workflows/docker_ci.yml new file mode 100644 index 00000000000..2cb181df5ef --- /dev/null +++ b/.github/workflows/docker_ci.yml @@ -0,0 +1,91 @@ +name: docker_ci +on: + push: + branches: + - "main" + - "release-[0-9]+.[0-9]" + tags: "**" + pull_request: + branches: "**" +permissions: read-all + +env: + BOOTSTRAP_VERSION: "ci" + BOOTSTRAP_FLAVOR: "mysql84" + +jobs: + build: + name: ${{ matrix.name }} + runs-on: ubuntu-24.04 + + strategy: + fail-fast: false + matrix: + include: + - shard: java + name: Java Docker Test + - shard: docker_cluster + name: Docker Test Cluster + + steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 + with: + egress-policy: audit + + - name: Skip CI + run: | + if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then + echo "skipping CI due to the 'Skip CI' label" + exit 1 + fi + + - name: Check out code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: "false" + + - name: Check for changes in relevant files + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + id: changes + with: + token: "" + filters: | + end_to_end: + - 'test/config.json' + - 'go/**/*.go' + - 'test.go' + - 'Makefile' + - 'build.env' + - 'go.sum' + - 'go.mod' + - 'proto/*.proto' + - 'tools/**' + - 'config/**' + - 'bootstrap.sh' + - 'docker/**' + - 'java/**' + - '.github/workflows/docker_ci.yml' + + - name: Build bootstrap images + if: steps.changes.outputs.end_to_end == 'true' + uses: ./.github/actions/build-bootstrap + with: + bootstrap-version: ${{ env.BOOTSTRAP_VERSION }} + bootstrap-flavor: ${{ env.BOOTSTRAP_FLAVOR }} + + - name: Set up Go + if: steps.changes.outputs.end_to_end == 'true' + uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + with: + go-version-file: go.mod + cache: ${{ (github.base_ref == 'main' || (github.base_ref == '' && github.ref_name == 'main')) && 'true' || 'false' }} + + - name: Tune the OS + if: steps.changes.outputs.end_to_end == 'true' + uses: ./.github/actions/tune-os + + - name: Run docker tests - ${{ matrix.shard }} + if: steps.changes.outputs.end_to_end == 'true' + run: | + go run test.go -docker=true -pull=false -flavor=${{ env.BOOTSTRAP_FLAVOR }} -bootstrap-version=${{ env.BOOTSTRAP_VERSION }} --follow -shard ${{ matrix.shard }} diff --git a/.github/workflows/docker_lite_build_check.yml b/.github/workflows/docker_lite_build_check.yml new file mode 100644 index 00000000000..83923fd2c85 --- /dev/null +++ b/.github/workflows/docker_lite_build_check.yml @@ -0,0 +1,68 @@ +name: Docker Lite Build Check + +on: + pull_request: + branches: '**' + push: + branches: + - "main" + - "release-[0-9]+.[0-9]" + +permissions: read-all + +jobs: + generate-matrix: + name: Generate matrix + runs-on: ubuntu-24.04 + outputs: + dockerfiles: ${{ steps.generate-matrix.outputs.dockerfiles }} + steps: + - name: Check out code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: 'false' + + - name: Generate matrix + id: generate-matrix + run: | + dockerfiles=$(ls docker/lite/Dockerfile* | jq -Rnc '[inputs]') + echo "dockerfiles=${dockerfiles}" >> "$GITHUB_OUTPUT" + + build: + name: Build ${{ matrix.dockerfile }} + runs-on: ubuntu-24.04 + needs: generate-matrix + + strategy: + fail-fast: false + matrix: + dockerfile: ${{ fromJson(needs.generate-matrix.outputs.dockerfiles) }} + + steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 + with: + egress-policy: audit + + - name: Skip CI + run: | + if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then + echo "skipping CI due to the 'Skip CI' label" + exit 1 + fi + + - name: Check out code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: 'false' + + - name: Build lite image + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + with: + context: . + file: ${{ matrix.dockerfile }} + push: false + + concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.dockerfile }} + cancel-in-progress: true diff --git a/.github/workflows/docker_test_cluster.yml b/.github/workflows/docker_test_cluster.yml deleted file mode 100644 index 40fab087f8a..00000000000 --- a/.github/workflows/docker_test_cluster.yml +++ /dev/null @@ -1,64 +0,0 @@ -name: docker_test_cluster -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -permissions: read-all -jobs: - - build: - name: Docker Test Cluster - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - 'docker/**' - - '.github/workflows/docker_test_cluster.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Run tests which require docker - 2 - if: steps.changes.outputs.end_to_end == 'true' - run: | - go run test.go -docker=true --follow -shard docker_cluster diff --git a/.github/workflows/e2e_race.yml b/.github/workflows/e2e_race.yml index ec934225c73..3d1270407e7 100644 --- a/.github/workflows/e2e_race.yml +++ b/.github/workflows/e2e_race.yml @@ -50,6 +50,7 @@ jobs: uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod + cache: ${{ (github.base_ref == 'main' || (github.base_ref == '' && github.ref_name == 'main')) && 'true' || 'false' }} - name: Tune the OS if: steps.changes.outputs.end_to_end == 'true' diff --git a/.github/workflows/endtoend.yml b/.github/workflows/endtoend.yml index 6543990abd4..896da9babb5 100644 --- a/.github/workflows/endtoend.yml +++ b/.github/workflows/endtoend.yml @@ -50,6 +50,7 @@ jobs: uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod + cache: ${{ (github.base_ref == 'main' || (github.base_ref == '' && github.ref_name == 'main')) && 'true' || 'false' }} - name: Tune the OS if: steps.changes.outputs.end_to_end == 'true' diff --git a/.github/workflows/java_docker_test.yml b/.github/workflows/java_docker_test.yml deleted file mode 100644 index 65e8253fd08..00000000000 --- a/.github/workflows/java_docker_test.yml +++ /dev/null @@ -1,65 +0,0 @@ -name: java_docker_test -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -permissions: read-all -jobs: - - build: - name: Java Docker Test - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - 'docker/**' - - 'java/**' - - '.github/workflows/java_docker_test.yml' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Run tests which require docker - 1 - if: steps.changes.outputs.end_to_end == 'true' - run: | - go run test.go -docker=true --follow -shard java diff --git a/.github/workflows/local_example.yml b/.github/workflows/local_example.yml index fb9e664c7a0..99badad812d 100644 --- a/.github/workflows/local_example.yml +++ b/.github/workflows/local_example.yml @@ -8,14 +8,19 @@ on: pull_request: branches: '**' permissions: read-all + +env: + BOOTSTRAP_VERSION: "ci" + BOOTSTRAP_FLAVOR: "mysql84" + jobs: build: name: Local example using ${{ matrix.topo }} on Ubuntu - runs-on: ubuntu-latest-xl + runs-on: ${{ github.repository == 'vitessio/vitess' && 'gh-hosted-runners-16cores-1-24.04' || 'ubuntu-24.04' }} strategy: matrix: - topo: [consul,etcd,zk2] + topo: [etcd,zk2] steps: - name: Skip CI @@ -51,11 +56,16 @@ jobs: - 'examples/**' - '.github/workflows/local_example.yml' + - name: Build bootstrap images + if: steps.changes.outputs.examples == 'true' + uses: ./.github/actions/build-bootstrap + - name: Set up Go if: steps.changes.outputs.examples == 'true' uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod + cache: ${{ (github.base_ref == 'main' || (github.base_ref == '' && github.ref_name == 'main')) && 'true' || 'false' }} - name: Tune the OS if: steps.changes.outputs.examples == 'true' @@ -84,4 +94,13 @@ jobs: if [ "${{matrix.os}}" = "macos-latest" ]; then export PATH="/usr/local/opt/mysql@5.7/bin:$PATH" fi - go run test.go -print-log -follow -retry=1 local_example + go run test.go -print-log -follow -pull=false -flavor=${{ env.BOOTSTRAP_FLAVOR }} -bootstrap-version=${{ env.BOOTSTRAP_VERSION }} local_example + + consul: + name: Local example using consul on Ubuntu + runs-on: ubuntu-latest + steps: + - name: Consul test currently broken + run: | + echo "Consul test is currently broken - this job exists to satisfy the required check" + exit 0 diff --git a/.github/workflows/region_example.yml b/.github/workflows/region_example.yml index 512c54da8f0..1a6cf952b75 100644 --- a/.github/workflows/region_example.yml +++ b/.github/workflows/region_example.yml @@ -8,11 +8,16 @@ on: pull_request: branches: '**' permissions: read-all + +env: + BOOTSTRAP_VERSION: "ci" + BOOTSTRAP_FLAVOR: "mysql84" + jobs: build: name: Region Sharding example using ${{ matrix.topo }} on Ubuntu - runs-on: ubuntu-latest-xl + runs-on: ${{ github.repository == 'vitessio/vitess' && 'gh-hosted-runners-16cores-1-24.04' || 'ubuntu-24.04' }} strategy: matrix: topo: [etcd] @@ -51,11 +56,16 @@ jobs: - 'examples/**' - '.github/workflows/region_example.yml' + - name: Build bootstrap images + if: steps.changes.outputs.examples == 'true' + uses: ./.github/actions/build-bootstrap + - name: Set up Go if: steps.changes.outputs.examples == 'true' uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod + cache: ${{ (github.base_ref == 'main' || (github.base_ref == '' && github.ref_name == 'main')) && 'true' || 'false' }} - name: Tune the OS if: steps.changes.outputs.examples == 'true' @@ -84,4 +94,4 @@ jobs: if [ "${{matrix.os}}" = "macos-latest" ]; then export PATH="/usr/local/opt/mysql@5.7/bin:$PATH" fi - go run test.go -print-log -follow -retry=1 region_example + go run test.go -print-log -follow -pull=false -flavor=${{ env.BOOTSTRAP_FLAVOR }} -bootstrap-version=${{ env.BOOTSTRAP_VERSION }} region_example diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index de90706da27..b2cd979861d 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -26,12 +26,12 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@v4 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0 + uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 with: results_file: results.sarif results_format: sarif @@ -53,7 +53,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: SARIF file path: results.sarif @@ -62,6 +62,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5 + uses: github/codeql-action/upload-sarif@4bdb89f48054571735e3792627da6195c57459e2 # v3.28.18 with: sarif_file: results.sarif diff --git a/.github/workflows/static_checks_etc.yml b/.github/workflows/static_checks_etc.yml index 7ae73965651..e171c3078ba 100644 --- a/.github/workflows/static_checks_etc.yml +++ b/.github/workflows/static_checks_etc.yml @@ -30,7 +30,7 @@ jobs: persist-credentials: 'false' - name: Run FOSSA scan and upload build data - uses: fossa-contrib/fossa-action@v3 + uses: fossa-contrib/fossa-action@3d2ef181b1820d6dcd1972f86a767d18167fa19b # v3.0.1 with: # This is a push-only API token: https://github.com/fossa-contrib/fossa-action#push-only-api-token fossa-api-key: f62c11ef0c249fef239947f01279aa0f @@ -121,6 +121,7 @@ jobs: uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod + cache: ${{ (github.base_ref == 'main' || (github.base_ref == '' && github.ref_name == 'main')) && 'true' || 'false' }} - name: Tune the OS if: steps.changes.outputs.go_files == 'true' @@ -218,7 +219,7 @@ jobs: - name: Setup Node if: steps.changes.outputs.proto_changes == 'true' - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 with: # make proto requires newer node than the pre-installed one node-version: '22.13.1' @@ -248,16 +249,4 @@ jobs: echo "" exit 1 - - name: Check make generate_ci_workflows - run: | - set -e - make generate_ci_workflows - output=$(git status -s) - if [ -z "${output}" ]; then - exit 0 - fi - echo 'Please run `make generate_ci_workflows`, commit and push again.' - echo 'Running `make generate_ci_workflows` on CI yields the following changes:' - echo "$output" - echo "" - exit 1 + diff --git a/.github/workflows/unit_race.yml b/.github/workflows/unit_race.yml deleted file mode 100644 index 8e6f608a7e3..00000000000 --- a/.github/workflows/unit_race.yml +++ /dev/null @@ -1,143 +0,0 @@ -name: unit_race -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'unit_race') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - - build: - name: Unit Test (Race) - runs-on: ubuntu-latest-xl - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - unit_tests: - - 'test/config.json' - - 'go/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/unit_race.yml' - - - name: Set up Go - if: steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.unit_tests == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.unit_tests == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.unit_tests == 'true' - run: | - export DEBIAN_FRONTEND="noninteractive" - sudo apt-get -qq update - - sudo apt-get -qq install -y make unzip g++ curl git wget ant openjdk-11-jdk - - mkdir -p dist bin - curl --max-time 10 --retry 3 --retry-max-time 45 -s -L https://github.com/coreos/etcd/releases/download/v3.5.25/etcd-v3.5.25-linux-amd64.tar.gz | tar -zxC dist - mv dist/etcd-v3.5.25-linux-amd64/{etcd,etcdctl} bin/ - - go mod download - go install golang.org/x/tools/cmd/goimports@latest - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Run make tools - if: steps.changes.outputs.unit_tests == 'true' - run: | - make tools - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.unit_tests == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: unit_race - if: steps.changes.outputs.unit_tests == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - export NOVTADMINBUILD=1 - export VTEVALENGINETEST="0" - - make unit_test_race | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.unit_tests == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.unit_tests == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.unit_tests == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/unit_race_evalengine.yml b/.github/workflows/unit_race_evalengine.yml deleted file mode 100644 index 290069ff869..00000000000 --- a/.github/workflows/unit_race_evalengine.yml +++ /dev/null @@ -1,143 +0,0 @@ -name: unit_race_evalengine -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'unit_race_evalengine') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - - build: - name: Unit Test (Evalengine_Race) - runs-on: ubuntu-latest-xl - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - unit_tests: - - 'test/config.json' - - 'go/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/unit_race_evalengine.yml' - - - name: Set up Go - if: steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.unit_tests == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.unit_tests == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.unit_tests == 'true' - run: | - export DEBIAN_FRONTEND="noninteractive" - sudo apt-get -qq update - - sudo apt-get -qq install -y make unzip g++ curl git wget ant openjdk-11-jdk - - mkdir -p dist bin - curl --max-time 10 --retry 3 --retry-max-time 45 -s -L https://github.com/coreos/etcd/releases/download/v3.5.25/etcd-v3.5.25-linux-amd64.tar.gz | tar -zxC dist - mv dist/etcd-v3.5.25-linux-amd64/{etcd,etcdctl} bin/ - - go mod download - go install golang.org/x/tools/cmd/goimports@latest - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Run make tools - if: steps.changes.outputs.unit_tests == 'true' - run: | - make tools - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.unit_tests == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: unit_race_evalengine - if: steps.changes.outputs.unit_tests == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - export NOVTADMINBUILD=1 - export VTEVALENGINETEST="1" - - make unit_test_race | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.unit_tests == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.unit_tests == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.unit_tests == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/unit_test.yml b/.github/workflows/unit_test.yml new file mode 100644 index 00000000000..f799f906b85 --- /dev/null +++ b/.github/workflows/unit_test.yml @@ -0,0 +1,195 @@ +name: Unit Test + +on: + push: + branches: + - "main" + - "release-[0-9]+.[0-9]" + tags: "**" + pull_request: + branches: "**" + +concurrency: + group: format('{0}-{1}', ${{ github.ref }}, 'Unit Test') + cancel-in-progress: true + +permissions: read-all + +env: + LAUNCHABLE_ORGANIZATION: "vitess" + LAUNCHABLE_WORKSPACE: "vitess-app" + GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" + +jobs: + test: + timeout-minutes: ${{ matrix.race && 45 || 30 }} + strategy: + fail-fast: false + matrix: + include: + # mysql57 tests + - platform: mysql57 + evalengine: "0" + flavor: mysql-5.7 + + - platform: mysql57 + evalengine: "1" + flavor: mysql-5.7 + + # mysql80 tests + - platform: mysql80 + evalengine: "0" + flavor: mysql-8.0 + + - platform: mysql80 + evalengine: "1" + flavor: mysql-8.0 + + # mysql84 tests + - platform: mysql84 + evalengine: "0" + flavor: mysql-8.4 + + - platform: mysql84 + evalengine: "1" + flavor: mysql-8.4 + + # Race tests (mysql80 only) + - platform: mysql80 + evalengine: "0" + flavor: mysql-8.0 + race: true + + - platform: mysql80 + evalengine: "1" + flavor: mysql-8.0 + race: true + + name: "Unit Test (${{ matrix.race && (matrix.evalengine == '1' && 'Evalengine_' || '') || (matrix.evalengine == '1' && 'evalengine_' || '') }}${{ matrix.race && 'Race' || matrix.platform }})" + runs-on: ${{ github.repository == 'vitessio/vitess' && matrix.race && 'gh-hosted-runners-16cores-1-24.04' || 'ubuntu-24.04' }} + + steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 + with: + egress-policy: audit + + - name: Skip CI + run: | + if [[ "${{ contains(github.event.pull_request.labels.*.name, 'Skip CI') }}" == "true" ]]; then + echo "skipping CI due to the 'Skip CI' label" + exit 1 + fi + + - name: Check out code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: "false" + + - name: Check for changes in relevant files + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + id: changes + with: + token: "" + filters: | + unit_tests: + - 'test/config.json' + - 'go/**' + - 'test.go' + - 'Makefile' + - 'build.env' + - 'go.sum' + - 'go.mod' + - 'proto/*.proto' + - 'tools/**' + - 'config/**' + - 'bootstrap.sh' + - '.github/workflows/unit_test.yml' + + - name: Set up Go + if: steps.changes.outputs.unit_tests == 'true' + uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + with: + go-version-file: go.mod + cache: ${{ (github.base_ref == 'main' || (github.base_ref == '' && github.ref_name == 'main')) && 'true' || 'false' }} + + - name: Set up python + if: steps.changes.outputs.unit_tests == 'true' + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + + - name: Tune the OS + if: steps.changes.outputs.unit_tests == 'true' + uses: ./.github/actions/tune-os + + - name: Setup MySQL + if: steps.changes.outputs.unit_tests == 'true' + uses: ./.github/actions/setup-mysql + with: + flavor: ${{ matrix.flavor }} + + - name: Get dependencies + if: steps.changes.outputs.unit_tests == 'true' + run: | + export DEBIAN_FRONTEND="noninteractive" + sudo apt-get install -y make unzip g++ curl git wget ant openjdk-11-jdk + + mkdir -p dist bin + curl --max-time 10 --retry 3 --retry-max-time 45 -s -L https://github.com/coreos/etcd/releases/download/v3.5.25/etcd-v3.5.25-linux-amd64.tar.gz | tar -zxC dist + mv dist/etcd-v3.5.25-linux-amd64/{etcd,etcdctl} bin/ + + go mod download + go install golang.org/x/tools/cmd/goimports@v0.39.0 + + - name: Run make tools + if: steps.changes.outputs.unit_tests == 'true' + run: | + make tools + + - name: Setup launchable dependencies + if: | + github.event_name == 'pull_request' && + github.event.pull_request.draft == false && + steps.changes.outputs.unit_tests == 'true' && + github.base_ref == 'main' + run: | + pip3 install --user launchable~=1.0 > /dev/null + launchable verify || true + launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . + + - name: Run test + if: steps.changes.outputs.unit_tests == 'true' + run: | + set -exo pipefail + + export VTDATAROOT="/tmp/" + export NOVTADMINBUILD=1 + export VT_GO_PARALLEL_VALUE=$(nproc) + export VTEVALENGINETEST="${{ matrix.evalengine }}" + export CI_DB_PLATFORM="${{ matrix.platform }}" + + JUNIT_OUTPUT=report.xml JSON_OUTPUT=report.json make ${{ matrix.race && 'unit_test_race' || 'unit_test' }} + + - name: Record test results in launchable + if: | + github.event_name == 'pull_request' && + github.event.pull_request.draft == false && + steps.changes.outputs.unit_tests == 'true' && + github.base_ref == 'main' && + !cancelled() + run: | + launchable record tests --build "$GITHUB_RUN_ID" go-test . || true + + - name: Test Summary + if: steps.changes.outputs.unit_tests == 'true' && failure() + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 + with: + paths: "report.xml" + show: "fail" + + - name: Slowest Tests + if: steps.changes.outputs.unit_tests == 'true' && !cancelled() + run: | + echo '## Slowest Tests' >> "$GITHUB_STEP_SUMMARY" + echo '```' >> "$GITHUB_STEP_SUMMARY" + go tool gotestsum tool slowest --num 20 --jsonfile report.json | tee -a "$GITHUB_STEP_SUMMARY" + echo '```' >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/unit_test_evalengine_mysql57.yml b/.github/workflows/unit_test_evalengine_mysql57.yml deleted file mode 100644 index 021ee59839d..00000000000 --- a/.github/workflows/unit_test_evalengine_mysql57.yml +++ /dev/null @@ -1,148 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Unit Test (evalengine_mysql57) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Unit Test (evalengine_mysql57)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - test: - name: Unit Test (evalengine_mysql57) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - unit_tests: - - 'test/config.json' - - 'go/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/unit_test_evalengine_mysql57.yml' - - - name: Set up Go - if: steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.unit_tests == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.unit_tests == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-5.7 - - - name: Get dependencies - if: steps.changes.outputs.unit_tests == 'true' - run: | - export DEBIAN_FRONTEND="noninteractive" - sudo apt-get install -y make unzip g++ curl git wget ant openjdk-11-jdk - - mkdir -p dist bin - curl --max-time 10 --retry 3 --retry-max-time 45 -s -L https://github.com/coreos/etcd/releases/download/v3.5.25/etcd-v3.5.25-linux-amd64.tar.gz | tar -zxC dist - mv dist/etcd-v3.5.25-linux-amd64/{etcd,etcdctl} bin/ - - go mod download - go install golang.org/x/tools/cmd/goimports@latest - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Run make tools - if: steps.changes.outputs.unit_tests == 'true' - run: | - make tools - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.unit_tests == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run test - if: steps.changes.outputs.unit_tests == 'true' - timeout-minutes: 30 - run: | - set -exo pipefail - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - - export NOVTADMINBUILD=1 - export VTEVALENGINETEST="1" - # We sometimes need to alter the behavior based on the platform we're - # testing, e.g. MySQL 5.7 vs 8.0. - export CI_DB_PLATFORM="mysql57" - - make unit_test | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.unit_tests == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.unit_tests == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.unit_tests == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/unit_test_evalengine_mysql80.yml b/.github/workflows/unit_test_evalengine_mysql80.yml deleted file mode 100644 index e73e593975f..00000000000 --- a/.github/workflows/unit_test_evalengine_mysql80.yml +++ /dev/null @@ -1,148 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Unit Test (evalengine_mysql80) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Unit Test (evalengine_mysql80)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - test: - name: Unit Test (evalengine_mysql80) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - unit_tests: - - 'test/config.json' - - 'go/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/unit_test_evalengine_mysql80.yml' - - - name: Set up Go - if: steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.unit_tests == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.unit_tests == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.unit_tests == 'true' - run: | - export DEBIAN_FRONTEND="noninteractive" - sudo apt-get install -y make unzip g++ curl git wget ant openjdk-11-jdk - - mkdir -p dist bin - curl --max-time 10 --retry 3 --retry-max-time 45 -s -L https://github.com/coreos/etcd/releases/download/v3.5.25/etcd-v3.5.25-linux-amd64.tar.gz | tar -zxC dist - mv dist/etcd-v3.5.25-linux-amd64/{etcd,etcdctl} bin/ - - go mod download - go install golang.org/x/tools/cmd/goimports@latest - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Run make tools - if: steps.changes.outputs.unit_tests == 'true' - run: | - make tools - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.unit_tests == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run test - if: steps.changes.outputs.unit_tests == 'true' - timeout-minutes: 30 - run: | - set -exo pipefail - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - - export NOVTADMINBUILD=1 - export VTEVALENGINETEST="1" - # We sometimes need to alter the behavior based on the platform we're - # testing, e.g. MySQL 5.7 vs 8.0. - export CI_DB_PLATFORM="mysql80" - - make unit_test | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.unit_tests == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.unit_tests == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.unit_tests == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/unit_test_evalengine_mysql84.yml b/.github/workflows/unit_test_evalengine_mysql84.yml deleted file mode 100644 index fd1dca75ef9..00000000000 --- a/.github/workflows/unit_test_evalengine_mysql84.yml +++ /dev/null @@ -1,148 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Unit Test (evalengine_mysql84) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Unit Test (evalengine_mysql84)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - test: - name: Unit Test (evalengine_mysql84) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - unit_tests: - - 'test/config.json' - - 'go/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/unit_test_evalengine_mysql84.yml' - - - name: Set up Go - if: steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.unit_tests == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.unit_tests == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.4 - - - name: Get dependencies - if: steps.changes.outputs.unit_tests == 'true' - run: | - export DEBIAN_FRONTEND="noninteractive" - sudo apt-get install -y make unzip g++ curl git wget ant openjdk-11-jdk - - mkdir -p dist bin - curl --max-time 10 --retry 3 --retry-max-time 45 -s -L https://github.com/coreos/etcd/releases/download/v3.5.25/etcd-v3.5.25-linux-amd64.tar.gz | tar -zxC dist - mv dist/etcd-v3.5.25-linux-amd64/{etcd,etcdctl} bin/ - - go mod download - go install golang.org/x/tools/cmd/goimports@latest - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Run make tools - if: steps.changes.outputs.unit_tests == 'true' - run: | - make tools - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.unit_tests == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run test - if: steps.changes.outputs.unit_tests == 'true' - timeout-minutes: 30 - run: | - set -exo pipefail - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - - export NOVTADMINBUILD=1 - export VTEVALENGINETEST="1" - # We sometimes need to alter the behavior based on the platform we're - # testing, e.g. MySQL 5.7 vs 8.0. - export CI_DB_PLATFORM="mysql84" - - make unit_test | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.unit_tests == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.unit_tests == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.unit_tests == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/unit_test_mysql57.yml b/.github/workflows/unit_test_mysql57.yml deleted file mode 100644 index d4480b4b441..00000000000 --- a/.github/workflows/unit_test_mysql57.yml +++ /dev/null @@ -1,148 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Unit Test (mysql57) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Unit Test (mysql57)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - test: - name: Unit Test (mysql57) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - unit_tests: - - 'test/config.json' - - 'go/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/unit_test_mysql57.yml' - - - name: Set up Go - if: steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.unit_tests == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.unit_tests == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-5.7 - - - name: Get dependencies - if: steps.changes.outputs.unit_tests == 'true' - run: | - export DEBIAN_FRONTEND="noninteractive" - sudo apt-get install -y make unzip g++ curl git wget ant openjdk-11-jdk - - mkdir -p dist bin - curl --max-time 10 --retry 3 --retry-max-time 45 -s -L https://github.com/coreos/etcd/releases/download/v3.5.25/etcd-v3.5.25-linux-amd64.tar.gz | tar -zxC dist - mv dist/etcd-v3.5.25-linux-amd64/{etcd,etcdctl} bin/ - - go mod download - go install golang.org/x/tools/cmd/goimports@latest - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Run make tools - if: steps.changes.outputs.unit_tests == 'true' - run: | - make tools - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.unit_tests == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run test - if: steps.changes.outputs.unit_tests == 'true' - timeout-minutes: 30 - run: | - set -exo pipefail - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - - export NOVTADMINBUILD=1 - export VTEVALENGINETEST="0" - # We sometimes need to alter the behavior based on the platform we're - # testing, e.g. MySQL 5.7 vs 8.0. - export CI_DB_PLATFORM="mysql57" - - make unit_test | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.unit_tests == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.unit_tests == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.unit_tests == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/unit_test_mysql80.yml b/.github/workflows/unit_test_mysql80.yml deleted file mode 100644 index 12c635976f7..00000000000 --- a/.github/workflows/unit_test_mysql80.yml +++ /dev/null @@ -1,148 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Unit Test (mysql80) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Unit Test (mysql80)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - test: - name: Unit Test (mysql80) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - unit_tests: - - 'test/config.json' - - 'go/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/unit_test_mysql80.yml' - - - name: Set up Go - if: steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.unit_tests == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.unit_tests == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.unit_tests == 'true' - run: | - export DEBIAN_FRONTEND="noninteractive" - sudo apt-get install -y make unzip g++ curl git wget ant openjdk-11-jdk - - mkdir -p dist bin - curl --max-time 10 --retry 3 --retry-max-time 45 -s -L https://github.com/coreos/etcd/releases/download/v3.5.25/etcd-v3.5.25-linux-amd64.tar.gz | tar -zxC dist - mv dist/etcd-v3.5.25-linux-amd64/{etcd,etcdctl} bin/ - - go mod download - go install golang.org/x/tools/cmd/goimports@latest - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Run make tools - if: steps.changes.outputs.unit_tests == 'true' - run: | - make tools - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.unit_tests == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run test - if: steps.changes.outputs.unit_tests == 'true' - timeout-minutes: 30 - run: | - set -exo pipefail - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - - export NOVTADMINBUILD=1 - export VTEVALENGINETEST="0" - # We sometimes need to alter the behavior based on the platform we're - # testing, e.g. MySQL 5.7 vs 8.0. - export CI_DB_PLATFORM="mysql80" - - make unit_test | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.unit_tests == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.unit_tests == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.unit_tests == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/unit_test_mysql84.yml b/.github/workflows/unit_test_mysql84.yml deleted file mode 100644 index 69c6550b38d..00000000000 --- a/.github/workflows/unit_test_mysql84.yml +++ /dev/null @@ -1,148 +0,0 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - -name: Unit Test (mysql84) -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Unit Test (mysql84)') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{ github.event.pull_request.head.sha }}" - -jobs: - test: - name: Unit Test (mysql84) - runs-on: ubuntu-24.04 - - steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - unit_tests: - - 'test/config.json' - - 'go/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/unit_test_mysql84.yml' - - - name: Set up Go - if: steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - - - name: Set up python - if: steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.unit_tests == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.unit_tests == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.4 - - - name: Get dependencies - if: steps.changes.outputs.unit_tests == 'true' - run: | - export DEBIAN_FRONTEND="noninteractive" - sudo apt-get install -y make unzip g++ curl git wget ant openjdk-11-jdk - - mkdir -p dist bin - curl --max-time 10 --retry 3 --retry-max-time 45 -s -L https://github.com/coreos/etcd/releases/download/v3.5.25/etcd-v3.5.25-linux-amd64.tar.gz | tar -zxC dist - mv dist/etcd-v3.5.25-linux-amd64/{etcd,etcdctl} bin/ - - go mod download - go install golang.org/x/tools/cmd/goimports@latest - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Run make tools - if: steps.changes.outputs.unit_tests == 'true' - run: | - make tools - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.unit_tests == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run test - if: steps.changes.outputs.unit_tests == 'true' - timeout-minutes: 30 - run: | - set -exo pipefail - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - - export NOVTADMINBUILD=1 - export VTEVALENGINETEST="0" - # We sometimes need to alter the behavior based on the platform we're - # testing, e.g. MySQL 5.7 vs 8.0. - export CI_DB_PLATFORM="mysql84" - - make unit_test | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.unit_tests == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.unit_tests == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.unit_tests == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/.github/workflows/update_golang_dependencies.yml b/.github/workflows/update_golang_dependencies.yml index fc8def557af..17048750b88 100644 --- a/.github/workflows/update_golang_dependencies.yml +++ b/.github/workflows/update_golang_dependencies.yml @@ -26,6 +26,7 @@ jobs: uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod + cache: ${{ (github.base_ref == 'main' || (github.base_ref == '' && github.ref_name == 'main')) && 'true' || 'false' }} - name: Upgrade the Golang Dependencies id: detect-and-update @@ -40,7 +41,7 @@ jobs: go mod tidy - name: Create Pull Request - uses: peter-evans/create-pull-request@v7 + uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0 with: token: ${{ secrets.CREATE_PR_VITESS_BOT }} branch: "upgrade-go-deps-on-main" diff --git a/.github/workflows/update_golang_version.yml b/.github/workflows/update_golang_version.yml index 686c1d85e9d..99436915d24 100644 --- a/.github/workflows/update_golang_version.yml +++ b/.github/workflows/update_golang_version.yml @@ -28,10 +28,12 @@ jobs: uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod + cache: ${{ (github.base_ref == 'main' || (github.base_ref == '' && github.ref_name == 'main')) && 'true' || 'false' }} - name: Detect new version and update codebase env: GH_TOKEN: ${{ github.token }} + GOTOOLCHAIN: auto id: detect-and-update run: | old_go_version=$(go run ./go/tools/go-upgrade/go-upgrade.go get go-version) @@ -56,7 +58,7 @@ jobs: echo "bootstrap-version=${bootstrap_version}" >> $GITHUB_OUTPUT # Check if the PR already exists, if it does then do not create new PR. - gh pr list -S "is:open [${{ matrix.branch }}] Upgrade the Golang version to go${go_version}" > out.txt 2>&1 | true + gh pr list -S 'is:open "[${{ matrix.branch }}] Upgrade the Golang version to go${go_version}"' > out.txt 2>&1 | true if [ -s out.txt ]; then rm -f out.txt exit 0 @@ -66,7 +68,7 @@ jobs: - name: Create Pull Request if: steps.detect-and-update.outputs.create-pr == 'true' - uses: peter-evans/create-pull-request@v7 + uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0 with: token: ${{ secrets.CREATE_PR_VITESS_BOT }} branch: "upgrade-go-to-${{steps.detect-and-update.outputs.go-version}}-on-${{ matrix.branch }}" @@ -79,15 +81,10 @@ jobs: This Pull Request bumps the Golang version to `go${{steps.detect-and-update.outputs.go-version}}` and the bootstrap version to `${{steps.detect-and-update.outputs.bootstrap-version}}`. > Do not trust the bot blindly. A thorough code review must be done to ensure all the files have been correctly modified. - - There are a few manual steps remaining: - - [ ] Make sure you update the Golang version used in the previous and next release branches for the Upgrade/Downgrade tests. - - [ ] Build and Push the bootstrap images to Docker Hub, the bot cannot handle that. cc @vitessio/release base: ${{ matrix.branch }} labels: | - Skip CI go Benchmark me Component: General diff --git a/.github/workflows/upgrade_downgrade_test_backups_e2e.yml b/.github/workflows/upgrade_downgrade_test_backups_e2e.yml index ab6a56da965..13438491967 100644 --- a/.github/workflows/upgrade_downgrade_test_backups_e2e.yml +++ b/.github/workflows/upgrade_downgrade_test_backups_e2e.yml @@ -18,7 +18,7 @@ jobs: upgrade_downgrade_test_e2e: timeout-minutes: 60 name: Run Upgrade Downgrade Test - Backups - E2E - runs-on: ubuntu-latest-xl + runs-on: ${{ github.repository == 'vitessio/vitess' && 'gh-hosted-runners-16cores-1-24.04' || 'ubuntu-24.04' }} steps: - name: Skip CI @@ -88,9 +88,10 @@ jobs: sudo service etcd stop wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb - sudo apt-get install -y gnupg2 + sudo apt-get install -y gnupg2 lz4 sudo dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb - sudo percona-release enable-only tools + sudo percona-release enable tools + sudo percona-release setup pxb-80 sudo apt-get update sudo apt-get install -y percona-xtrabackup-80 diff --git a/.github/workflows/upgrade_downgrade_test_backups_e2e_next_release.yml b/.github/workflows/upgrade_downgrade_test_backups_e2e_next_release.yml index bdb40094a91..f7afda39cf8 100644 --- a/.github/workflows/upgrade_downgrade_test_backups_e2e_next_release.yml +++ b/.github/workflows/upgrade_downgrade_test_backups_e2e_next_release.yml @@ -19,7 +19,7 @@ jobs: upgrade_downgrade_test_e2e: timeout-minutes: 60 name: Run Upgrade Downgrade Test - Backups - E2E - Next Release - runs-on: ubuntu-latest-xl + runs-on: ${{ github.repository == 'vitessio/vitess' && 'gh-hosted-runners-16cores-1-24.04' || 'ubuntu-24.04' }} steps: - name: Skip CI @@ -90,9 +90,10 @@ jobs: sudo service etcd stop wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb - sudo apt-get install -y gnupg2 + sudo apt-get install -y gnupg2 lz4 sudo dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb - sudo percona-release enable-only tools + sudo percona-release enable tools + sudo percona-release setup pxb-80 sudo apt-get update sudo apt-get install -y percona-xtrabackup-80 diff --git a/.github/workflows/upgrade_downgrade_test_backups_manual.yml b/.github/workflows/upgrade_downgrade_test_backups_manual.yml index 14c8897a97a..20240889afe 100644 --- a/.github/workflows/upgrade_downgrade_test_backups_manual.yml +++ b/.github/workflows/upgrade_downgrade_test_backups_manual.yml @@ -20,7 +20,7 @@ jobs: upgrade_downgrade_test_manual: timeout-minutes: 40 name: Run Upgrade Downgrade Test - Backups - Manual - runs-on: ubuntu-latest-xl + runs-on: ${{ github.repository == 'vitessio/vitess' && 'gh-hosted-runners-16cores-1-24.04' || 'ubuntu-24.04' }} steps: - name: Skip CI @@ -93,9 +93,10 @@ jobs: sudo service etcd stop wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb - sudo apt-get install -y gnupg2 + sudo apt-get install -y gnupg2 lz4 sudo dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb - sudo percona-release enable-only tools + sudo percona-release enable tools + sudo percona-release setup pxb-80 sudo apt-get update sudo apt-get install -y percona-xtrabackup-80 diff --git a/.github/workflows/upgrade_downgrade_test_backups_manual_next_release.yml b/.github/workflows/upgrade_downgrade_test_backups_manual_next_release.yml index 810da7ac5fd..ef92531e42c 100644 --- a/.github/workflows/upgrade_downgrade_test_backups_manual_next_release.yml +++ b/.github/workflows/upgrade_downgrade_test_backups_manual_next_release.yml @@ -20,7 +20,7 @@ jobs: upgrade_downgrade_test_manual: timeout-minutes: 40 name: Run Upgrade Downgrade Test - Backups - Manual - Next Release - runs-on: ubuntu-latest-xl + runs-on: ${{ github.repository == 'vitessio/vitess' && 'gh-hosted-runners-16cores-1-24.04' || 'ubuntu-24.04' }} steps: - name: Skip CI @@ -94,9 +94,10 @@ jobs: sudo service etcd stop wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb - sudo apt-get install -y gnupg2 + sudo apt-get install -y gnupg2 lz4 sudo dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb - sudo percona-release enable-only tools + sudo percona-release enable tools + sudo percona-release setup pxb-80 sudo apt-get update sudo apt-get install -y percona-xtrabackup-80 diff --git a/.github/workflows/upgrade_downgrade_test_onlineddl_flow.yml b/.github/workflows/upgrade_downgrade_test_onlineddl_flow.yml index f82b9259c43..ceee6513309 100644 --- a/.github/workflows/upgrade_downgrade_test_onlineddl_flow.yml +++ b/.github/workflows/upgrade_downgrade_test_onlineddl_flow.yml @@ -22,7 +22,7 @@ jobs: upgrade_downgrade_test: timeout-minutes: 60 name: Run Upgrade Downgrade Test - Online DDL flow - runs-on: ubuntu-latest-xl + runs-on: ${{ github.repository == 'vitessio/vitess' && 'gh-hosted-runners-16cores-1-24.04' || 'ubuntu-24.04' }} steps: - name: Skip CI diff --git a/.github/workflows/upgrade_downgrade_test_query_serving_queries.yml b/.github/workflows/upgrade_downgrade_test_query_serving_queries.yml index e85a49026cc..1f7b9af1ba8 100644 --- a/.github/workflows/upgrade_downgrade_test_query_serving_queries.yml +++ b/.github/workflows/upgrade_downgrade_test_query_serving_queries.yml @@ -22,7 +22,7 @@ jobs: upgrade_downgrade_test: timeout-minutes: 60 name: Run Upgrade Downgrade Test - Query Serving (Queries) - runs-on: ubuntu-latest-xl + runs-on: ${{ github.repository == 'vitessio/vitess' && 'gh-hosted-runners-16cores-1-24.04' || 'ubuntu-24.04' }} steps: - name: Skip CI diff --git a/.github/workflows/upgrade_downgrade_test_query_serving_queries_2.yml b/.github/workflows/upgrade_downgrade_test_query_serving_queries_2.yml index 72d5331e01a..a46719fdc84 100644 --- a/.github/workflows/upgrade_downgrade_test_query_serving_queries_2.yml +++ b/.github/workflows/upgrade_downgrade_test_query_serving_queries_2.yml @@ -21,7 +21,7 @@ jobs: upgrade_downgrade_test: timeout-minutes: 60 name: Run Upgrade Downgrade Test - Query Serving (Queries - 2) - runs-on: ubuntu-latest-xl + runs-on: ${{ github.repository == 'vitessio/vitess' && 'gh-hosted-runners-16cores-1-24.04' || 'ubuntu-24.04' }} steps: - name: Skip CI diff --git a/.github/workflows/upgrade_downgrade_test_query_serving_queries_2_next_release.yml b/.github/workflows/upgrade_downgrade_test_query_serving_queries_2_next_release.yml index 9e7c5657334..936156f4340 100644 --- a/.github/workflows/upgrade_downgrade_test_query_serving_queries_2_next_release.yml +++ b/.github/workflows/upgrade_downgrade_test_query_serving_queries_2_next_release.yml @@ -22,7 +22,7 @@ jobs: upgrade_downgrade_test: timeout-minutes: 60 name: Run Upgrade Downgrade Test - Query Serving (Queries - 2) Next Release - runs-on: ubuntu-latest-xl + runs-on: ${{ github.repository == 'vitessio/vitess' && 'gh-hosted-runners-16cores-1-24.04' || 'ubuntu-24.04' }} steps: - name: Skip CI diff --git a/.github/workflows/upgrade_downgrade_test_query_serving_queries_next_release.yml b/.github/workflows/upgrade_downgrade_test_query_serving_queries_next_release.yml index c64cee5b914..1849f1c0e4c 100644 --- a/.github/workflows/upgrade_downgrade_test_query_serving_queries_next_release.yml +++ b/.github/workflows/upgrade_downgrade_test_query_serving_queries_next_release.yml @@ -22,7 +22,7 @@ jobs: upgrade_downgrade_test: timeout-minutes: 60 name: Run Upgrade Downgrade Test - Query Serving (Queries) Next Release - runs-on: ubuntu-latest-xl + runs-on: ${{ github.repository == 'vitessio/vitess' && 'gh-hosted-runners-16cores-1-24.04' || 'ubuntu-24.04' }} steps: - name: Skip CI diff --git a/.github/workflows/upgrade_downgrade_test_query_serving_schema.yml b/.github/workflows/upgrade_downgrade_test_query_serving_schema.yml index 50f750d3179..a105a5d6a16 100644 --- a/.github/workflows/upgrade_downgrade_test_query_serving_schema.yml +++ b/.github/workflows/upgrade_downgrade_test_query_serving_schema.yml @@ -22,7 +22,7 @@ jobs: upgrade_downgrade_test: timeout-minutes: 60 name: Run Upgrade Downgrade Test - Query Serving (Schema) - runs-on: ubuntu-latest-xl + runs-on: ${{ github.repository == 'vitessio/vitess' && 'gh-hosted-runners-16cores-1-24.04' || 'ubuntu-24.04' }} steps: - name: Skip CI diff --git a/.github/workflows/upgrade_downgrade_test_query_serving_schema_next_release.yml b/.github/workflows/upgrade_downgrade_test_query_serving_schema_next_release.yml index 76b5596f2c1..d8a28b21443 100644 --- a/.github/workflows/upgrade_downgrade_test_query_serving_schema_next_release.yml +++ b/.github/workflows/upgrade_downgrade_test_query_serving_schema_next_release.yml @@ -22,7 +22,7 @@ jobs: upgrade_downgrade_test: timeout-minutes: 60 name: Run Upgrade Downgrade Test - Query Serving (Schema) Next Release - runs-on: ubuntu-latest-xl + runs-on: ${{ github.repository == 'vitessio/vitess' && 'gh-hosted-runners-16cores-1-24.04' || 'ubuntu-24.04' }} steps: - name: Skip CI diff --git a/.github/workflows/upgrade_downgrade_test_reparent_new_vtctl.yml b/.github/workflows/upgrade_downgrade_test_reparent_new_vtctl.yml index 6fe2dbf3db8..f0cefbdb886 100644 --- a/.github/workflows/upgrade_downgrade_test_reparent_new_vtctl.yml +++ b/.github/workflows/upgrade_downgrade_test_reparent_new_vtctl.yml @@ -22,7 +22,7 @@ jobs: upgrade_downgrade_test: timeout-minutes: 60 name: Run Upgrade Downgrade Test - Reparent New Vtctl - runs-on: ubuntu-latest-xl + runs-on: ${{ github.repository == 'vitessio/vitess' && 'gh-hosted-runners-16cores-1-24.04' || 'ubuntu-24.04' }} steps: - name: Skip CI diff --git a/.github/workflows/upgrade_downgrade_test_reparent_new_vttablet.yml b/.github/workflows/upgrade_downgrade_test_reparent_new_vttablet.yml index 94bd9fa26d6..271556116d1 100644 --- a/.github/workflows/upgrade_downgrade_test_reparent_new_vttablet.yml +++ b/.github/workflows/upgrade_downgrade_test_reparent_new_vttablet.yml @@ -22,7 +22,7 @@ jobs: upgrade_downgrade_test: timeout-minutes: 60 name: Run Upgrade Downgrade Test - Reparent New VTTablet - runs-on: ubuntu-latest-xl + runs-on: ${{ github.repository == 'vitessio/vitess' && 'gh-hosted-runners-16cores-1-24.04' || 'ubuntu-24.04' }} steps: - name: Skip CI @@ -92,9 +92,10 @@ jobs: sudo service etcd stop wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb - sudo apt-get install -y gnupg2 + sudo apt-get install -y gnupg2 lz4 sudo dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb - sudo percona-release enable-only tools + sudo percona-release enable tools + sudo percona-release setup pxb-80 sudo apt-get update sudo apt-get install -y percona-xtrabackup-80 diff --git a/.github/workflows/upgrade_downgrade_test_reparent_old_vtctl.yml b/.github/workflows/upgrade_downgrade_test_reparent_old_vtctl.yml index e61cd907752..0f5548076f7 100644 --- a/.github/workflows/upgrade_downgrade_test_reparent_old_vtctl.yml +++ b/.github/workflows/upgrade_downgrade_test_reparent_old_vtctl.yml @@ -22,7 +22,7 @@ jobs: upgrade_downgrade_test: timeout-minutes: 60 name: Run Upgrade Downgrade Test - Reparent Old Vtctl - runs-on: ubuntu-latest-xl + runs-on: ${{ github.repository == 'vitessio/vitess' && 'gh-hosted-runners-16cores-1-24.04' || 'ubuntu-24.04' }} steps: - name: Skip CI diff --git a/.github/workflows/upgrade_downgrade_test_reparent_old_vttablet.yml b/.github/workflows/upgrade_downgrade_test_reparent_old_vttablet.yml index 0d49f056861..10b8f4b5765 100644 --- a/.github/workflows/upgrade_downgrade_test_reparent_old_vttablet.yml +++ b/.github/workflows/upgrade_downgrade_test_reparent_old_vttablet.yml @@ -22,7 +22,7 @@ jobs: upgrade_downgrade_test: timeout-minutes: 60 name: Run Upgrade Downgrade Test - Reparent Old VTTablet - runs-on: ubuntu-latest-xl + runs-on: ${{ github.repository == 'vitessio/vitess' && 'gh-hosted-runners-16cores-1-24.04' || 'ubuntu-24.04' }} steps: - name: Skip CI diff --git a/.github/workflows/upgrade_downgrade_test_semi_sync.yml b/.github/workflows/upgrade_downgrade_test_semi_sync.yml index ceb376cc0d6..1585e1cb64f 100644 --- a/.github/workflows/upgrade_downgrade_test_semi_sync.yml +++ b/.github/workflows/upgrade_downgrade_test_semi_sync.yml @@ -18,7 +18,7 @@ jobs: upgrade_downgrade_test_e2e: timeout-minutes: 60 name: Run Semi Sync Upgrade Downgrade Test - runs-on: ubuntu-latest-xl + runs-on: ${{ github.repository == 'vitessio/vitess' && 'gh-hosted-runners-16cores-1-24.04' || 'ubuntu-24.04' }} steps: - name: Skip CI @@ -89,9 +89,10 @@ jobs: sudo service etcd stop wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb - sudo apt-get install -y gnupg2 + sudo apt-get install -y gnupg2 lz4 sudo dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb - sudo percona-release enable-only tools + sudo percona-release enable tools + sudo percona-release setup pxb-80 sudo apt-get update sudo apt-get install -y percona-xtrabackup-80 diff --git a/.github/workflows/vitess_tester_vtgate.yml b/.github/workflows/vitess_tester_vtgate.yml index 74d22ac16ec..dc408eb156a 100644 --- a/.github/workflows/vitess_tester_vtgate.yml +++ b/.github/workflows/vitess_tester_vtgate.yml @@ -1,5 +1,3 @@ -# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" - name: Vitess Tester (vtgate) on: push: @@ -65,6 +63,7 @@ jobs: uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: go-version-file: go.mod + cache: ${{ (github.base_ref == 'main' || (github.base_ref == '' && github.ref_name == 'main')) && 'true' || 'false' }} - name: Set up python if: steps.changes.outputs.end_to_end == 'true' diff --git a/.github/workflows/vtadmin_web_build.yml b/.github/workflows/vtadmin_web_build.yml index 64cc4a454af..522535c2dde 100644 --- a/.github/workflows/vtadmin_web_build.yml +++ b/.github/workflows/vtadmin_web_build.yml @@ -37,7 +37,7 @@ jobs: - name: Tune the OS uses: ./.github/actions/tune-os - - uses: actions/setup-node@v4 + - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 with: # node-version should match package.json node-version: '22.13.1' diff --git a/.github/workflows/vtadmin_web_lint.yml b/.github/workflows/vtadmin_web_lint.yml index b46f36660c3..0ff53373f45 100644 --- a/.github/workflows/vtadmin_web_lint.yml +++ b/.github/workflows/vtadmin_web_lint.yml @@ -37,7 +37,7 @@ jobs: - name: Tune the OS uses: ./.github/actions/tune-os - - uses: actions/setup-node@v4 + - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 with: # node-version should match package.json node-version: '22.13.1' diff --git a/.github/workflows/vtadmin_web_unit_tests.yml b/.github/workflows/vtadmin_web_unit_tests.yml index 096634942e2..dfdd813118c 100644 --- a/.github/workflows/vtadmin_web_unit_tests.yml +++ b/.github/workflows/vtadmin_web_unit_tests.yml @@ -37,7 +37,7 @@ jobs: - name: Tune the OS uses: ./.github/actions/tune-os - - uses: actions/setup-node@v4 + - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 with: # node-version should match package.json node-version: '22.13.1' diff --git a/.github/workflows/vtop_example.yml b/.github/workflows/vtop_example.yml index feb347a886f..fec1f815e85 100644 --- a/.github/workflows/vtop_example.yml +++ b/.github/workflows/vtop_example.yml @@ -14,7 +14,7 @@ concurrency: jobs: build: name: VTop Example - runs-on: oracle-vm-8cpu-32gb-x86-64 + runs-on: ${{ github.repository == 'vitessio/vitess' && 'oracle-vm-8cpu-32gb-x86-64' || 'ubuntu-24.04' }} steps: - name: Skip CI diff --git a/.gitignore b/.gitignore index e8c441d3bd7..3a471a05d22 100644 --- a/.gitignore +++ b/.gitignore @@ -93,3 +93,5 @@ report # mise files .mise.toml /errors/ +go/flags/endtoend/count_flags.sh +/coverage.out diff --git a/Makefile b/Makefile index 1ddba949b1e..c666175b4b7 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ export REWRITER=go/vt/sqlparser/rewriter.go # Since we are not using this Makefile for compilation, limiting parallelism will not increase build time. .NOTPARALLEL: -.PHONY: all build install test clean unit_test unit_test_cover unit_test_race integration_test proto proto_banner site_test site_integration_test docker_bootstrap docker_test docker_unit_test java_test reshard_tests e2e_test e2e_test_race minimaltools tools generate_ci_workflows generate-flag-testdata +.PHONY: all build install test clean unit_test unit_test_cover unit_test_race integration_test proto proto_banner site_test site_integration_test docker_bootstrap docker_test docker_unit_test java_test reshard_tests e2e_test e2e_test_race minimaltools tools generate-flag-testdata all: build @@ -219,16 +219,10 @@ e2e_test: build # Run the code coverage tools, compute aggregate. unit_test_cover: build dependency_check demo - source build.env - go test $(VT_GO_PARALLEL) -count=1 -failfast -covermode=atomic -coverpkg=vitess.io/vitess/go/... -coverprofile=coverage.out ./go/... - # Handle go tool cover failures due to not handling `//line` directives, which - # the goyacc compiler adds to the generated parser in sql.go. See: - # https://github.com/golang/go/issues/41222 - sed -i'' -e '/^vitess.io\/vitess\/go\/vt\/sqlparser\/yaccpar/d' coverage.out - go tool $(VT_GO_PARALLEL) cover -html=coverage.out + source build.env && tools/run_codecov.sh $(COVERAGE_PACKAGES) unit_test_race: build dependency_check - tools/unit_test_race.sh + RACE=1 tools/unit_test_runner.sh e2e_test_race: build tools/e2e_test_race.sh @@ -286,7 +280,7 @@ $(PROTO_GO_OUTS): minimaltools install_protoc-gen-go proto/*.proto # This rule builds the bootstrap images for all flavors. DOCKER_IMAGES_FOR_TEST = mysql80 mysql84 percona80 DOCKER_IMAGES = common $(DOCKER_IMAGES_FOR_TEST) -BOOTSTRAP_VERSION=43.5 +BOOTSTRAP_VERSION=43.7 ensure_bootstrap_version: find docker/ -type f -exec sed -i "s/^\(ARG bootstrap_version\)=.*/\1=${BOOTSTRAP_VERSION}/" {} \; sed -i 's/\(^.*flag.String(\"bootstrap-version\",\) *\"[^\"]\+\"/\1 \"${BOOTSTRAP_VERSION}\"/' test.go @@ -387,12 +381,6 @@ vtadmin_authz_testgen: go generate ./go/vt/vtadmin/ go fmt ./go/vt/vtadmin/ -# Generate github CI actions workflow files for unit tests and cluster endtoend tests based on templates in the test/templates directory -# Needs to be called if the templates change or if a new test "shard" is created. We do not need to rebuild tests if only the test/config.json -# is changed by adding a new test to an existing shard. Any new or modified files need to be committed into git -generate_ci_workflows: - cd test && go run ci_workflow_gen.go && cd .. - generate-flag-testdata: ./tools/generate_flag_testdata.sh diff --git a/build.env b/build.env index 140c27f5cb9..fe66cd0f23e 100755 --- a/build.env +++ b/build.env @@ -17,7 +17,7 @@ source ./tools/shell_functions.inc go version >/dev/null 2>&1 || fail "Go is not installed or is not in \$PATH. See https://vitess.io/contributing/build-from-source for install instructions." -goversion_min 1.24.10 || echo "Go version reported: `go version`. Version 1.24.10+ recommended. See https://vitess.io/contributing/build-from-source for install instructions." +goversion_min 1.24.13 || echo "Go version reported: `go version`. Version 1.24.13+ recommended. See https://vitess.io/contributing/build-from-source for install instructions." mkdir -p dist mkdir -p bin diff --git a/changelog/22.0/22.0.3/changelog.md b/changelog/22.0/22.0.3/changelog.md new file mode 100644 index 00000000000..dd072034736 --- /dev/null +++ b/changelog/22.0/22.0.3/changelog.md @@ -0,0 +1,74 @@ +# Changelog of Vitess v22.0.3 + +### Bug fixes +#### Build/CI + * [release-22.0] Fix major upgrade logic in go upgrade tool [#19211](https://github.com/vitessio/vitess/pull/19211) +#### CLI + * [release-22.0] `vtbench`: add `--db-credentials-*` flags (#18913) [#18921](https://github.com/vitessio/vitess/pull/18921) +#### Cluster management + * [release-22.0] Improve Semi-Sync Monitor Behavior to Prevent Errant ERS (#18884) [#18906](https://github.com/vitessio/vitess/pull/18906) +#### Evalengine + * [release-22.0] evalengine: Fix `NULL` document handling in JSON functions (#19052) [#19230](https://github.com/vitessio/vitess/pull/19230) + * [release-22.0] evalengine: make `JSON_EXTRACT` work with non-static arguments (#19035) [#19253](https://github.com/vitessio/vitess/pull/19253) +#### General + * [release-22.0] Escape control bytes in JSON strings (#19270) [#19274](https://github.com/vitessio/vitess/pull/19274) +#### Query Serving + * [release-22.0] Properly Strip Keyspace Table Qualifiers in FK Constraints (#18926) [#18934](https://github.com/vitessio/vitess/pull/18934) + * [release-22.0] Fix cross shard/keyspace joins with derived tables containing a `UNION`. (#19046) [#19136](https://github.com/vitessio/vitess/pull/19136) + * [release-22.0] Fix column offset tracking for `UNION`s to be case insensitive. (#19139) [#19161](https://github.com/vitessio/vitess/pull/19161) +#### TabletManager + * [release-22.0] Fix `ReloadSchema` incorrectly using `DisableBinlogs` value in `grpctmclient` (#19085) [#19129](https://github.com/vitessio/vitess/pull/19129) +#### VDiff + * [release-22.0] VDiff: Prevent division by 0 when reconciling mismatches for reference tables (#19160) [#19164](https://github.com/vitessio/vitess/pull/19164) +#### VReplication + * [release-22.0] VDiff: Handle the case where a workflow's table has been dropped on the source (#18985) [#18988](https://github.com/vitessio/vitess/pull/18988) + * [release-22.0] VReplication: Properly Handle Sequence Table Initialization For Empty Tables (#19226) [#19227](https://github.com/vitessio/vitess/pull/19227) +#### VTGate + * [release-22.0] workflows: avoid accidental deletion to routing rules (#19121) [#19135](https://github.com/vitessio/vitess/pull/19135) +#### VTTablet + * [release-22.0] connpool: fix connection leak during idle connection reopen (#18967) [#18970](https://github.com/vitessio/vitess/pull/18970) + * [release-22.0] Change connection pool idle expiration logic (#19004) [#19013](https://github.com/vitessio/vitess/pull/19013) + * [release-22.0] binlog_json: fix opaque value parsing to read variable-length (#19102) [#19109](https://github.com/vitessio/vitess/pull/19109) +#### VTorc + * [release-22.0] `vtorc`: detect errant GTIDs for replicas not connected to primary (#19224) [#19233](https://github.com/vitessio/vitess/pull/19233) + * [release-22.0] vtorc: add `StaleTopoPrimary` analysis and recovery (#19173) [#19236](https://github.com/vitessio/vitess/pull/19236) +#### vtctl + * [release-22.0] vschema revert: initialize as nil so that nil checks do not pass later (#19114) [#19117](https://github.com/vitessio/vitess/pull/19117) +### CI/Build +#### Build/CI + * Pin GitHub Actions and Docker images by hash [#19151](https://github.com/vitessio/vitess/pull/19151) + * [release-22.0] Update go-upgrade to update docker image digests (#19178) [#19188](https://github.com/vitessio/vitess/pull/19188) + * [release-22.0] Fix go upgrade workflow (#19216) [#19219](https://github.com/vitessio/vitess/pull/19219) + * [release-22.0] switch end-to-end tests to gotestsum (#19182) [#19244](https://github.com/vitessio/vitess/pull/19244) +#### General + * [release-22.0] Upgrade the Golang version to `go1.24.10` [#18897](https://github.com/vitessio/vitess/pull/18897) + * [release-22.0] Upgrade the Golang version to `go1.24.12` [#19222](https://github.com/vitessio/vitess/pull/19222) +### Enhancement +#### Build/CI + * [release-22.0] Don't hardcode the go version to use for upgrade/downgrade tests. (#18920) [#18955](https://github.com/vitessio/vitess/pull/18955) +#### TabletManager + * [release-22.0] Add new `force` flag to `DemotePrimary` to force a demotion even when blocked on waiting for semi-sync acks (#18714) [#19238](https://github.com/vitessio/vitess/pull/19238) +#### VDiff + * [release-22.0] vdiff: do not sort by table name in summary, it is not necessary (#18972) [#18977](https://github.com/vitessio/vitess/pull/18977) +### Internal Cleanup +#### Docker + * [release-22.0] `ci`: use `etcd` v3.5.25, add retries (#19015) [#19021](https://github.com/vitessio/vitess/pull/19021) +### Release +#### General + * [release-22.0] Code Freeze for `v22.0.3` [#19281](https://github.com/vitessio/vitess/pull/19281) +### Security +#### Java + * [release-22.0] Bump org.apache.logging.log4j:log4j-core from 2.24.1 to 2.25.3 in /java (#19063) [#19065](https://github.com/vitessio/vitess/pull/19065) +#### VTAdmin + * [release-22.0] Bump js-yaml from 4.1.0 to 4.1.1 in /web/vtadmin (#18908) [#18910](https://github.com/vitessio/vitess/pull/18910) + * [release-22.0] Drop dependency on `npm`, bump version of `glob`. (#18931) [#18957](https://github.com/vitessio/vitess/pull/18957) + * [release-22.0] Potential fix for code scanning alert no. 3944: Database query built … [#18962](https://github.com/vitessio/vitess/pull/18962) +### Testing +#### Build/CI + * [release-22.0] Stop using Equinix Metal self hosted runners (#18942) [#18943](https://github.com/vitessio/vitess/pull/18943) + * [release-22.0] CI: Improve reliability of codecov workflow with larger runner (#18992) [#18994](https://github.com/vitessio/vitess/pull/18994) + * [release-22.0] Skip flaky `TestRedial` test (#19106) [#19107](https://github.com/vitessio/vitess/pull/19107) + * [release-22.0] CI: Look for expected log message rather than code in Backup tests (#19199) [#19200](https://github.com/vitessio/vitess/pull/19200) +#### VTGate + * [release-22.0] Fix sporadic TestServingKeyspaces panic on context cancellation (#19163) [#19186](https://github.com/vitessio/vitess/pull/19186) + diff --git a/changelog/22.0/22.0.3/release_notes.md b/changelog/22.0/22.0.3/release_notes.md new file mode 100644 index 00000000000..da18cc4e572 --- /dev/null +++ b/changelog/22.0/22.0.3/release_notes.md @@ -0,0 +1,7 @@ +# Release of Vitess v22.0.3 +The entire changelog for this release can be found [here](https://github.com/vitessio/vitess/blob/main/changelog/22.0/22.0.3/changelog.md). + +The release includes 40 merged Pull Requests. + +Thanks to all our contributors: @app/vitess-bot, @mattlord, @mhamza15, @timvaillancourt, @vitess-bot + diff --git a/changelog/22.0/22.0.4/changelog.md b/changelog/22.0/22.0.4/changelog.md new file mode 100644 index 00000000000..2521697b052 --- /dev/null +++ b/changelog/22.0/22.0.4/changelog.md @@ -0,0 +1,69 @@ +# Changelog of Vitess v22.0.4 + +### Bug fixes +#### Backup and Restore + * [release-22.0] fix(backup): propagate file hashes to manifest after retry (#19336) [#19343](https://github.com/vitessio/vitess/pull/19343) +#### Docker + * [release-22.0] docker: install mysql-shell from Oracle repo and fix shellcheck warnings (#19456) [#19463](https://github.com/vitessio/vitess/pull/19463) +#### Online DDL + * [release-22.0] vreplication: fix infinite retry loop when terminal error message contains binary data (#19423) [#19437](https://github.com/vitessio/vitess/pull/19437) +#### Query Serving + * [release-22.0] vtgate: defer implicit transaction start until after query planning (#19277) [#19341](https://github.com/vitessio/vitess/pull/19341) +#### VDiff + * [release-22.0] Address a few VDiff concerns (#19413) [#19447](https://github.com/vitessio/vitess/pull/19447) +#### VReplication + * [release-22.0] Bug fix: Add missing db_name filters to vreplication and vdiff queries #19378 [#19430](https://github.com/vitessio/vitess/pull/19430) + * [release-22.0] Normalize the --on-ddl param for MoveTables (#19445) [#19451](https://github.com/vitessio/vitess/pull/19451) +#### VTGate + * [release-22.0] vtgate: Add bounds check in `visitUnion` for mismatched column counts (#19476) [#19482](https://github.com/vitessio/vitess/pull/19482) +#### VTOrc + * [release-22.0] vtorc: Add a timeout to `DemotePrimary` RPC (#19432) [#19449](https://github.com/vitessio/vitess/pull/19449) +#### schema management + * [release-22.0] sidecardb: make ALTER TABLE algorithm version-aware (#19358) [#19403](https://github.com/vitessio/vitess/pull/19403) +### CI/Build +#### Build/CI + * [release-22.0] Consolidate CI test workflows (#19259) [#19272](https://github.com/vitessio/vitess/pull/19272) + * [release-22.0] Run tests with gotestsum (#19076) [#19292](https://github.com/vitessio/vitess/pull/19292) + * [release-22.0] Fix go upgrade tool (#19290) [#19298](https://github.com/vitessio/vitess/pull/19298) + * [release-22.0] Switch gotestsum output format (#19215) [#19302](https://github.com/vitessio/vitess/pull/19302) + * [release-22.0] Build boostrap image for local/region example CI (#19310) [#19316](https://github.com/vitessio/vitess/pull/19316) + * [release-22.0] Don't add "Skip CI" label for Go upgrade PRs (#19307) [#19322](https://github.com/vitessio/vitess/pull/19322) + * [release-22.0] Explicitly pass local image tags in example CI (#19320) [#19325](https://github.com/vitessio/vitess/pull/19325) + * [release-22.0] Add lite image build CI job (#19321) [#19329](https://github.com/vitessio/vitess/pull/19329) + * [release-22.0] try to fix setup mysql (#19371) [#19375](https://github.com/vitessio/vitess/pull/19375) + * [release-22.0] CI: Fix workflows that install xtrabackup (#19383) [#19384](https://github.com/vitessio/vitess/pull/19384) +#### Docker + * [release-22.0] Build bootstrap image locally in ci (#19255) [#19265](https://github.com/vitessio/vitess/pull/19265) +### Compatibility Bug +#### Query Serving + * [release-22.0] fix streaming binary row corruption in prepared statements (#19381) [#19414](https://github.com/vitessio/vitess/pull/19414) +#### VTGate + * [release-22.0] vtgate: fix handling of session variables on targeted connections (#19318) [#19334](https://github.com/vitessio/vitess/pull/19334) +### Dependencies +#### Docker + * [release-22.0] Upgrade the Golang version to `go1.24.13` [#19305](https://github.com/vitessio/vitess/pull/19305) +### Enhancement +#### VTGate + * [release-22.0] Performance: use `IsSingleShard()` check in `pushDerived` instead of just `engine.EqualUnique` opcode (#18974) [#19345](https://github.com/vitessio/vitess/pull/19345) +### Release +#### Build/CI + * [release-22.0] Code Freeze for `v22.0.4` [#19509](https://github.com/vitessio/vitess/pull/19509) +#### Documentation + * Add release summary for v22.0.4 [#19508](https://github.com/vitessio/vitess/pull/19508) +#### General + * [release-22.0] Bump to `v22.0.4-SNAPSHOT` after the `v22.0.3` release [#19284](https://github.com/vitessio/vitess/pull/19284) +### Security +#### Backup and Restore + * [release-22.0] Restore: make loading compressor commands from `MANIFEST` opt-in (#19460) [#19473](https://github.com/vitessio/vitess/pull/19473) + * [release-22.0] `backupengine`: disallow path traversals via backup `MANIFEST` on restore (#19470) [#19477](https://github.com/vitessio/vitess/pull/19477) + * [release-22.0] `mysqlshellbackupengine`: use `fileutil.SafePathJoin(...)` to build path (#19484) [#19490](https://github.com/vitessio/vitess/pull/19490) +#### VTTablet + * [release-22.0] `filebackupstorage`: use `fileutil.SafePathJoin` for all path building (#19479) [#19480](https://github.com/vitessio/vitess/pull/19480) + * [release-22.0] `vttablet`: harden `ExecuteHook` RPC and backup engine flag inputs (#19486) [#19500](https://github.com/vitessio/vitess/pull/19500) +### Testing +#### Build/CI + * [release-22.0] Generate race unit tests (#19078) [#19295](https://github.com/vitessio/vitess/pull/19295) + * [release-22.0] CI: Deflake Code Coverage workflow (#19388) [#19393](https://github.com/vitessio/vitess/pull/19393) + * [release-22.0] CI: Deflake two flaky tests (#19364) [#19411](https://github.com/vitessio/vitess/pull/19411) + * [release-22.0] CI: Use larger runners for vreplication workflows (#19433) [#19434](https://github.com/vitessio/vitess/pull/19434) + diff --git a/changelog/22.0/22.0.4/release_notes.md b/changelog/22.0/22.0.4/release_notes.md new file mode 100644 index 00000000000..31c8ec20d50 --- /dev/null +++ b/changelog/22.0/22.0.4/release_notes.md @@ -0,0 +1,37 @@ +# Release of Vitess v22.0.4 + +## Summary + +This is a security focused release. It contains fixes for two recently reported CVEs along with a number of other security related fixes. + +### External Decompressor No Longer Read from Backup MANIFEST by Default + +This is a fix for the following security advisory and associated CVE + +- Advisory: +- CVE: + +The external decompressor command stored in a backup's `MANIFEST` file is no longer used at restore time by default. Previously, when no `--external-decompressor` flag was provided, VTTablet would fall back to the command specified in the `MANIFEST`. This posed a security risk: an attacker with write access to backup storage could modify the `MANIFEST` to execute arbitrary commands on the tablet. + +*Please note that this is a breaking change.* Starting in v22.0.4, the `MANIFEST`-based decompressor is ignored unless you explicitly opt in with the new `--external-decompressor-use-manifest` flag. If you rely on this behavior, add the flag to your VTTablet configuration, but be aware of the security implications. + +See [#19460](https://github.com/vitessio/vitess/pull/19460) for details. + +### Prevent Path Traversals Via Backup MANIFEST Files On restore + +This is a fix for the following security advisory and associated CVE + +- Advisory: +- CVE: + +We now prevent a common [Path Traversal attack](https://owasp.org/www-community/attacks/Path_Traversal) that someone with write access to backup storage could use to escape the target restore directory and write files to arbitrary filesystem paths via modifications to the `MANIFEST`. + +See [#19470](https://github.com/vitessio/vitess/pull/19470) for details. + +------------ +The entire changelog for this release can be found [here](https://github.com/vitessio/vitess/blob/main/changelog/22.0/22.0.4/changelog.md). + +The release includes 37 merged Pull Requests. + +Thanks to all our contributors: @app/vitess-bot, @mattlord, @vitess-bot + diff --git a/changelog/22.0/22.0.4/summary.md b/changelog/22.0/22.0.4/summary.md new file mode 100644 index 00000000000..3927041651f --- /dev/null +++ b/changelog/22.0/22.0.4/summary.md @@ -0,0 +1,29 @@ +# Release of Vitess v22.0.4 + +## Summary + +This is a security focused release. It contains fixes for two recently reported CVEs along with a number of other security related fixes. + +### External Decompressor No Longer Read from Backup MANIFEST by Default + +This is a fix for the following security advisory and associated CVE + +- Advisory: +- CVE: + +The external decompressor command stored in a backup's `MANIFEST` file is no longer used at restore time by default. Previously, when no `--external-decompressor` flag was provided, VTTablet would fall back to the command specified in the `MANIFEST`. This posed a security risk: an attacker with write access to backup storage could modify the `MANIFEST` to execute arbitrary commands on the tablet. + +*Please note that this is a breaking change.* Starting in v22.0.4, the `MANIFEST`-based decompressor is ignored unless you explicitly opt in with the new `--external-decompressor-use-manifest` flag. If you rely on this behavior, add the flag to your VTTablet configuration, but be aware of the security implications. + +See [#19460](https://github.com/vitessio/vitess/pull/19460) for details. + +### Prevent Path Traversals Via Backup MANIFEST Files On restore + +This is a fix for the following security advisory and associated CVE + +- Advisory: +- CVE: + +We now prevent a common [Path Traversal attack](https://owasp.org/www-community/attacks/Path_Traversal) that someone with write access to backup storage could use to escape the target restore directory and write files to arbitrary filesystem paths via modifications to the `MANIFEST`. + +See [#19470](https://github.com/vitessio/vitess/pull/19470) for details. diff --git a/changelog/22.0/README.md b/changelog/22.0/README.md index 96b173a8537..11745abb642 100644 --- a/changelog/22.0/README.md +++ b/changelog/22.0/README.md @@ -1,4 +1,12 @@ ## v22.0 +* **[22.0.4](22.0.4)** + * [Changelog](22.0.4/changelog.md) + * [Release Notes](22.0.4/release_notes.md) + +* **[22.0.3](22.0.3)** + * [Changelog](22.0.3/changelog.md) + * [Release Notes](22.0.3/release_notes.md) + * **[22.0.2](22.0.2)** * [Changelog](22.0.2/changelog.md) * [Release Notes](22.0.2/release_notes.md) diff --git a/docker/bootstrap/CHANGELOG.md b/docker/bootstrap/CHANGELOG.md index 2275c4a5163..23a01287f8c 100644 --- a/docker/bootstrap/CHANGELOG.md +++ b/docker/bootstrap/CHANGELOG.md @@ -194,4 +194,12 @@ List of changes between bootstrap image versions. ## [43.5] - 2025-11-12 ### Changes -- Update build to golang 1.24.10 \ No newline at end of file +- Update build to golang 1.24.10 + +## [43.6] - 2026-01-27 +### Changes +- Update build to golang 1.24.12 + +## [43.7] - 2026-02-08 +### Changes +- Update build to golang 1.24.13 \ No newline at end of file diff --git a/docker/bootstrap/Dockerfile.common b/docker/bootstrap/Dockerfile.common index e112119f836..39e734b7892 100644 --- a/docker/bootstrap/Dockerfile.common +++ b/docker/bootstrap/Dockerfile.common @@ -1,4 +1,4 @@ -FROM --platform=linux/amd64 golang:1.24.10-bookworm +FROM --platform=linux/amd64 golang:1.24.13-bookworm@sha256:98d673f18a1aac43da744209873cb79323e11706f909251bcfb131828b95559d # Install Vitess build dependencies RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ diff --git a/docker/bootstrap/docker-bake.hcl b/docker/bootstrap/docker-bake.hcl new file mode 100644 index 00000000000..c9b82c7187b --- /dev/null +++ b/docker/bootstrap/docker-bake.hcl @@ -0,0 +1,44 @@ +// docker-bake.hcl defines the build targets for the Vitess bootstrap images. +// +// The bootstrap images provide a pre-configured environment for running +// Vitess tests in Docker. The common image contains shared dependencies, +// while flavor-specific images (e.g., mysql80) add database-specific packages. +// +// Usage: +// docker buildx bake -f docker/bootstrap/docker-bake.hcl +// +// Variables can be overridden: +// docker buildx bake -f docker/bootstrap/docker-bake.hcl --set *.tags=myregistry/bootstrap:mytag + +variable "BOOTSTRAP_VERSION" { + default = "ci" +} + +variable "BOOTSTRAP_FLAVOR" { + default = "mysql84" +} + +group "default" { + targets = ["common", "flavor"] +} + +target "common" { + context = "." + dockerfile = "docker/bootstrap/Dockerfile.common" + tags = ["vitess/bootstrap:${BOOTSTRAP_VERSION}-common"] +} + +target "flavor" { + context = "." + dockerfile = "docker/bootstrap/Dockerfile.${BOOTSTRAP_FLAVOR}" + tags = ["vitess/bootstrap:${BOOTSTRAP_VERSION}-${BOOTSTRAP_FLAVOR}"] + + contexts = { + "vitess/bootstrap:${BOOTSTRAP_VERSION}-common" = "target:common" + } + + args = { + bootstrap_version = BOOTSTRAP_VERSION + image = "vitess/bootstrap:${BOOTSTRAP_VERSION}-common" + } +} diff --git a/docker/lite/Dockerfile b/docker/lite/Dockerfile index 074097ddb2e..dbe5263d745 100644 --- a/docker/lite/Dockerfile +++ b/docker/lite/Dockerfile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM --platform=linux/amd64 golang:1.24.10-bookworm AS builder +FROM --platform=linux/amd64 golang:1.24.13-bookworm@sha256:98d673f18a1aac43da744209873cb79323e11706f909251bcfb131828b95559d AS builder # Allows docker builds to set the BUILD_NUMBER ARG BUILD_NUMBER @@ -40,7 +40,7 @@ COPY --chown=vitess:vitess . /vt/src/vitess.io/vitess RUN make install PREFIX=/vt/install # Start over and build the final image. -FROM --platform=linux/amd64 debian:bookworm-slim +FROM --platform=linux/amd64 debian:bookworm-slim@sha256:09c53e50b5110eb26e0932ab77934481ce9c0068069d4f28e3e7493e51323bfe # Install locale required for mysqlsh RUN apt-get update && apt-get install -y locales \ diff --git a/docker/lite/Dockerfile.mysql84 b/docker/lite/Dockerfile.mysql84 index ca7c0913534..3239362d497 100644 --- a/docker/lite/Dockerfile.mysql84 +++ b/docker/lite/Dockerfile.mysql84 @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM --platform=linux/amd64 golang:1.24.10-bookworm AS builder +FROM --platform=linux/amd64 golang:1.24.13-bookworm@sha256:98d673f18a1aac43da744209873cb79323e11706f909251bcfb131828b95559d AS builder # Allows docker builds to set the BUILD_NUMBER ARG BUILD_NUMBER @@ -40,7 +40,7 @@ COPY --chown=vitess:vitess . /vt/src/vitess.io/vitess RUN make install PREFIX=/vt/install # Start over and build the final image. -FROM --platform=linux/amd64 debian:bookworm-slim +FROM --platform=linux/amd64 debian:bookworm-slim@sha256:09c53e50b5110eb26e0932ab77934481ce9c0068069d4f28e3e7493e51323bfe # Install locale required for mysqlsh RUN apt-get update && apt-get install -y locales \ diff --git a/docker/lite/Dockerfile.percona80 b/docker/lite/Dockerfile.percona80 index 46a4cb80a3e..6e9356a2c23 100644 --- a/docker/lite/Dockerfile.percona80 +++ b/docker/lite/Dockerfile.percona80 @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM --platform=linux/amd64 golang:1.24.10-bookworm AS builder +FROM --platform=linux/amd64 golang:1.24.13-bookworm@sha256:98d673f18a1aac43da744209873cb79323e11706f909251bcfb131828b95559d AS builder # Allows docker builds to set the BUILD_NUMBER ARG BUILD_NUMBER @@ -40,7 +40,7 @@ COPY --chown=vitess:vitess . /vt/src/vitess.io/vitess RUN make install PREFIX=/vt/install # Start over and build the final image. -FROM --platform=linux/amd64 debian:bookworm-slim +FROM --platform=linux/amd64 debian:bookworm-slim@sha256:09c53e50b5110eb26e0932ab77934481ce9c0068069d4f28e3e7493e51323bfe # Install dependencies COPY docker/utils/install_dependencies.sh /vt/dist/install_dependencies.sh diff --git a/docker/test/run.sh b/docker/test/run.sh index 8c6f65e694a..280e750679c 100755 --- a/docker/test/run.sh +++ b/docker/test/run.sh @@ -122,7 +122,7 @@ if [[ -n "$existing_cache_image" ]]; then fi # Fix permissions before copying files, to avoid AUFS bug other must have read/access permissions -chmod -R o=rx *; +chmod -R o=rx -- *; # This is required by the vtctld_web_test.py test. # Otherwise, /usr/bin/chromium will crash with the error: @@ -141,12 +141,22 @@ args="$args -v /tmp/mavencache:/home/vitess/.m2" args="$args --user vitess" args="$args -v $PWD/test/bin:/tmp/bin" +# Pass through TOPO environment variable if it's set +if [[ -n "$TOPO" ]]; then + args="$args -e TOPO=$TOPO" +fi + +# Pass through PACKAGES environment variable if it's set +if [[ -n "$PACKAGES" ]]; then + args="$args -e PACKAGES=$PACKAGES" +fi + # Mount in host VTDATAROOT if one exists, since it might be a RAM disk or SSD. if [[ -n "$VTDATAROOT" ]]; then - hostdir=`mktemp -d $VTDATAROOT/test-XXX` - testid=`basename $hostdir` + hostdir=$(mktemp -d "$VTDATAROOT/test-XXX") + testid=$(basename "$hostdir") - chmod 777 $hostdir + chmod 777 "$hostdir" echo "Mounting host dir $hostdir as VTDATAROOT" args="$args -v $hostdir:/vt/vtdataroot --name=$testid -h $testid" @@ -191,12 +201,14 @@ bashcmd=$(append_cmd "$bashcmd" "$cmd") if tty -s; then # interactive shell # See above why we turn on "extglob" (extended Glob). - docker run -ti $args $image bash -O extglob -c "$bashcmd" + # shellcheck disable=SC2086 + docker run -ti $args "$image" bash -O extglob -c "$bashcmd" exitcode=$? else # non-interactive shell (kill child on signal) trap 'docker kill $testid &>/dev/null' SIGTERM SIGINT - docker run $args $image bash -O extglob -c "$bashcmd" & + # shellcheck disable=SC2086 + docker run $args "$image" bash -O extglob -c "$bashcmd" & wait $! exitcode=$? trap - SIGTERM SIGINT @@ -205,23 +217,21 @@ fi # Clean up host dir mounted VTDATAROOT if [[ -n "$hostdir" ]]; then # Use Docker user to clean up first, to avoid permission errors. - docker run --name=rm_$testid -v $hostdir:/vt/vtdataroot $image bash -c 'rm -rf /vt/vtdataroot/*' - docker rm -f rm_$testid &>/dev/null - rm -rf $hostdir + docker run --name="rm_$testid" -v "$hostdir":/vt/vtdataroot "$image" bash -c 'rm -rf /vt/vtdataroot/*' + docker rm -f "rm_$testid" &>/dev/null + rm -rf "$hostdir" fi # If requested, create the cache image. if [[ "$mode" == "create_cache" && $exitcode == 0 ]]; then msg="DO NOT PUSH: This is a temporary layer meant to persist e.g. the result of 'make build'. Never push this layer back to our official Docker Hub repository." - docker commit -m "$msg" $testid $cache_image - - if [[ $? != 0 ]]; then + if ! docker commit -m "$msg" "$testid" "$cache_image"; then exitcode=$? echo "ERROR: Failed to create Docker cache. Used command: docker commit -m '$msg' $testid $image" fi fi # Delete the container -docker rm -f $testid &>/dev/null +docker rm -f "$testid" &>/dev/null exit $exitcode diff --git a/docker/utils/install_dependencies.sh b/docker/utils/install_dependencies.sh index 59e16b6303a..08ece1df515 100755 --- a/docker/utils/install_dependencies.sh +++ b/docker/utils/install_dependencies.sh @@ -39,7 +39,7 @@ do_fetch() { --retry-connrefused\ --waitretry=1\ --no-dns-cache \ - $1 -O $2 + "$1" -O "$2" } # Install base packages that are common to all flavors. @@ -75,26 +75,27 @@ mysql80) if [ -z "$VERSION" ]; then VERSION=8.0.40 fi - do_fetch https://repo.mysql.com/apt/debian/pool/mysql-8.0/m/mysql-community/mysql-common_${VERSION}-1debian12_amd64.deb /tmp/mysql-common_${VERSION}-1debian12_amd64.deb - do_fetch https://repo.mysql.com/apt/debian/pool/mysql-8.0/m/mysql-community/libmysqlclient21_${VERSION}-1debian12_amd64.deb /tmp/libmysqlclient21_${VERSION}-1debian12_amd64.deb - do_fetch https://repo.mysql.com/apt/debian/pool/mysql-8.0/m/mysql-community/mysql-community-client-core_${VERSION}-1debian12_amd64.deb /tmp/mysql-community-client-core_${VERSION}-1debian12_amd64.deb - do_fetch https://repo.mysql.com/apt/debian/pool/mysql-8.0/m/mysql-community/mysql-community-client-plugins_${VERSION}-1debian12_amd64.deb /tmp/mysql-community-client-plugins_${VERSION}-1debian12_amd64.deb - do_fetch https://repo.mysql.com/apt/debian/pool/mysql-8.0/m/mysql-community/mysql-community-client_${VERSION}-1debian12_amd64.deb /tmp/mysql-community-client_${VERSION}-1debian12_amd64.deb - do_fetch https://repo.mysql.com/apt/debian/pool/mysql-8.0/m/mysql-community/mysql-client_${VERSION}-1debian12_amd64.deb /tmp/mysql-client_${VERSION}-1debian12_amd64.deb - do_fetch https://repo.mysql.com/apt/debian/pool/mysql-8.0/m/mysql-community/mysql-community-server-core_${VERSION}-1debian12_amd64.deb /tmp/mysql-community-server-core_${VERSION}-1debian12_amd64.deb - do_fetch https://repo.mysql.com/apt/debian/pool/mysql-8.0/m/mysql-community/mysql-community-server_${VERSION}-1debian12_amd64.deb /tmp/mysql-community-server_${VERSION}-1debian12_amd64.deb - do_fetch https://repo.mysql.com/apt/debian/pool/mysql-8.0/m/mysql-community/mysql-server_${VERSION}-1debian12_amd64.deb /tmp/mysql-server_${VERSION}-1debian12_amd64.deb + do_fetch "https://repo.mysql.com/apt/debian/pool/mysql-8.0/m/mysql-community/mysql-common_${VERSION}-1debian12_amd64.deb" "/tmp/mysql-common_${VERSION}-1debian12_amd64.deb" + do_fetch "https://repo.mysql.com/apt/debian/pool/mysql-8.0/m/mysql-community/libmysqlclient21_${VERSION}-1debian12_amd64.deb" "/tmp/libmysqlclient21_${VERSION}-1debian12_amd64.deb" + do_fetch "https://repo.mysql.com/apt/debian/pool/mysql-8.0/m/mysql-community/mysql-community-client-core_${VERSION}-1debian12_amd64.deb" "/tmp/mysql-community-client-core_${VERSION}-1debian12_amd64.deb" + do_fetch "https://repo.mysql.com/apt/debian/pool/mysql-8.0/m/mysql-community/mysql-community-client-plugins_${VERSION}-1debian12_amd64.deb" "/tmp/mysql-community-client-plugins_${VERSION}-1debian12_amd64.deb" + do_fetch "https://repo.mysql.com/apt/debian/pool/mysql-8.0/m/mysql-community/mysql-community-client_${VERSION}-1debian12_amd64.deb" "/tmp/mysql-community-client_${VERSION}-1debian12_amd64.deb" + do_fetch "https://repo.mysql.com/apt/debian/pool/mysql-8.0/m/mysql-community/mysql-client_${VERSION}-1debian12_amd64.deb" "/tmp/mysql-client_${VERSION}-1debian12_amd64.deb" + do_fetch "https://repo.mysql.com/apt/debian/pool/mysql-8.0/m/mysql-community/mysql-community-server-core_${VERSION}-1debian12_amd64.deb" "/tmp/mysql-community-server-core_${VERSION}-1debian12_amd64.deb" + do_fetch "https://repo.mysql.com/apt/debian/pool/mysql-8.0/m/mysql-community/mysql-community-server_${VERSION}-1debian12_amd64.deb" "/tmp/mysql-community-server_${VERSION}-1debian12_amd64.deb" + do_fetch "https://repo.mysql.com/apt/debian/pool/mysql-8.0/m/mysql-community/mysql-server_${VERSION}-1debian12_amd64.deb" "/tmp/mysql-server_${VERSION}-1debian12_amd64.deb" + do_fetch "https://repo.mysql.com/apt/debian/pool/mysql-8.0/m/mysql-shell/mysql-shell_${VERSION}-1debian12_amd64.deb" "/tmp/mysql-shell_${VERSION}-1debian12_amd64.deb" PACKAGES=( - /tmp/mysql-common_${VERSION}-1debian12_amd64.deb - /tmp/libmysqlclient21_${VERSION}-1debian12_amd64.deb - /tmp/mysql-community-client-core_${VERSION}-1debian12_amd64.deb - /tmp/mysql-community-client-plugins_${VERSION}-1debian12_amd64.deb - /tmp/mysql-community-client_${VERSION}-1debian12_amd64.deb - /tmp/mysql-client_${VERSION}-1debian12_amd64.deb - /tmp/mysql-community-server-core_${VERSION}-1debian12_amd64.deb - /tmp/mysql-community-server_${VERSION}-1debian12_amd64.deb - /tmp/mysql-server_${VERSION}-1debian12_amd64.deb - mysql-shell + "/tmp/mysql-common_${VERSION}-1debian12_amd64.deb" + "/tmp/libmysqlclient21_${VERSION}-1debian12_amd64.deb" + "/tmp/mysql-community-client-core_${VERSION}-1debian12_amd64.deb" + "/tmp/mysql-community-client-plugins_${VERSION}-1debian12_amd64.deb" + "/tmp/mysql-community-client_${VERSION}-1debian12_amd64.deb" + "/tmp/mysql-client_${VERSION}-1debian12_amd64.deb" + "/tmp/mysql-community-server-core_${VERSION}-1debian12_amd64.deb" + "/tmp/mysql-community-server_${VERSION}-1debian12_amd64.deb" + "/tmp/mysql-server_${VERSION}-1debian12_amd64.deb" + "/tmp/mysql-shell_${VERSION}-1debian12_amd64.deb" percona-xtrabackup-80 ) ;; @@ -102,26 +103,27 @@ mysql84) if [ -z "$VERSION" ]; then VERSION=8.4.3 fi - do_fetch https://repo.mysql.com/apt/debian/pool/mysql-8.4-lts/m/mysql-community/mysql-common_${VERSION}-1debian12_amd64.deb /tmp/mysql-common_${VERSION}-1debian12_amd64.deb - do_fetch https://repo.mysql.com/apt/debian/pool/mysql-8.4-lts/m/mysql-community/libmysqlclient24_${VERSION}-1debian12_amd64.deb /tmp/libmysqlclient24_${VERSION}-1debian12_amd64.deb - do_fetch https://repo.mysql.com/apt/debian/pool/mysql-8.4-lts/m/mysql-community/mysql-community-client-core_${VERSION}-1debian12_amd64.deb /tmp/mysql-community-client-core_${VERSION}-1debian12_amd64.deb - do_fetch https://repo.mysql.com/apt/debian/pool/mysql-8.4-lts/m/mysql-community/mysql-community-client-plugins_${VERSION}-1debian12_amd64.deb /tmp/mysql-community-client-plugins_${VERSION}-1debian12_amd64.deb - do_fetch https://repo.mysql.com/apt/debian/pool/mysql-8.4-lts/m/mysql-community/mysql-community-client_${VERSION}-1debian12_amd64.deb /tmp/mysql-community-client_${VERSION}-1debian12_amd64.deb - do_fetch https://repo.mysql.com/apt/debian/pool/mysql-8.4-lts/m/mysql-community/mysql-client_${VERSION}-1debian12_amd64.deb /tmp/mysql-client_${VERSION}-1debian12_amd64.deb - do_fetch https://repo.mysql.com/apt/debian/pool/mysql-8.4-lts/m/mysql-community/mysql-community-server-core_${VERSION}-1debian12_amd64.deb /tmp/mysql-community-server-core_${VERSION}-1debian12_amd64.deb - do_fetch https://repo.mysql.com/apt/debian/pool/mysql-8.4-lts/m/mysql-community/mysql-community-server_${VERSION}-1debian12_amd64.deb /tmp/mysql-community-server_${VERSION}-1debian12_amd64.deb - do_fetch https://repo.mysql.com/apt/debian/pool/mysql-8.4-lts/m/mysql-community/mysql-server_${VERSION}-1debian12_amd64.deb /tmp/mysql-server_${VERSION}-1debian12_amd64.deb + do_fetch "https://repo.mysql.com/apt/debian/pool/mysql-8.4-lts/m/mysql-community/mysql-common_${VERSION}-1debian12_amd64.deb" "/tmp/mysql-common_${VERSION}-1debian12_amd64.deb" + do_fetch "https://repo.mysql.com/apt/debian/pool/mysql-8.4-lts/m/mysql-community/libmysqlclient24_${VERSION}-1debian12_amd64.deb" "/tmp/libmysqlclient24_${VERSION}-1debian12_amd64.deb" + do_fetch "https://repo.mysql.com/apt/debian/pool/mysql-8.4-lts/m/mysql-community/mysql-community-client-core_${VERSION}-1debian12_amd64.deb" "/tmp/mysql-community-client-core_${VERSION}-1debian12_amd64.deb" + do_fetch "https://repo.mysql.com/apt/debian/pool/mysql-8.4-lts/m/mysql-community/mysql-community-client-plugins_${VERSION}-1debian12_amd64.deb" "/tmp/mysql-community-client-plugins_${VERSION}-1debian12_amd64.deb" + do_fetch "https://repo.mysql.com/apt/debian/pool/mysql-8.4-lts/m/mysql-community/mysql-community-client_${VERSION}-1debian12_amd64.deb" "/tmp/mysql-community-client_${VERSION}-1debian12_amd64.deb" + do_fetch "https://repo.mysql.com/apt/debian/pool/mysql-8.4-lts/m/mysql-community/mysql-client_${VERSION}-1debian12_amd64.deb" "/tmp/mysql-client_${VERSION}-1debian12_amd64.deb" + do_fetch "https://repo.mysql.com/apt/debian/pool/mysql-8.4-lts/m/mysql-community/mysql-community-server-core_${VERSION}-1debian12_amd64.deb" "/tmp/mysql-community-server-core_${VERSION}-1debian12_amd64.deb" + do_fetch "https://repo.mysql.com/apt/debian/pool/mysql-8.4-lts/m/mysql-community/mysql-community-server_${VERSION}-1debian12_amd64.deb" "/tmp/mysql-community-server_${VERSION}-1debian12_amd64.deb" + do_fetch "https://repo.mysql.com/apt/debian/pool/mysql-8.4-lts/m/mysql-community/mysql-server_${VERSION}-1debian12_amd64.deb" "/tmp/mysql-server_${VERSION}-1debian12_amd64.deb" + do_fetch "https://repo.mysql.com/apt/debian/pool/mysql-8.4-lts/m/mysql-shell/mysql-shell_${VERSION}-1debian12_amd64.deb" "/tmp/mysql-shell_${VERSION}-1debian12_amd64.deb" PACKAGES=( - /tmp/mysql-common_${VERSION}-1debian12_amd64.deb - /tmp/libmysqlclient24_${VERSION}-1debian12_amd64.deb - /tmp/mysql-community-client-core_${VERSION}-1debian12_amd64.deb - /tmp/mysql-community-client-plugins_${VERSION}-1debian12_amd64.deb - /tmp/mysql-community-client_${VERSION}-1debian12_amd64.deb - /tmp/mysql-client_${VERSION}-1debian12_amd64.deb - /tmp/mysql-community-server-core_${VERSION}-1debian12_amd64.deb - /tmp/mysql-community-server_${VERSION}-1debian12_amd64.deb - /tmp/mysql-server_${VERSION}-1debian12_amd64.deb - mysql-shell + "/tmp/mysql-common_${VERSION}-1debian12_amd64.deb" + "/tmp/libmysqlclient24_${VERSION}-1debian12_amd64.deb" + "/tmp/mysql-community-client-core_${VERSION}-1debian12_amd64.deb" + "/tmp/mysql-community-client-plugins_${VERSION}-1debian12_amd64.deb" + "/tmp/mysql-community-client_${VERSION}-1debian12_amd64.deb" + "/tmp/mysql-client_${VERSION}-1debian12_amd64.deb" + "/tmp/mysql-community-server-core_${VERSION}-1debian12_amd64.deb" + "/tmp/mysql-community-server_${VERSION}-1debian12_amd64.deb" + "/tmp/mysql-server_${VERSION}-1debian12_amd64.deb" + "/tmp/mysql-shell_${VERSION}-1debian12_amd64.deb" percona-xtrabackup-84 ) ;; diff --git a/docker/vttestserver/Dockerfile.mysql80 b/docker/vttestserver/Dockerfile.mysql80 index 2e25dc6f0bc..89999824a5d 100644 --- a/docker/vttestserver/Dockerfile.mysql80 +++ b/docker/vttestserver/Dockerfile.mysql80 @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM --platform=linux/amd64 golang:1.24.10-bookworm AS builder +FROM --platform=linux/amd64 golang:1.24.13-bookworm@sha256:98d673f18a1aac43da744209873cb79323e11706f909251bcfb131828b95559d AS builder # Allows docker builds to set the BUILD_NUMBER ARG BUILD_NUMBER @@ -31,7 +31,7 @@ COPY --chown=vitess:vitess . /vt/src/vitess.io/vitess RUN make install-testing PREFIX=/vt/install # Start over and build the final image. -FROM --platform=linux/amd64 debian:bookworm-slim +FROM --platform=linux/amd64 debian:bookworm-slim@sha256:09c53e50b5110eb26e0932ab77934481ce9c0068069d4f28e3e7493e51323bfe # Install dependencies COPY docker/utils/install_dependencies.sh /vt/dist/install_dependencies.sh diff --git a/docker/vttestserver/Dockerfile.mysql84 b/docker/vttestserver/Dockerfile.mysql84 index 6fe1326147a..13f247acf07 100644 --- a/docker/vttestserver/Dockerfile.mysql84 +++ b/docker/vttestserver/Dockerfile.mysql84 @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM --platform=linux/amd64 golang:1.24.10-bookworm AS builder +FROM --platform=linux/amd64 golang:1.24.13-bookworm@sha256:98d673f18a1aac43da744209873cb79323e11706f909251bcfb131828b95559d AS builder # Allows docker builds to set the BUILD_NUMBER ARG BUILD_NUMBER @@ -31,7 +31,7 @@ COPY --chown=vitess:vitess . /vt/src/vitess.io/vitess RUN make install-testing PREFIX=/vt/install # Start over and build the final image. -FROM --platform=linux/amd64 debian:bookworm-slim +FROM --platform=linux/amd64 debian:bookworm-slim@sha256:09c53e50b5110eb26e0932ab77934481ce9c0068069d4f28e3e7493e51323bfe # Install dependencies COPY docker/utils/install_dependencies.sh /vt/dist/install_dependencies.sh diff --git a/examples/common/scripts/zk-down.sh b/examples/common/scripts/zk-down.sh index f244f2b0f05..3f42d90a478 100755 --- a/examples/common/scripts/zk-down.sh +++ b/examples/common/scripts/zk-down.sh @@ -18,6 +18,10 @@ source "$(dirname "${BASH_SOURCE[0]:-$0}")/../env.sh" +# Explicitly set VTROOT for this script, since it requires it. +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)" +export VTROOT=${VTROOT:-$(cd "$SCRIPT_DIR/../../.." && pwd)} + # Stop ZooKeeper servers. echo "Stopping zk servers..." for zkid in $zkids; do diff --git a/examples/common/scripts/zk-up.sh b/examples/common/scripts/zk-up.sh index 143a704cbb4..2fcde21674f 100755 --- a/examples/common/scripts/zk-up.sh +++ b/examples/common/scripts/zk-up.sh @@ -18,6 +18,10 @@ source "$(dirname "${BASH_SOURCE[0]:-$0}")/../env.sh" +# Explicitly set VTROOT for this script, since it requires it. +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)" +export VTROOT=${VTROOT:-$(cd "$SCRIPT_DIR/../../.." && pwd)} + cell=${CELL:-'test'} # Start ZooKeeper servers. # The "zkctl init" command won't return until the server is able to contact its diff --git a/examples/compose/docker-compose.beginners.yml b/examples/compose/docker-compose.beginners.yml index 6c22e60efa3..a87c0b1a83b 100644 --- a/examples/compose/docker-compose.beginners.yml +++ b/examples/compose/docker-compose.beginners.yml @@ -58,7 +58,7 @@ services: - "3306" vtctld: - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - "15000:$WEB_PORT" - "$GRPC_PORT" @@ -83,7 +83,7 @@ services: condition: service_healthy vtgate: - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - "15099:$WEB_PORT" - "$GRPC_PORT" @@ -113,7 +113,7 @@ services: condition: service_healthy schemaload: - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 command: - sh - -c @@ -146,12 +146,12 @@ services: environment: - KEYSPACES=$KEYSPACE - GRPC_PORT=15999 - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 volumes: - .:/script vttablet100: - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - "15100:$WEB_PORT" - "$GRPC_PORT" @@ -183,7 +183,7 @@ services: retries: 15 vttablet101: - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - "15101:$WEB_PORT" - "$GRPC_PORT" @@ -215,7 +215,7 @@ services: retries: 15 vttablet102: - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - "15102:$WEB_PORT" - "$GRPC_PORT" @@ -247,7 +247,7 @@ services: retries: 15 vttablet103: - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - "15103:$WEB_PORT" - "$GRPC_PORT" @@ -279,7 +279,7 @@ services: retries: 15 vtorc: - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 command: ["sh", "-c", "/script/vtorc-up.sh"] depends_on: - vtctld @@ -309,7 +309,7 @@ services: retries: 15 vreplication: - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 volumes: - ".:/script" environment: diff --git a/examples/compose/docker-compose.yml b/examples/compose/docker-compose.yml index 133ad0c150d..9643f8502e8 100644 --- a/examples/compose/docker-compose.yml +++ b/examples/compose/docker-compose.yml @@ -75,7 +75,7 @@ services: - SCHEMA_FILES=lookup_keyspace_schema_file.sql - POST_LOAD_FILE= - EXTERNAL_DB=0 - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 volumes: - .:/script schemaload_test_keyspace: @@ -101,7 +101,7 @@ services: - SCHEMA_FILES=test_keyspace_schema_file.sql - POST_LOAD_FILE= - EXTERNAL_DB=0 - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 volumes: - .:/script set_keyspace_durability_policy: @@ -115,7 +115,7 @@ services: environment: - KEYSPACES=test_keyspace lookup_keyspace - GRPC_PORT=15999 - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 volumes: - .:/script vreplication: @@ -129,7 +129,7 @@ services: - TOPOLOGY_FLAGS=--topo_implementation consul --topo_global_server_address consul1:8500 --topo_global_root vitess/global - EXTERNAL_DB=0 - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 volumes: - .:/script vtctld: @@ -143,7 +143,7 @@ services: depends_on: external_db_host: condition: service_healthy - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - 15000:8080 - "15999" @@ -160,7 +160,7 @@ services: --normalize_queries=true ' depends_on: - vtctld - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - 15099:8080 - "15999" @@ -182,7 +182,7 @@ services: - EXTERNAL_DB=0 - DB_USER= - DB_PASS= - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - 13000:8080 volumes: @@ -217,7 +217,7 @@ services: - CMD-SHELL - curl -s --fail --show-error localhost:8080/debug/health timeout: 10s - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - 15101:8080 - "15999" @@ -254,7 +254,7 @@ services: - CMD-SHELL - curl -s --fail --show-error localhost:8080/debug/health timeout: 10s - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - 15102:8080 - "15999" @@ -291,7 +291,7 @@ services: - CMD-SHELL - curl -s --fail --show-error localhost:8080/debug/health timeout: 10s - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - 15201:8080 - "15999" @@ -328,7 +328,7 @@ services: - CMD-SHELL - curl -s --fail --show-error localhost:8080/debug/health timeout: 10s - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - 15202:8080 - "15999" @@ -365,7 +365,7 @@ services: - CMD-SHELL - curl -s --fail --show-error localhost:8080/debug/health timeout: 10s - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - 15301:8080 - "15999" @@ -402,7 +402,7 @@ services: - CMD-SHELL - curl -s --fail --show-error localhost:8080/debug/health timeout: 10s - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - 15302:8080 - "15999" diff --git a/examples/compose/vtcompose/docker-compose.test.yml b/examples/compose/vtcompose/docker-compose.test.yml index be4d1c98c49..65ddc1feba0 100644 --- a/examples/compose/vtcompose/docker-compose.test.yml +++ b/examples/compose/vtcompose/docker-compose.test.yml @@ -79,7 +79,7 @@ services: - SCHEMA_FILES=test_keyspace_schema_file.sql - POST_LOAD_FILE= - EXTERNAL_DB=0 - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 volumes: - .:/script schemaload_unsharded_keyspace: @@ -103,7 +103,7 @@ services: - SCHEMA_FILES=unsharded_keyspace_schema_file.sql - POST_LOAD_FILE= - EXTERNAL_DB=0 - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 volumes: - .:/script set_keyspace_durability_policy_test_keyspace: @@ -117,7 +117,7 @@ services: environment: - GRPC_PORT=15999 - KEYSPACES=test_keyspace - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 volumes: - .:/script set_keyspace_durability_policy_unsharded_keyspace: @@ -130,7 +130,7 @@ services: environment: - GRPC_PORT=15999 - KEYSPACES=unsharded_keyspace - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 volumes: - .:/script vreplication: @@ -144,7 +144,7 @@ services: - TOPOLOGY_FLAGS=--topo_implementation consul --topo_global_server_address consul1:8500 --topo_global_root vitess/global - EXTERNAL_DB=0 - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 volumes: - .:/script vtctld: @@ -159,7 +159,7 @@ services: depends_on: external_db_host: condition: service_healthy - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - 15000:8080 - "15999" @@ -176,7 +176,7 @@ services: ''grpc-vtgateservice'' --normalize_queries=true ' depends_on: - vtctld - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - 15099:8080 - "15999" @@ -199,7 +199,7 @@ services: - EXTERNAL_DB=0 - DB_USER= - DB_PASS= - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - 13000:8080 volumes: @@ -234,7 +234,7 @@ services: - CMD-SHELL - curl -s --fail --show-error localhost:8080/debug/health timeout: 10s - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - 15101:8080 - "15999" @@ -271,7 +271,7 @@ services: - CMD-SHELL - curl -s --fail --show-error localhost:8080/debug/health timeout: 10s - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - 15102:8080 - "15999" @@ -308,7 +308,7 @@ services: - CMD-SHELL - curl -s --fail --show-error localhost:8080/debug/health timeout: 10s - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - 15201:8080 - "15999" @@ -345,7 +345,7 @@ services: - CMD-SHELL - curl -s --fail --show-error localhost:8080/debug/health timeout: 10s - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - 15202:8080 - "15999" @@ -382,7 +382,7 @@ services: - CMD-SHELL - curl -s --fail --show-error localhost:8080/debug/health timeout: 10s - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - 15301:8080 - "15999" diff --git a/examples/compose/vtcompose/vtcompose.go b/examples/compose/vtcompose/vtcompose.go index 8426a9aec10..a0b7fbc092a 100644 --- a/examples/compose/vtcompose/vtcompose.go +++ b/examples/compose/vtcompose/vtcompose.go @@ -525,7 +525,7 @@ func generateExternalPrimary( - op: add path: /services/vttablet%[1]d value: - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - "15%[1]d:%[3]d" - "%[4]d" @@ -587,7 +587,7 @@ func generateDefaultTablet(tabAlias int, shard, role, keyspace string, dbInfo ex - op: add path: /services/vttablet%[1]d value: - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - "15%[1]d:%[4]d" - "%[5]d" @@ -625,7 +625,7 @@ func generateVtctld(opts vtOptions) string { - op: add path: /services/vtctld value: - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - "15000:%[1]d" - "%[2]d" @@ -656,7 +656,7 @@ func generateVtgate(opts vtOptions) string { - op: add path: /services/vtgate value: - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 ports: - "15099:%[1]d" - "%[2]d" @@ -698,7 +698,7 @@ func generateVTOrc(dbInfo externalDbInfo, keyspaceInfoMap map[string]keyspaceInf - op: add path: /services/vtorc value: - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 volumes: - ".:/script" environment: @@ -723,7 +723,7 @@ func generateVreplication(dbInfo externalDbInfo, opts vtOptions) string { - op: add path: /services/vreplication value: - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 volumes: - ".:/script" environment: @@ -751,7 +751,7 @@ func generateSetKeyspaceDurabilityPolicy( - op: add path: /services/set_keyspace_durability_policy_%[3]s value: - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 volumes: - ".:/script" environment: @@ -788,7 +788,7 @@ func generateSchemaload( - op: add path: /services/schemaload_%[7]s value: - image: vitess/lite:v22.0.2 + image: vitess/lite:v22.0.4 volumes: - ".:/script" environment: diff --git a/examples/operator/101_initial_cluster.yaml b/examples/operator/101_initial_cluster.yaml index 26fbcbad38e..bc546b193db 100644 --- a/examples/operator/101_initial_cluster.yaml +++ b/examples/operator/101_initial_cluster.yaml @@ -16,14 +16,14 @@ spec: path: /tmp type: Directory images: - vtctld: vitess/lite:v22.0.2 - vtadmin: vitess/vtadmin:v22.0.2 - vtgate: vitess/lite:v22.0.2 - vttablet: vitess/lite:v22.0.2 - vtbackup: vitess/lite:v22.0.2 - vtorc: vitess/lite:v22.0.2 + vtctld: vitess/lite:v22.0.4 + vtadmin: vitess/vtadmin:v22.0.4 + vtgate: vitess/lite:v22.0.4 + vttablet: vitess/lite:v22.0.4 + vtbackup: vitess/lite:v22.0.4 + vtorc: vitess/lite:v22.0.4 mysqld: - mysql80Compatible: vitess/lite:v22.0.2 + mysql80Compatible: vitess/lite:v22.0.4 mysqldExporter: prom/mysqld-exporter:v0.14.0 cells: - name: zone1 diff --git a/examples/operator/201_customer_tablets.yaml b/examples/operator/201_customer_tablets.yaml index 5cd355b9bdc..6ecbe613718 100644 --- a/examples/operator/201_customer_tablets.yaml +++ b/examples/operator/201_customer_tablets.yaml @@ -12,14 +12,14 @@ spec: path: /tmp type: Directory images: - vtctld: vitess/lite:v22.0.2 - vtadmin: vitess/vtadmin:v22.0.2 - vtgate: vitess/lite:v22.0.2 - vttablet: vitess/lite:v22.0.2 - vtbackup: vitess/lite:v22.0.2 - vtorc: vitess/lite:v22.0.2 + vtctld: vitess/lite:v22.0.4 + vtadmin: vitess/vtadmin:v22.0.4 + vtgate: vitess/lite:v22.0.4 + vttablet: vitess/lite:v22.0.4 + vtbackup: vitess/lite:v22.0.4 + vtorc: vitess/lite:v22.0.4 mysqld: - mysql80Compatible: vitess/lite:v22.0.2 + mysql80Compatible: vitess/lite:v22.0.4 mysqldExporter: prom/mysqld-exporter:v0.14.0 cells: - name: zone1 diff --git a/examples/operator/302_new_shards.yaml b/examples/operator/302_new_shards.yaml index 416e1c22cf7..04f93836693 100644 --- a/examples/operator/302_new_shards.yaml +++ b/examples/operator/302_new_shards.yaml @@ -12,14 +12,14 @@ spec: path: /tmp type: Directory images: - vtctld: vitess/lite:v22.0.2 - vtadmin: vitess/vtadmin:v22.0.2 - vtgate: vitess/lite:v22.0.2 - vttablet: vitess/lite:v22.0.2 - vtbackup: vitess/lite:v22.0.2 - vtorc: vitess/lite:v22.0.2 + vtctld: vitess/lite:v22.0.4 + vtadmin: vitess/vtadmin:v22.0.4 + vtgate: vitess/lite:v22.0.4 + vttablet: vitess/lite:v22.0.4 + vtbackup: vitess/lite:v22.0.4 + vtorc: vitess/lite:v22.0.4 mysqld: - mysql80Compatible: vitess/lite:v22.0.2 + mysql80Compatible: vitess/lite:v22.0.4 mysqldExporter: prom/mysqld-exporter:v0.14.0 cells: - name: zone1 diff --git a/examples/operator/306_down_shard_0.yaml b/examples/operator/306_down_shard_0.yaml index 3cc5bb188ec..fc926303719 100644 --- a/examples/operator/306_down_shard_0.yaml +++ b/examples/operator/306_down_shard_0.yaml @@ -12,14 +12,14 @@ spec: path: /tmp type: Directory images: - vtctld: vitess/lite:v22.0.2 - vtadmin: vitess/vtadmin:v22.0.2 - vtgate: vitess/lite:v22.0.2 - vttablet: vitess/lite:v22.0.2 - vtbackup: vitess/lite:v22.0.2 - vtorc: vitess/lite:v22.0.2 + vtctld: vitess/lite:v22.0.4 + vtadmin: vitess/vtadmin:v22.0.4 + vtgate: vitess/lite:v22.0.4 + vttablet: vitess/lite:v22.0.4 + vtbackup: vitess/lite:v22.0.4 + vtorc: vitess/lite:v22.0.4 mysqld: - mysql80Compatible: vitess/lite:v22.0.2 + mysql80Compatible: vitess/lite:v22.0.4 mysqldExporter: prom/mysqld-exporter:v0.14.0 cells: - name: zone1 diff --git a/examples/operator/401_scheduled_backups.yaml b/examples/operator/401_scheduled_backups.yaml index 7a351281fbd..a081fcc0cd5 100644 --- a/examples/operator/401_scheduled_backups.yaml +++ b/examples/operator/401_scheduled_backups.yaml @@ -46,14 +46,14 @@ spec: keyspace: "customer" shard: "-80" images: - vtctld: vitess/lite:v22.0.2 - vtadmin: vitess/vtadmin:v22.0.2 - vtgate: vitess/lite:v22.0.2 - vttablet: vitess/lite:v22.0.2 - vtbackup: vitess/lite:v22.0.2 - vtorc: vitess/lite:v22.0.2 + vtctld: vitess/lite:v22.0.4 + vtadmin: vitess/vtadmin:v22.0.4 + vtgate: vitess/lite:v22.0.4 + vttablet: vitess/lite:v22.0.4 + vtbackup: vitess/lite:v22.0.4 + vtorc: vitess/lite:v22.0.4 mysqld: - mysql80Compatible: vitess/lite:v22.0.2 + mysql80Compatible: vitess/lite:v22.0.4 mysqldExporter: prom/mysqld-exporter:v0.14.0 cells: - name: zone1 diff --git a/go.mod b/go.mod index 4df3b1013dd..23718d40909 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module vitess.io/vitess -go 1.24.10 +go 1.24.13 + +tool gotest.tools/gotestsum require ( cloud.google.com/go/storage v1.51.0 @@ -15,7 +17,7 @@ require ( github.com/corpix/uarand v0.1.1 // indirect github.com/dave/jennifer v1.7.1 github.com/evanphx/json-patch v5.9.11+incompatible - github.com/fsnotify/fsnotify v1.8.0 + github.com/fsnotify/fsnotify v1.9.0 github.com/go-sql-driver/mysql v1.7.1 github.com/golang/glog v1.2.4 github.com/golang/protobuf v1.5.4 // indirect @@ -66,15 +68,15 @@ require ( go.etcd.io/etcd/client/pkg/v3 v3.5.25 go.etcd.io/etcd/client/v3 v3.5.25 go.uber.org/mock v0.5.0 - golang.org/x/crypto v0.36.0 // indirect - golang.org/x/mod v0.24.0 // indirect - golang.org/x/net v0.38.0 - golang.org/x/oauth2 v0.28.0 - golang.org/x/sys v0.31.0 - golang.org/x/term v0.30.0 - golang.org/x/text v0.23.0 // indirect + golang.org/x/crypto v0.44.0 // indirect + golang.org/x/mod v0.30.0 // indirect + golang.org/x/net v0.47.0 + golang.org/x/oauth2 v0.33.0 + golang.org/x/sys v0.38.0 + golang.org/x/term v0.37.0 + golang.org/x/text v0.31.0 // indirect golang.org/x/time v0.11.0 - golang.org/x/tools v0.31.0 + golang.org/x/tools v0.39.0 google.golang.org/api v0.226.0 google.golang.org/genproto v0.0.0-20250313205543-e70fdf4c4cb4 // indirect google.golang.org/grpc v1.71.1 @@ -98,6 +100,7 @@ require ( github.com/bndr/gotabulate v1.1.2 github.com/dustin/go-humanize v1.0.1 github.com/gammazero/deque v1.0.0 + github.com/google/go-containerregistry v0.20.6 github.com/google/safehtml v0.1.0 github.com/hashicorp/go-version v1.7.0 github.com/kr/pretty v0.3.1 @@ -109,7 +112,7 @@ require ( github.com/xlab/treeprint v1.2.0 go.uber.org/goleak v1.3.0 golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 - golang.org/x/sync v0.12.0 + golang.org/x/sync v0.18.0 gonum.org/v1/gonum v0.15.1 modernc.org/sqlite v1.36.1 ) @@ -119,7 +122,7 @@ require ( cloud.google.com/go v0.119.0 // indirect cloud.google.com/go/auth v0.15.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect - cloud.google.com/go/compute/metadata v0.6.0 // indirect + cloud.google.com/go/compute/metadata v0.7.0 // indirect cloud.google.com/go/iam v1.4.2 // indirect cloud.google.com/go/monitoring v1.24.1 // indirect github.com/DataDog/appsec-internal-go v1.10.0 // indirect @@ -148,18 +151,24 @@ require ( github.com/aws/aws-sdk-go-v2/service/ssooidc v1.29.1 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.33.17 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/bitfield/gotestdox v0.2.2 // indirect github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 // indirect + github.com/containerd/stargz-snapshotter/estargz v0.18.0 // indirect github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/dnephin/pflag v1.0.7 // indirect + github.com/docker/cli v29.0.3+incompatible // indirect + github.com/docker/distribution v2.8.3+incompatible // indirect + github.com/docker/docker-credential-helpers v0.9.3 // indirect github.com/eapache/queue/v2 v2.0.0-20230407133247-75960ed334e4 // indirect github.com/ebitengine/purego v0.8.2 // indirect github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect github.com/fatih/color v1.18.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/s2a-go v0.1.9 // indirect @@ -186,6 +195,8 @@ require ( github.com/ncruces/go-strftime v0.1.9 // indirect github.com/onsi/ginkgo v1.16.5 // indirect github.com/onsi/gomega v1.23.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.1 // indirect github.com/outcaste-io/ristretto v0.2.3 // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect @@ -199,20 +210,22 @@ require ( github.com/sagikazarmark/locafero v0.7.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/secure-systems-lab/go-securesystemslib v0.9.0 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/cast v1.7.1 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect + github.com/vbatts/tar-split v0.12.2 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.35.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect - go.opentelemetry.io/otel v1.35.0 // indirect - go.opentelemetry.io/otel/metric v1.35.0 // indirect - go.opentelemetry.io/otel/sdk v1.35.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.35.0 // indirect - go.opentelemetry.io/otel/trace v1.35.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect + go.opentelemetry.io/otel v1.36.0 // indirect + go.opentelemetry.io/otel/metric v1.36.0 // indirect + go.opentelemetry.io/otel/sdk v1.36.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.36.0 // indirect + go.opentelemetry.io/otel/trace v1.36.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect @@ -222,6 +235,7 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + gotest.tools/gotestsum v1.13.0 // indirect modernc.org/libc v1.61.13 // indirect modernc.org/mathutil v1.7.1 // indirect modernc.org/memory v1.8.2 // indirect diff --git a/go.sum b/go.sum index fcb9f3c158b..36964cbc5eb 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ cloud.google.com/go/auth v0.15.0 h1:Ly0u4aA5vG/fsSsxu98qCQBemXtAtJf+95z9HK+cxps= cloud.google.com/go/auth v0.15.0/go.mod h1:WJDGqZ1o9E9wKIL+IwStfyn/+s59zl4Bi+1KQNVXLZ8= cloud.google.com/go/auth/oauth2adapt v0.2.7 h1:/Lc7xODdqcEw8IrZ9SvwnlLX6j9FHQM74z6cBk9Rw6M= cloud.google.com/go/auth/oauth2adapt v0.2.7/go.mod h1:NTbTTzfvPl1Y3V1nPpOgl2w6d/FjO7NNUQaWSox6ZMc= -cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= -cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= +cloud.google.com/go/compute/metadata v0.7.0 h1:PBWF+iiAerVNe8UCHxdOt6eHLVc3ydFeOCw78U8ytSU= +cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo= cloud.google.com/go/iam v1.4.2 h1:4AckGYAYsowXeHzsn/LCKWIwSWLkdb0eGjH8wWkd27Q= cloud.google.com/go/iam v1.4.2/go.mod h1:REGlrt8vSlh4dfCJfSEcNjLGq75wW75c5aU3FLOYq34= cloud.google.com/go/logging v1.13.0 h1:7j0HgAp0B94o1YRDqiqm26w4q1rDMH7XNRU34lJXHYc= @@ -129,6 +129,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 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/bitfield/gotestdox v0.2.2 h1:x6RcPAbBbErKLnapz1QeAlf3ospg8efBsedU93CDsnE= +github.com/bitfield/gotestdox v0.2.2/go.mod h1:D+gwtS0urjBrzguAkTM2wodsTQYFHdpx8eqRJ3N+9pY= github.com/bndr/gotabulate v1.1.2 h1:yC9izuZEphojb9r+KYL4W9IJKO/ceIO8HDwxMA24U4c= github.com/bndr/gotabulate v1.1.2/go.mod h1:0+8yUgaPTtLRTjf49E8oju7ojpU11YmXyvq1LbPAb3U= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= @@ -144,14 +146,17 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 h1:Om6kYQYDUk5wWbT0t0q6pvyM49i9XZAv9dDrkDA7gjk= github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/codegangsta/cli v1.20.0/go.mod h1:/qJNoX69yVSKu5o4jLyXAENLRyk1uhi7zkbQ3slBdOA= +github.com/containerd/stargz-snapshotter/estargz v0.18.0 h1:Ny5yptQgEXSkDFKvlKJGTvf1YJ+4xD8V+hXqoRG0n74= +github.com/containerd/stargz-snapshotter/estargz v0.18.0/go.mod h1:7hfU1BO2KB3axZl0dRQCdnHrIWw7TRDdK6L44Rdeuo0= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/corpix/uarand v0.1.1 h1:RMr1TWc9F4n5jiPDzFHtmaUXLKLNUFK0SgCLo4BhX/U= github.com/corpix/uarand v0.1.1/go.mod h1:SFKZvkcRoLqVRFZ4u25xPmp6m9ktANfbpXZ7SJ0/FNU= -github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= +github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/dave/jennifer v1.7.1 h1:B4jJJDHelWcDhlRQxWeo0Npa/pYKBLrirAQoTN45txo= github.com/dave/jennifer v1.7.1/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc= @@ -162,6 +167,14 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8Yc 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/dnephin/pflag v1.0.7 h1:oxONGlWxhmUct0YzKTgrpQv9AUA1wtPBn7zuSjJqptk= +github.com/dnephin/pflag v1.0.7/go.mod h1:uxE91IoWURlOiTUIA8Mq5ZZkAv3dPUfZNaT80Zm7OQE= +github.com/docker/cli v29.0.3+incompatible h1:8J+PZIcF2xLd6h5sHPsp5pvvJA+Sr2wGQxHkRl53a1E= +github.com/docker/cli v29.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= +github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8= +github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= @@ -194,8 +207,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= 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/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= -github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/gammazero/deque v1.0.0 h1:LTmimT8H7bXkkCy6gZX7zNLtkbz4NdS2z8LZuor3j34= github.com/gammazero/deque v1.0.0/go.mod h1:iflpYvtGfM3U8S8j+sZEKIak3SAKYpA5/SQewgfXDKo= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -205,8 +218,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= @@ -248,6 +261,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/go-containerregistry v0.20.6 h1:cvWX87UxxLgaH76b4hIvya6Dzz9qHB31qAwjAohdSTU= +github.com/google/go-containerregistry v0.20.6/go.mod h1:T0x8MuoAoKX/873bkeSfLD2FAkwCDf9/HZgsFJ02E2Y= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -409,6 +424,10 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.23.0 h1:/oxKu9c2HVap+F3PfKort2Hw5DEU+HGlW8n+tguWsys= github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= +github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= github.com/opentracing-contrib/go-grpc v0.1.1 h1:Ws7IN1zyiL1DFqKQPhRXuKe5pLYzMfdxnC1qtajE2PE= github.com/opentracing-contrib/go-grpc v0.1.1/go.mod h1:Nu6sz+4zzgxXu8rvKfnwjBEmHsuhTigxRwV2RhELrS8= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -492,6 +511,8 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx 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.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sjmudd/stopwatch v0.1.1 h1:x45OvxFB5OtCkjvYtzRF5fWB857Jzjjk84Oyd5C5ebw= github.com/sjmudd/stopwatch v0.1.1/go.mod h1:BLw0oIQJ1YLXBO/q9ufK/SgnKBVIkC2qrm6uy78Zw6U= github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -549,6 +570,8 @@ github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaO github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= 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/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4= +github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA= github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= @@ -570,20 +593,20 @@ go.opentelemetry.io/contrib/detectors/gcp v1.35.0 h1:bGvFt68+KTiAKFlacHW6AhA56GF go.opentelemetry.io/contrib/detectors/gcp v1.35.0/go.mod h1:qGWP8/+ILwMRIUf9uIVLloR1uo5ZYAslM4O6OqUi1DA= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= -go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= -go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= +go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= +go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0 h1:WDdP9acbMYjbKIyJUhTvtzj601sVJOqgWdUxSdR/Ysc= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0/go.mod h1:BLbf7zbNIONBLPwvFnwNHGj4zge8uTCM/UPIVW1Mq2I= -go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= -go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= -go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= -go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= -go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= -go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= -go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= -go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= +go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= +go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= +go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= +go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= +go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis= +go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= +go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= +go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= @@ -606,8 +629,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/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.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU= +golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= @@ -618,8 +641,8 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= -golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= +golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= 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= @@ -639,12 +662,12 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= -golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= 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.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= -golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= +golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo= +golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= 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= @@ -653,8 +676,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= 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= @@ -688,18 +711,19 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= -golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -713,8 +737,8 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= -golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= +golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= +golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= 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= @@ -786,6 +810,10 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/gotestsum v1.13.0 h1:+Lh454O9mu9AMG1APV4o0y7oDYKyik/3kBOiCqiEpRo= +gotest.tools/gotestsum v1.13.0/go.mod h1:7f0NS5hFb0dWr4NtcsAsF0y1kzjEFfAil0HiBQJE03Q= +gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= +gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= modernc.org/cc/v4 v4.24.4 h1:TFkx1s6dCkQpd6dKurBNmpo+G8Zl4Sq/ztJ+2+DEsh0= diff --git a/go/cmd/vtctldclient/command/vreplication/common/utils.go b/go/cmd/vtctldclient/command/vreplication/common/utils.go index ff6d264be66..d6e2a3fae76 100644 --- a/go/cmd/vtctldclient/command/vreplication/common/utils.go +++ b/go/cmd/vtctldclient/command/vreplication/common/utils.go @@ -190,9 +190,11 @@ func ParseTableMaterializeSettings(tableSettings string, parser *sqlparser.Parse } func validateOnDDL(cmd *cobra.Command) error { - if _, ok := binlogdatapb.OnDDLAction_value[strings.ToUpper(CreateOptions.OnDDL)]; !ok { + normalized := strings.ToUpper(CreateOptions.OnDDL) + if _, ok := binlogdatapb.OnDDLAction_value[normalized]; !ok { return fmt.Errorf("invalid on-ddl value: %s", CreateOptions.OnDDL) } + CreateOptions.OnDDL = normalized return nil } diff --git a/go/cmd/vtctldclient/command/vreplication/common/utils_test.go b/go/cmd/vtctldclient/command/vreplication/common/utils_test.go index 39de482da2c..5768a4f00bb 100644 --- a/go/cmd/vtctldclient/command/vreplication/common/utils_test.go +++ b/go/cmd/vtctldclient/command/vreplication/common/utils_test.go @@ -110,6 +110,48 @@ func TestParseAndValidateCreateOptions(t *testing.T) { require.Equal(t, cells, common.CreateOptions.Cells) }, }, + { + name: "invalid on-ddl value", + setFunc: func(cmd *cobra.Command) error { + onDDLFlag := cmd.Flags().Lookup("on-ddl") + if err := onDDLFlag.Value.Set("INVALID"); err != nil { + return err + } + onDDLFlag.Changed = true + return nil + }, + wantErr: true, + }, + { + name: "valid on-ddl normalizes to uppercase", + setFunc: func(cmd *cobra.Command) error { + onDDLFlag := cmd.Flags().Lookup("on-ddl") + if err := onDDLFlag.Value.Set("exec"); err != nil { + return err + } + onDDLFlag.Changed = true + return nil + }, + wantErr: false, + checkFunc: func() { + require.Equal(t, "EXEC", common.CreateOptions.OnDDL) + }, + }, + { + name: "valid on-ddl EXEC_IGNORE", + setFunc: func(cmd *cobra.Command) error { + onDDLFlag := cmd.Flags().Lookup("on-ddl") + if err := onDDLFlag.Value.Set("exec_ignore"); err != nil { + return err + } + onDDLFlag.Changed = true + return nil + }, + wantErr: false, + checkFunc: func() { + require.Equal(t, "EXEC_IGNORE", common.CreateOptions.OnDDL) + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/go/cmd/zkctl/command/teardown.go b/go/cmd/zkctl/command/teardown.go index 14fe7278835..791ac2cf4a4 100644 --- a/go/cmd/zkctl/command/teardown.go +++ b/go/cmd/zkctl/command/teardown.go @@ -16,14 +16,25 @@ limitations under the License. package command -import "github.com/spf13/cobra" +import ( + "time" + + "github.com/spf13/cobra" +) var Teardown = &cobra.Command{ Use: "teardown", Short: "Shuts down the zookeeper server and removes its data dir.", Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { - return zkd.Teardown() + var err error + for range 3 { + if err = zkd.Teardown(); err == nil { + break + } + time.Sleep(1 * time.Second) + } + return err }, } diff --git a/go/flags/endtoend/vtbackup.txt b/go/flags/endtoend/vtbackup.txt index a274e881092..9e5184b1521 100644 --- a/go/flags/endtoend/vtbackup.txt +++ b/go/flags/endtoend/vtbackup.txt @@ -131,6 +131,7 @@ Flags: --external-compressor string command with arguments to use when compressing a backup. --external-compressor-extension string extension to use when using an external compressor. --external-decompressor string command with arguments to use when decompressing a backup. + --external-decompressor-use-manifest allows the decompressor command stored in the backup manifest to be used at restore time. Enabling this is a security risk: an attacker with write access to the backup storage could modify the manifest to execute arbitrary commands on the tablet as the Vitess user. NOT RECOMMENDED. --file_backup_storage_root string Root directory for the file backup storage. --gcs_backup_storage_bucket string Google Cloud Storage bucket to use for backups. --gcs_backup_storage_root string Root prefix for all backup-related object names. diff --git a/go/flags/endtoend/vtcombo.txt b/go/flags/endtoend/vtcombo.txt index acd659516c5..a68845cb16f 100644 --- a/go/flags/endtoend/vtcombo.txt +++ b/go/flags/endtoend/vtcombo.txt @@ -131,6 +131,7 @@ Flags: --external-compressor string command with arguments to use when compressing a backup. --external-compressor-extension string extension to use when using an external compressor. --external-decompressor string command with arguments to use when decompressing a backup. + --external-decompressor-use-manifest allows the decompressor command stored in the backup manifest to be used at restore time. Enabling this is a security risk: an attacker with write access to the backup storage could modify the manifest to execute arbitrary commands on the tablet as the Vitess user. NOT RECOMMENDED. --external_topo_server Should vtcombo use an external topology server instead of starting its own in-memory topology server. If true, vtcombo will use the flags defined in topo/server.go to open topo server --foreign_key_mode string This is to provide how to handle foreign key constraint in create/alter table. Valid values are: allow, disallow (default "allow") --gate_query_cache_memory int gate server query cache size in bytes, maximum amount of memory to be cached. vtgate analyzes every incoming query and generate a query plan, these plans are being cached in a lru cache. This config controls the capacity of the lru cache. (default 33554432) diff --git a/go/flags/endtoend/vttablet.txt b/go/flags/endtoend/vttablet.txt index 04eb16edc25..0eeec3f2bec 100644 --- a/go/flags/endtoend/vttablet.txt +++ b/go/flags/endtoend/vttablet.txt @@ -155,6 +155,7 @@ Flags: --external-compressor string command with arguments to use when compressing a backup. --external-compressor-extension string extension to use when using an external compressor. --external-decompressor string command with arguments to use when decompressing a backup. + --external-decompressor-use-manifest allows the decompressor command stored in the backup manifest to be used at restore time. Enabling this is a security risk: an attacker with write access to the backup storage could modify the manifest to execute arbitrary commands on the tablet as the Vitess user. NOT RECOMMENDED. --file_backup_storage_root string Root directory for the file backup storage. --filecustomrules string file based custom rule path --filecustomrules_watch set up a watch on the target file and reload query rules when it changes diff --git a/go/flags/endtoend/vttestserver.txt b/go/flags/endtoend/vttestserver.txt index 385b7194652..eee43552002 100644 --- a/go/flags/endtoend/vttestserver.txt +++ b/go/flags/endtoend/vttestserver.txt @@ -38,6 +38,7 @@ Flags: --external-compressor string command with arguments to use when compressing a backup. --external-compressor-extension string extension to use when using an external compressor. --external-decompressor string command with arguments to use when decompressing a backup. + --external-decompressor-use-manifest allows the decompressor command stored in the backup manifest to be used at restore time. Enabling this is a security risk: an attacker with write access to the backup storage could modify the manifest to execute arbitrary commands on the tablet as the Vitess user. NOT RECOMMENDED. --external_topo_global_root string the path of the global topology data in the global topology server for vtcombo process --external_topo_global_server_address string the address of the global topology server for vtcombo process --external_topo_implementation string the topology implementation to use for vtcombo process diff --git a/go/hack/ensure_swiss_map.go b/go/hack/ensure_swiss_map.go index b09bde1121c..f57d1fb3e1a 100644 --- a/go/hack/ensure_swiss_map.go +++ b/go/hack/ensure_swiss_map.go @@ -1,4 +1,4 @@ -//go:build !goexperiment.swissmap +//go:build !goexperiment.swissmap && !go1.26 /* Copyright (c) 2009 The Go Authors. All rights reserved. @@ -32,7 +32,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // This is invalid Go code, and it will fail to compile if you disable // Swiss maps when building Vitess. Our runtime memory accounting system -// expects the map implementation in Go 1.24 to be Swiss. +// expects the map implementation in Go 1.24 and 1.25 to be Swiss. +// In Go 1.26 and later, Swiss maps are always enabled. package hack diff --git a/go/mysql/auth_server_static_test.go b/go/mysql/auth_server_static_test.go index ee7815d0647..70a5517adf9 100644 --- a/go/mysql/auth_server_static_test.go +++ b/go/mysql/auth_server_static_test.go @@ -24,6 +24,7 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "vitess.io/vitess/go/test/utils" @@ -177,11 +178,9 @@ func hupTest(t *testing.T, aStatic *AuthServerStatic, tmpFile *os.File, oldStr, require.Equal(t, oldStr, aStatic.getEntries()[oldStr][0].Password, "%s's Password should still be '%s'", oldStr, oldStr) syscall.Kill(syscall.Getpid(), syscall.SIGHUP) - time.Sleep(100 * time.Millisecond) - // wait for signal handler - require.Nil(t, aStatic.getEntries()[oldStr], "Should not have old %s after config reload", oldStr) - require.Equal(t, newStr, aStatic.getEntries()[newStr][0].Password, "%s's Password should be '%s'", newStr, newStr) + // wait for signal handler + waitForReload(t, aStatic, oldStr, newStr) } func hupTestWithRotation(t *testing.T, aStatic *AuthServerStatic, tmpFile *os.File, oldStr, newStr string) { @@ -190,11 +189,28 @@ func hupTestWithRotation(t *testing.T, aStatic *AuthServerStatic, tmpFile *os.Fi t.Fatalf("couldn't overwrite temp file: %v", err) } - time.Sleep(20 * time.Millisecond) - // wait for signal handler - require.Nil(t, aStatic.getEntries()[oldStr], "Should not have old %s after config reload", oldStr) - require.Equal(t, newStr, aStatic.getEntries()[newStr][0].Password, "%s's Password should be '%s'", newStr, newStr) + waitForReload(t, aStatic, oldStr, newStr) +} +// waitForReload polls aStatic until the auth file reload has dropped oldStr +// and installed newStr. +// +// We use `assert.X(c, ...)` (not `require.X`) inside the callback because +// testify v1.9 on this branch implements `CollectT.FailNow` as +// `panic("Assertion failed")`, and `EventuallyWithT` doesn't recover from +// that — a failed poll would crash the test instead of being retried. We +// also gate the `[0]` indexing on `NotEmpty` for the same reason: a panic +// inside the callback (e.g. `nil[0]`) escapes the goroutine. +func waitForReload(t *testing.T, aStatic *AuthServerStatic, oldStr, newStr string) { + t.Helper() + require.EventuallyWithT(t, func(c *assert.CollectT) { + assert.Nil(c, aStatic.getEntries()[oldStr], "Should not have old %s after config reload", oldStr) + entries := aStatic.getEntries()[newStr] + if !assert.NotEmpty(c, entries, "Should have new %s entries after config reload", newStr) { + return + } + assert.Equal(c, newStr, entries[0].Password, "%s's Password should be '%s'", newStr, newStr) + }, 30*time.Second, 10*time.Millisecond, "config should be reloaded with new file after rotation") } func TestStaticMysqlNativePasswords(t *testing.T) { diff --git a/go/mysql/binlog/binlog_json.go b/go/mysql/binlog/binlog_json.go index 51b4fef0ef8..f647a4f130e 100644 --- a/go/mysql/binlog/binlog_json.go +++ b/go/mysql/binlog/binlog_json.go @@ -449,11 +449,25 @@ func binparserLiteral(_ jsonDataType, data []byte, pos int) (node *json.Value, e // other types are stored as catch-all opaque types: documentation on these is scarce. // we currently know about (and support) date/time/datetime/decimal. func binparserOpaque(_ jsonDataType, data []byte, pos int) (node *json.Value, err error) { - dataType := data[pos] - start := 3 // account for length of stored value - end := start + 8 // all currently supported opaque data types are 8 bytes in size + if pos >= len(data) { + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "opaque JSON field value missing type at position %d", pos) + } + typePos := pos + dataType := data[typePos] + pos = typePos + 1 + if pos >= len(data) { + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "opaque JSON field value missing length at position %d", typePos) + } + length, start := readVariableLength(data, pos) + end := start + length + if start > len(data) || end > len(data) { + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "opaque JSON field value length %d exceeds available bytes", length) + } switch dataType { case TypeDate: + if length < 8 { + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "opaque date length %d is too short", length) + } raw := binary.LittleEndian.Uint64(data[start:end]) value := raw >> 24 yearMonth := (value >> 22) & 0x01ffff // 17 bits starting at 22nd @@ -463,6 +477,9 @@ func binparserOpaque(_ jsonDataType, data []byte, pos int) (node *json.Value, er dateString := fmt.Sprintf("%04d-%02d-%02d", year, month, day) node = json.NewDate(dateString) case TypeTime2, TypeTime: + if length < 8 { + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "opaque time length %d is too short", length) + } raw := binary.LittleEndian.Uint64(data[start:end]) value := raw >> 24 hour := (value >> 12) & 0x03ff // 10 bits starting at 12th @@ -472,6 +489,9 @@ func binparserOpaque(_ jsonDataType, data []byte, pos int) (node *json.Value, er timeString := fmt.Sprintf("%02d:%02d:%02d.%06d", hour, minute, second, microSeconds) node = json.NewTime(timeString) case TypeDateTime2, TypeDateTime, TypeTimestamp2, TypeTimestamp: + if length < 8 { + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "opaque datetime length %d is too short", length) + } raw := binary.LittleEndian.Uint64(data[start:end]) value := raw >> 24 yearMonth := (value >> 22) & 0x01ffff // 17 bits starting at 22nd @@ -485,6 +505,9 @@ func binparserOpaque(_ jsonDataType, data []byte, pos int) (node *json.Value, er timeString := fmt.Sprintf("%04d-%02d-%02d %02d:%02d:%02d.%06d", year, month, day, hour, minute, second, microSeconds) node = json.NewDateTime(timeString) case TypeDecimal, TypeNewDecimal: + if length < 2 { + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "opaque decimal length %d is too short", length) + } decimalData := data[start:end] precision := decimalData[0] scale := decimalData[1] @@ -495,11 +518,11 @@ func binparserOpaque(_ jsonDataType, data []byte, pos int) (node *json.Value, er } node = json.NewNumber(val.ToString(), json.NumberTypeDecimal) case TypeVarchar, TypeVarString, TypeString, TypeBlob, TypeTinyBlob, TypeMediumBlob, TypeLongBlob: - node = json.NewBlob(string(data[pos+1:])) + node = json.NewBlob(string(data[start:end])) case TypeBit: - node = json.NewBit(string(data[pos+1:])) + node = json.NewBit(string(data[start:end])) default: - node = json.NewOpaqueValue(string(data[pos+1:])) + node = json.NewOpaqueValue(string(data[start:end])) } return node, nil } diff --git a/go/mysql/binlog/binlog_json_test.go b/go/mysql/binlog/binlog_json_test.go index 5652b58567e..59cfffcbab9 100644 --- a/go/mysql/binlog/binlog_json_test.go +++ b/go/mysql/binlog/binlog_json_test.go @@ -232,19 +232,24 @@ func TestBinaryJSON(t *testing.T) { expected: json.NewNumber("123456789.1234", json.NumberTypeDecimal), }, { - name: `bit literal [2 202 254]`, + name: `small decimal "1.99"`, + data: []byte{15, 246, 4, 3, 2, 0x81, 0x63}, + expected: json.NewNumber("1.99", json.NumberTypeDecimal), + }, + { + name: `bit literal 0xCAFE`, data: []byte{15, 16, 2, 202, 254}, - expected: json.NewBit(string([]byte{2, 202, 254})), + expected: json.NewBit(string([]byte{202, 254})), }, { - name: `opaque string [2 202 254]`, + name: `opaque string 0xCAFE`, data: []byte{15, 15, 2, 202, 254}, - expected: json.NewBlob(string([]byte{2, 202, 254})), + expected: json.NewBlob(string([]byte{202, 254})), }, { - name: `opaque blob [2 202 254]`, + name: `opaque blob 0xCAFE`, data: []byte{15, 252, 2, 202, 254}, - expected: json.NewBlob(string([]byte{2, 202, 254})), + expected: json.NewBlob(string([]byte{202, 254})), }, } for _, tc := range testcases { @@ -256,6 +261,36 @@ func TestBinaryJSON(t *testing.T) { } } +func TestBinaryJSONOpaqueErrors(t *testing.T) { + testcases := []struct { + name string + data []byte + expectedErr string + }{ + { + name: "opaque length exceeds payload", + data: []byte{15, 252, 2, 202}, + expectedErr: "opaque JSON field value length 2 exceeds available bytes", + }, + { + name: "opaque date too short", + data: []byte{15, 10, 4, 0, 0, 0, 0}, + expectedErr: "opaque date length 4 is too short", + }, + { + name: "opaque decimal too short", + data: []byte{15, 246, 1, 0x01}, + expectedErr: "opaque decimal length 1 is too short", + }, + } + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + _, err := ParseBinaryJSON(tc.data) + require.ErrorContains(t, err, tc.expectedErr) + }) + } +} + func TestMarshalJSONToSQL(t *testing.T) { testcases := []struct { name string @@ -443,19 +478,20 @@ func TestMarshalJSONToSQL(t *testing.T) { expected: `CAST(123456789.1234 as JSON)`, }, { - name: `bit literal [2 202 254]`, + // 0xCAFE = 51966 = binary 1100101011111110 (16 bits) + name: `bit literal 0xCAFE`, data: []byte{15, 16, 2, 202, 254}, - expected: `CAST(b'101100101011111110' as JSON)`, + expected: `CAST(b'1100101011111110' as JSON)`, }, { - name: `opaque string [2 202 254]`, + name: `opaque string 0xCAFE`, data: []byte{15, 15, 2, 202, 254}, - expected: `CAST(x'02CAFE' as JSON)`, + expected: `CAST(x'CAFE' as JSON)`, }, { - name: `opaque blob [2 202 254]`, + name: `opaque blob 0xCAFE`, data: []byte{15, 252, 2, 202, 254}, - expected: `CAST(x'02CAFE' as JSON)`, + expected: `CAST(x'CAFE' as JSON)`, }, } for _, tc := range testcases { diff --git a/go/mysql/json/marshal_test.go b/go/mysql/json/marshal_test.go index 9329c3cd49a..d59f15a4892 100644 --- a/go/mysql/json/marshal_test.go +++ b/go/mysql/json/marshal_test.go @@ -20,6 +20,8 @@ import ( "testing" "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/sqltypes" ) func TestMarshalSQLTo(t *testing.T) { @@ -55,3 +57,31 @@ func TestMarshalSQLTo(t *testing.T) { }) } } + +// TestMarshalSQLValuePreservesControlByte verifies that JSON control bytes +// are preserved when marshaled into SQL. +func TestMarshalSQLValuePreservesControlByte(t *testing.T) { + raw := "Foo Bar" + string([]byte{26}) + "a" + + val := NewString(raw) + + got, err := MarshalSQLValue(val.MarshalTo(nil)) + require.NoError(t, err) + + expected := "CAST(JSON_QUOTE(_utf8mb4" + sqltypes.EncodeStringSQL(raw) + ") as JSON)" + require.Equal(t, expected, string(got.Raw())) +} + +// TestMarshalSQLValueNormalizesInvalidUTF8 verifies that JSON string +// marshaling normalizes invalid UTF-8 before producing SQL. +func TestMarshalSQLValueNormalizesInvalidUTF8(t *testing.T) { + raw := string([]byte{0xff, 0xfe, 'A'}) + val := NewString(raw) + + got, err := MarshalSQLValue(val.MarshalTo(nil)) + require.NoError(t, err) + + normalized := string([]rune(raw)) + expected := "CAST(JSON_QUOTE(_utf8mb4" + sqltypes.EncodeStringSQL(normalized) + ") as JSON)" + require.Equal(t, expected, string(got.Raw())) +} diff --git a/go/mysql/json/parser.go b/go/mysql/json/parser.go index 02225c7db24..03912e9c683 100644 --- a/go/mysql/json/parser.go +++ b/go/mysql/json/parser.go @@ -26,6 +26,7 @@ import ( "strings" "time" "unicode/utf16" + "unicode/utf8" "vitess.io/vitess/go/mysql/fastparse" @@ -311,7 +312,18 @@ func parseObject(s string, c *cache, depth int) (*Value, string, error) { } } +const hexDigits = "0123456789abcdef" + +// escapeString appends s as a JSON string to dst and returns the result. +// +// The output uses JSON compliant escapes for control bytes and only uses the +// short escape sequences for \b, \f, \n, \r, and \t. func escapeString(dst []byte, s string) []byte { + // If we have invalid UTF-8, normalize it so JSON output stays valid. + if !utf8.ValidString(s) { + s = string([]rune(s)) + } + if !hasSpecialChars(s) { // Fast path - nothing to escape. dst = append(dst, '"') @@ -320,8 +332,43 @@ func escapeString(dst []byte, s string) []byte { return dst } - // Slow path. - return strconv.AppendQuote(dst, s) + dst = append(dst, '"') + + // Escape control bytes, quotes, and backslashes. + for i := 0; i < len(s); i++ { + ch := s[i] + + switch ch { + case '"', '\\': + dst = append(dst, '\\', ch) + case '\b': // 0x08, backspace + dst = append(dst, '\\', 'b') + case '\f': // 0x0C, form feed + dst = append(dst, '\\', 'f') + case '\n': // 0x0A, line feed + dst = append(dst, '\\', 'n') + case '\r': // 0x0D, carriage return + dst = append(dst, '\\', 'r') + case '\t': // 0x09, horizontal tab + dst = append(dst, '\\', 't') + default: + // Other control characters (0x00-0x1F) use \u00XX escapes. + // We hardcode 00 since we only handle single byte control + // characters, then split the byte into two 4-bit halves; + // ch>>4 extracts the upper bits, and ch&0x0f extracts the lower + // bits. Each then indexes into hexDigits to produce the final + // two hex characters. + if ch < 0x20 { + dst = append(dst, '\\', 'u', '0', '0', hexDigits[ch>>4], hexDigits[ch&0x0f]) + continue + } + + dst = append(dst, ch) + } + } + + dst = append(dst, '"') + return dst } func hasSpecialChars(s string) bool { diff --git a/go/mysql/server_test.go b/go/mysql/server_test.go index 781c142e7eb..6bd4b71ce6b 100644 --- a/go/mysql/server_test.go +++ b/go/mysql/server_test.go @@ -1024,7 +1024,17 @@ func TestTLSRequired(t *testing.T) { params.SslCert = path.Join(root, "revoked-client-cert.pem") params.SslKey = path.Join(root, "revoked-client-key.pem") conn, err = connectWithGoneServerHandling() - require.ErrorContains(t, err, "remote error: tls: bad certificate") + // On a happy day the client reads the server's TLS `bad_certificate` + // alert; on a less happy day the server's TCP close races ahead of the + // alert and the client sees `connection reset by peer` / `broken pipe`. + // Either outcome means the revoked cert was rejected, which is what the + // test cares about — so accept both. + errStr := err.Error() + require.True(t, + strings.Contains(errStr, "remote error: tls: bad certificate") || + strings.Contains(errStr, "connection reset by peer") || + strings.Contains(errStr, "broken pipe"), + "expected revoked-cert connection to be rejected, got: %v", err) if conn != nil { conn.Close() } diff --git a/go/mysql/sqlerror/constants.go b/go/mysql/sqlerror/constants.go index 9ac29ef7d9f..8f725f02585 100644 --- a/go/mysql/sqlerror/constants.go +++ b/go/mysql/sqlerror/constants.go @@ -104,6 +104,7 @@ const ( ERDupUnique = ErrorCode(1169) ERRequiresPrimaryKey = ErrorCode(1173) ERCantDoThisDuringAnTransaction = ErrorCode(1179) + ERMasterInfo = ErrorCode(1201) ERReadOnlyTransaction = ErrorCode(1207) ERCannotAddForeign = ErrorCode(1215) ERNoReferencedRow = ErrorCode(1216) @@ -126,7 +127,17 @@ const ( ErNoReferencedRow2 = ErrorCode(1452) ERInnodbIndexCorrupt = ErrorCode(1817) ERDupIndex = ErrorCode(1831) - ERInnodbReadOnly = ErrorCode(1874) + + // MySQL used 1871/1872 for master-info and relay-log-info initialization + // errors through 8.0.32, and reassigned those numbers in 8.0.33 to + // connection-metadata and applier-metadata initialization errors. These + // errnos therefore map to different metadata types depending on version. + ERReplicaMasterInfoInitRepository = ErrorCode(1871) + ERReplicaRelayLogInfoInitRepository = ErrorCode(1872) + ERReplicaConnectionMetadataInitRepository = ErrorCode(1871) + ERReplicaApplierMetadataInitRepository = ErrorCode(1872) + + ERInnodbReadOnly = ErrorCode(1874) ERVectorConversion = ErrorCode(6138) diff --git a/go/mysql/sqlerror/sql_error.go b/go/mysql/sqlerror/sql_error.go index 4600f0927cc..b7a7c6dc6c0 100644 --- a/go/mysql/sqlerror/sql_error.go +++ b/go/mysql/sqlerror/sql_error.go @@ -93,10 +93,23 @@ func (se *SQLError) SQLState() string { return se.State } -var errExtract = regexp.MustCompile(`\(errno ([0-9]*)\) \(sqlstate ([0-9a-zA-Z]{5})\)`) +var ( + // errExtract matches Vitess-wrapped SQL errors ending with `(errno ) (sqlstate )`. + errExtract = regexp.MustCompile(`\(errno ([0-9]*)\) \(sqlstate ([0-9a-zA-Z]{5})\)`) + + // nativeErrExtract matches native MySQL server errors using `ERROR (): `. + nativeErrExtract = regexp.MustCompile(`ERROR ([0-9]*) \(([0-9a-zA-Z]{5})\):`) +) // NewSQLErrorFromError returns a *SQLError from the provided error. -// If it's not the right type, it still tries to get it from a regexp. +// +// - If err already is a *SQLError, it returns err unchanged. +// - If err is a Vitess error with a mapped MySQL code, it returns the converted SQLError. +// - If err contains a Vitess-wrapped `(errno ) (sqlstate )` suffix, it extracts that code and state. +// - If err contains a native MySQL `ERROR (): ` string, it extracts that code and state. +// - Otherwise, it maps the Vitess error code to a MySQL error code when one is defined and returns +// a generic SQLError with that code and err.Error() as the message. +// // Notes about the `error` return type: // The function really returns *SQLError or `nil`. Seemingly, the function could just return // `*SQLError` type. However, it really must return `error`. The reason is the way `golang` @@ -128,6 +141,11 @@ func NewSQLErrorFromError(err error) error { return extractSQLErrorFromMessage(match, msg) } + match = nativeErrExtract.FindStringSubmatch(msg) + if len(match) >= 2 { + return extractSQLErrorFromMessage(match, msg) + } + return mapToSQLErrorFromErrorCode(err, msg) } diff --git a/go/mysql/sqlerror/sql_error_test.go b/go/mysql/sqlerror/sql_error_test.go index 9e73138d60f..9c05cdd2190 100644 --- a/go/mysql/sqlerror/sql_error_test.go +++ b/go/mysql/sqlerror/sql_error_test.go @@ -54,7 +54,7 @@ func TestDemuxResourceExhaustedErrors(t *testing.T) { } func TestNewSQLErrorFromError(t *testing.T) { - var tCases = []struct { + tCases := []struct { err error num ErrorCode ha HandlerErrorCode @@ -155,6 +155,16 @@ func TestNewSQLErrorFromError(t *testing.T) { num: ERNoDb, ss: SSNoDB, }, + { + err: fmt.Errorf("ERROR 1201 (HY000): Could not initialize master info structure; more error messages can be found in the MySQL error log"), + num: ERMasterInfo, + ss: SSUnknownSQLState, + }, + { + err: fmt.Errorf("ERROR 1872 (HY000): Replica failed to initialize applier metadata structure from the repository"), + num: ERReplicaApplierMetadataInitRepository, + ss: SSUnknownSQLState, + }, { err: fmt.Errorf("just some random text here"), num: ERUnknownError, diff --git a/go/sqltypes/proto3.go b/go/sqltypes/proto3.go index 73e2faf654c..b9500bd5cb2 100644 --- a/go/sqltypes/proto3.go +++ b/go/sqltypes/proto3.go @@ -135,7 +135,7 @@ func CustomProto3ToResult(fields []*querypb.Field, qr *querypb.QueryResult) *Res return nil } return &Result{ - Fields: qr.Fields, + Fields: fields, RowsAffected: qr.RowsAffected, InsertID: qr.InsertId, InsertIDChanged: qr.InsertIdChanged, diff --git a/go/test/endtoend/backup/vtbackup/backup_only_test.go b/go/test/endtoend/backup/vtbackup/backup_only_test.go index 0ad25301af0..89871fe14f6 100644 --- a/go/test/endtoend/backup/vtbackup/backup_only_test.go +++ b/go/test/endtoend/backup/vtbackup/backup_only_test.go @@ -435,7 +435,7 @@ func verifyDisableEnableRedoLogs(ctx context.Context, t *testing.T, mysqlSocket // MY-013600 // https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html#error_er_ib_wrn_redo_disabled - qr, err = conn.ExecuteFetch("SELECT 1 FROM performance_schema.error_log WHERE error_code = 'MY-013600'", 1, false) + qr, err = conn.ExecuteFetch("SELECT 1 FROM performance_schema.error_log WHERE data like '%InnoDB redo logging is disabled%'", 1, false) require.NoError(t, err) if len(qr.Rows) != 1 { // Keep trying, possible we haven't disabled yet. @@ -444,7 +444,7 @@ func verifyDisableEnableRedoLogs(ctx context.Context, t *testing.T, mysqlSocket // MY-013601 // https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html#error_er_ib_wrn_redo_enabled - qr, err = conn.ExecuteFetch("SELECT 1 FROM performance_schema.error_log WHERE error_code = 'MY-013601'", 1, false) + qr, err = conn.ExecuteFetch("SELECT 1 FROM performance_schema.error_log WHERE data like '%InnoDB redo logging is enabled%'", 1, false) require.NoError(t, err) if len(qr.Rows) != 1 { // Keep trying, possible we haven't disabled yet. diff --git a/go/test/endtoend/backup/vtctlbackup/backup_test.go b/go/test/endtoend/backup/vtctlbackup/backup_test.go index be9e5bbf490..be80d097c9b 100644 --- a/go/test/endtoend/backup/vtctlbackup/backup_test.go +++ b/go/test/endtoend/backup/vtctlbackup/backup_test.go @@ -60,6 +60,7 @@ func TestBuiltinBackupWithExternalZstdCompressionAndManifestedDecompressor(t *te CompressorEngineName: "external", ExternalCompressorCmd: "zstd", ExternalCompressorExt: ".zst", + ExternalDecompressorUseManifest: true, ManifestExternalDecompressorCmd: "zstd -d", } diff --git a/go/test/endtoend/backup/vtctlbackup/backup_utils.go b/go/test/endtoend/backup/vtctlbackup/backup_utils.go index e92ba516ff3..a3ce59e513a 100644 --- a/go/test/endtoend/backup/vtctlbackup/backup_utils.go +++ b/go/test/endtoend/backup/vtctlbackup/backup_utils.go @@ -92,6 +92,7 @@ type CompressionDetails struct { ExternalCompressorCmd string ExternalCompressorExt string ExternalDecompressorCmd string + ExternalDecompressorUseManifest bool ManifestExternalDecompressorCmd string } @@ -131,7 +132,7 @@ func LaunchCluster(setupType int, streamMode string, stripes int, cDetails *Comp return 1, err } newInitDBFile = path.Join(localCluster.TmpDirectory, "init_db_with_passwords.sql") - err = os.WriteFile(newInitDBFile, []byte(sql), 0666) + err = os.WriteFile(newInitDBFile, []byte(sql), 0o666) if err != nil { return 1, err } @@ -305,6 +306,9 @@ func getCompressorArgs(cDetails *CompressionDetails) []string { if cDetails.ExternalDecompressorCmd != "" { args = append(args, fmt.Sprintf("--external-decompressor=%s", cDetails.ExternalDecompressorCmd)) } + if cDetails.ExternalDecompressorUseManifest { + args = append(args, "--external-decompressor-use-manifest") + } if cDetails.ManifestExternalDecompressorCmd != "" { args = append(args, fmt.Sprintf("--manifest-external-decompressor=%s", cDetails.ManifestExternalDecompressorCmd)) } @@ -543,10 +547,10 @@ func primaryBackup(t *testing.T) { _, err = primary.VttabletProcess.QueryTablet("DROP TABLE vt_insert_test", keyspaceName, true) require.NoError(t, err) + + restartPrimaryAndReplica(t) } -// Test a primary and replica from the same backup. -// // Check that a replica and primary both restored from the same backup // can replicate successfully. func primaryReplicaSameBackup(t *testing.T) { diff --git a/go/test/endtoend/backup/xtrabackup/xtrabackup_test.go b/go/test/endtoend/backup/xtrabackup/xtrabackup_test.go index 3402a170310..e18f229d9cb 100644 --- a/go/test/endtoend/backup/xtrabackup/xtrabackup_test.go +++ b/go/test/endtoend/backup/xtrabackup/xtrabackup_test.go @@ -59,6 +59,7 @@ func TestXtrabackupWithExternalZstdCompressionAndManifestedDecompressor(t *testi CompressorEngineName: "external", ExternalCompressorCmd: "zstd", ExternalCompressorExt: ".zst", + ExternalDecompressorUseManifest: true, ManifestExternalDecompressorCmd: "zstd -d", } diff --git a/go/test/endtoend/cluster/vttablet_process.go b/go/test/endtoend/cluster/vttablet_process.go index 8fbe4be54d9..73fa2b01b3f 100644 --- a/go/test/endtoend/cluster/vttablet_process.go +++ b/go/test/endtoend/cluster/vttablet_process.go @@ -410,6 +410,20 @@ func (vttablet *VttabletProcess) TearDown() error { return vttablet.TearDownWithTimeout(vttabletStateTimeout) } +func (vttablet *VttabletProcess) Stop() { + if vttablet.proc == nil || vttablet.exit == nil { + return + } + vttablet.proc.Process.Signal(syscall.SIGSTOP) +} + +func (vttablet *VttabletProcess) Resume() { + if vttablet.proc == nil || vttablet.exit == nil { + return + } + vttablet.proc.Process.Signal(syscall.SIGCONT) +} + // Kill shuts down the running vttablet service immediately. func (vttablet *VttabletProcess) Kill() error { if vttablet.proc == nil || vttablet.exit == nil { diff --git a/go/test/endtoend/onlineddl/scheduler/onlineddl_scheduler_test.go b/go/test/endtoend/onlineddl/scheduler/onlineddl_scheduler_test.go index 84ffbe20f5e..9f3adcf887c 100644 --- a/go/test/endtoend/onlineddl/scheduler/onlineddl_scheduler_test.go +++ b/go/test/endtoend/onlineddl/scheduler/onlineddl_scheduler_test.go @@ -23,6 +23,7 @@ import ( "math/rand/v2" "os" "path" + "strconv" "strings" "sync" "testing" @@ -242,7 +243,7 @@ func TestMain(m *testing.M) { defer clusterInstance.Teardown() if _, err := os.Stat(schemaChangeDirectory); os.IsNotExist(err) { - _ = os.Mkdir(schemaChangeDirectory, 0700) + _ = os.Mkdir(schemaChangeDirectory, 0o700) } clusterInstance.VtctldExtraArgs = []string{ @@ -294,11 +295,9 @@ func TestMain(m *testing.M) { } else { os.Exit(exitcode) } - } func TestSchedulerSchemaChanges(t *testing.T) { - throttler.EnableLagThrottlerAndWaitForStatus(t, clusterInstance) t.Run("scheduler", testScheduler) @@ -792,6 +791,117 @@ func testScheduler(t *testing.T) { }) }) } + + t.Run("low wait_timeout", func(t *testing.T) { + // Validate that OnlineDDL cutover increases wait_timeout on its connections + // when the server has a low wait_timeout configured. Without this protection, + // MySQL would kill cutover connections mid-operation, potentially causing + // data corruption. + ctx, cancel := context.WithTimeout(t.Context(), extendedWaitTime*5) + defer cancel() + + // Read the original wait_timeout. + rs, err := primaryTablet.VttabletProcess.QueryTabletWithDB("select @@global.wait_timeout as wait_timeout", "performance_schema") + require.NoError(t, err) + row := rs.Named().Row() + require.NotNil(t, row) + originalWaitTimeout := row.AsInt64("wait_timeout", 0) + require.NotZero(t, originalWaitTimeout) + + // Ensure the table exists (may not if running this subtest in isolation). + t.Run("ensure table exists", func(t *testing.T) { + uuid := testOnlineDDLStatement(t, createParams(createT1IfNotExistsStatement, ddlStrategy, "vtgate", "", "", false)) + onlineddl.CheckMigrationStatus(t, &vtParams, shards, uuid, schema.OnlineDDLStatusComplete) + }) + + t1uuid = testOnlineDDLStatement(t, createParams(trivialAlterT1Statement, ddlStrategy+" --postpone-completion", "vtgate", "", "", true)) // skip wait + + t.Run("wait for t1 running", func(t *testing.T) { + status := onlineddl.WaitForMigrationStatus(t, &vtParams, shards, t1uuid, normalWaitTime, schema.OnlineDDLStatusRunning) + fmt.Printf("# Migration status (for debug purposes): <%s>\n", status) + }) + t.Run("wait for t1 ready to complete", func(t *testing.T) { + waitForReadyToComplete(t, t1uuid, true) + }) + + // Set a dangerously low wait_timeout AFTER the migration is running and + // ready to complete. This way VReplication and other connections survive + // setup, but new connections (the cutover connections) inherit the low value. + t.Run("set low wait_timeout", func(t *testing.T) { + _, err = primaryTablet.VttabletProcess.QueryTabletWithDB("set global wait_timeout=5", "performance_schema") + require.NoError(t, err) + }) + defer primaryTablet.VttabletProcess.QueryTabletWithDB(fmt.Sprintf("set global wait_timeout=%d", originalWaitTimeout), "performance_schema") + + // Hold a WRITE lock on the table to stall the cutover's RENAME TABLE. + lockConn, err := primaryTablet.VttabletProcess.TabletConn(keyspaceName, true) + require.NoError(t, err) + defer lockConn.Close() + // Ensure our lock connection itself won't be killed. + _, err = lockConn.ExecuteFetch("set @@session.wait_timeout=28800", 0, false) + require.NoError(t, err) + + t.Run("lock table to stall cutover", func(t *testing.T) { + _, err := lockConn.ExecuteFetch("lock tables t1_test write", 0, false) + require.NoError(t, err) + }) + defer lockConn.ExecuteFetch("unlock tables", 0, false) + + t.Run("injecting heartbeats asynchronously", func(t *testing.T) { + go func() { + ticker := time.NewTicker(time.Second) + defer ticker.Stop() + for { + throttler.CheckThrottler(&clusterInstance.VtctldClientProcess, primaryTablet, throttlerapp.OnlineDDLName, nil) + select { + case <-ticker.C: + case <-ctx.Done(): + return + } + } + }() + }) + + t.Run("complete migration", func(t *testing.T) { + onlineddl.CheckCompleteMigration(t, &vtParams, shards, t1uuid, true) + }) + + t.Run("validate cutover connections have increased wait_timeout", func(t *testing.T) { + // Wait for the cutover to be in-progress. The LOCK TABLES will be blocked by + // our held WRITE lock, so the lock connection should be visible in the + // processlist with state "Waiting for table metadata lock". + query := ` + SELECT v.VARIABLE_VALUE as wait_timeout + FROM performance_schema.threads t + JOIN performance_schema.variables_by_thread v ON v.THREAD_ID = t.THREAD_ID + WHERE v.VARIABLE_NAME = 'wait_timeout' + AND t.PROCESSLIST_STATE = 'Waiting for table metadata lock' + AND t.PROCESSLIST_INFO LIKE 'LOCK TABLES%' + ` + assert.Eventually(t, func() bool { + rs, err := primaryTablet.VttabletProcess.QueryTabletWithDB(query, "performance_schema") + if err != nil { + return false + } + for _, row := range rs.Named().Rows { + waitTimeout, _ := strconv.ParseInt(row.AsString("wait_timeout", "0"), 10, 64) + if waitTimeout == 31536000 { + // Validated! Release the lock so the cutover can proceed. + lockConn.ExecuteFetch("unlock tables", 0, false) + return true + } + } + return false + }, normalWaitTime, time.Second, "expected cutover connection to have wait_timeout == 31536000") + }) + + t.Run("expect completion", func(t *testing.T) { + status := onlineddl.WaitForMigrationStatus(t, &vtParams, shards, t1uuid, normalWaitTime, schema.OnlineDDLStatusComplete, schema.OnlineDDLStatusFailed) + fmt.Printf("# Migration status (for debug purposes): <%s>\n", status) + onlineddl.CheckMigrationStatus(t, &vtParams, shards, t1uuid, schema.OnlineDDLStatusComplete) + }) + }) + t.Run("ALTER both tables non-concurrent", func(t *testing.T) { t1uuid = testOnlineDDLStatement(t, createParams(trivialAlterT1Statement, ddlStrategy, "vtgate", "", "", true)) // skip wait t2uuid = testOnlineDDLStatement(t, createParams(trivialAlterT2Statement, ddlStrategy, "vtgate", "", "", true)) // skip wait @@ -1964,6 +2074,7 @@ DROP TABLE IF EXISTS stress_test onlineddl.CheckMigrationStatus(t, &vtParams, shards, revertUUID, schema.OnlineDDLStatusCancelled) }) } + func testDeclarative(t *testing.T) { shards = clusterInstance.Keyspaces[0].Shards require.Equal(t, 1, len(shards)) @@ -2636,7 +2747,6 @@ func testDeclarative(t *testing.T) { } func testForeignKeys(t *testing.T) { - var ( createStatements = []string{ ` @@ -2685,7 +2795,7 @@ func testForeignKeys(t *testing.T) { expectCountUUIDs int onlyIfFKOnlineDDLPossible bool } - var testCases = []testCase{ + testCases := []testCase{ { name: "modify parent, not allowed", sql: "alter table parent_table engine=innodb", diff --git a/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-binary-no-default-value/alter b/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-binary-no-default-value/alter new file mode 100644 index 00000000000..bf75cfaf36c --- /dev/null +++ b/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-binary-no-default-value/alter @@ -0,0 +1 @@ +add column new_col bigint not null \ No newline at end of file diff --git a/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-binary-no-default-value/create.sql b/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-binary-no-default-value/create.sql new file mode 100644 index 00000000000..aede64f0a63 --- /dev/null +++ b/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-binary-no-default-value/create.sql @@ -0,0 +1,47 @@ +drop table if exists onlineddl_test; +create table onlineddl_test ( + id int auto_increment, + bin_data varbinary(256) not null, + primary key(id) +) auto_increment=1; + +-- Insert rows with binary data containing bytes 0x80-0xFF. +-- These bytes are invalid standalone UTF-8. When VReplication copies these rows, +-- the bulk INSERT query is built by encodeBytesSQLBytes2 (byte iteration, WriteByte), +-- preserving raw high bytes. If the error message is truncated and then re-encoded +-- by EncodeStringSQL (rune iteration, WriteRune), each invalid byte expands from +-- 1 byte to 3 bytes (U+FFFD), causing the stored message to exceed varbinary(1000). +insert into onlineddl_test (bin_data) values + (UNHEX(REPEAT('FF80FE90FD82FC83', 16))), + (UNHEX(REPEAT('FF80FE90FD82FC83', 16))), + (UNHEX(REPEAT('FF80FE90FD82FC83', 16))), + (UNHEX(REPEAT('FF80FE90FD82FC83', 16))), + (UNHEX(REPEAT('FF80FE90FD82FC83', 16))), + (UNHEX(REPEAT('FF80FE90FD82FC83', 16))), + (UNHEX(REPEAT('FF80FE90FD82FC83', 16))), + (UNHEX(REPEAT('FF80FE90FD82FC83', 16))), + (UNHEX(REPEAT('FF80FE90FD82FC83', 16))), + (UNHEX(REPEAT('FF80FE90FD82FC83', 16))), + (UNHEX(REPEAT('FF80FE90FD82FC83', 16))), + (UNHEX(REPEAT('FF80FE90FD82FC83', 16))), + (UNHEX(REPEAT('FF80FE90FD82FC83', 16))), + (UNHEX(REPEAT('FF80FE90FD82FC83', 16))), + (UNHEX(REPEAT('FF80FE90FD82FC83', 16))), + (UNHEX(REPEAT('FF80FE90FD82FC83', 16))), + (UNHEX(REPEAT('FF80FE90FD82FC83', 16))), + (UNHEX(REPEAT('FF80FE90FD82FC83', 16))), + (UNHEX(REPEAT('FF80FE90FD82FC83', 16))), + (UNHEX(REPEAT('FF80FE90FD82FC83', 16))); + +drop event if exists onlineddl_test; +delimiter ;; +create event onlineddl_test + on schedule every 1 second + starts current_timestamp + ends current_timestamp + interval 60 second + on completion not preserve + enable + do +begin + insert into onlineddl_test values (null, UNHEX(REPEAT('FF80FE90FD82FC83', 16))); +end ;; diff --git a/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-binary-no-default-value/expect_failure b/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-binary-no-default-value/expect_failure new file mode 100644 index 00000000000..8ca6bb9534c --- /dev/null +++ b/go/test/endtoend/onlineddl/vrepl_suite/testdata/fail-binary-no-default-value/expect_failure @@ -0,0 +1 @@ +doesn't have a default value \ No newline at end of file diff --git a/go/test/endtoend/reparent/emergencyreparent/ers_test.go b/go/test/endtoend/reparent/emergencyreparent/ers_test.go index f2febf9e27f..d03b47f085e 100644 --- a/go/test/endtoend/reparent/emergencyreparent/ers_test.go +++ b/go/test/endtoend/reparent/emergencyreparent/ers_test.go @@ -19,9 +19,11 @@ package emergencyreparent import ( "context" "os/exec" + "sync" "testing" "time" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "vitess.io/vitess/go/mysql" @@ -29,6 +31,8 @@ import ( "vitess.io/vitess/go/test/endtoend/reparent/utils" "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/vtctl/reparentutil/policy" + + topodatapb "vitess.io/vitess/go/vt/proto/topodata" ) func TestTrivialERS(t *testing.T) { @@ -131,6 +135,131 @@ func TestReparentDownPrimary(t *testing.T) { utils.ResurrectTablet(ctx, t, clusterInstance, tablets[0]) } +func TestEmergencyReparentWithBlockedPrimary(t *testing.T) { + clusterInstance := utils.SetupReparentCluster(t, policy.DurabilitySemiSync) + defer utils.TeardownCluster(clusterInstance) + + if clusterInstance.VtTabletMajorVersion < 24 { + t.Skip("Skipping test since `DemotePrimary` on earlier versions does not handle blocked primaries correctly") + } + + // start vtgate w/disabled buffering + clusterInstance.VtGateExtraArgs = append(clusterInstance.VtGateExtraArgs, + "--enable_buffer=false", + "--query-timeout", "3000") + err := clusterInstance.StartVtgate() + require.NoError(t, err) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + conn, err := mysql.Connect(ctx, &mysql.ConnParams{ + Host: clusterInstance.Hostname, + Port: clusterInstance.VtgateMySQLPort, + }) + require.NoError(t, err) + defer conn.Close() + + _, err = conn.ExecuteFetch("CREATE TABLE test (id INT PRIMARY KEY, msg VARCHAR(64))", 0, false) + require.NoError(t, err) + + tablets := clusterInstance.Keyspaces[0].Shards[0].Vttablets + + // Simulate no semi-sync replicas being available by disabling semi-sync on all replicas + for _, tablet := range tablets[1:] { + utils.RunSQL(ctx, t, "STOP REPLICA IO_THREAD", tablet) + + // Disable semi-sync on replicas to simulate blocking + semisyncType, err := utils.SemiSyncExtensionLoaded(context.Background(), tablet) + require.NoError(t, err) + switch semisyncType { + case mysql.SemiSyncTypeSource: + utils.RunSQL(context.Background(), t, "SET GLOBAL rpl_semi_sync_replica_enabled = false", tablet) + case mysql.SemiSyncTypeMaster: + utils.RunSQL(context.Background(), t, "SET GLOBAL rpl_semi_sync_slave_enabled = false", tablet) + } + + utils.RunSQL(context.Background(), t, "START REPLICA IO_THREAD", tablet) + } + + // Try performing a write and ensure that it blocks. + writeSQL := `insert into test(id, msg) values (1, 'test 1')` + wg := sync.WaitGroup{} + wg.Add(1) + go func() { + defer wg.Done() + + // Attempt writing via vtgate against the primary. This should block (because there's no replicas to ack the semi-sync), + // and fail on the vtgate query timeout. Async replicas will still receive this write (probably), because it is written + // to the PRIMARY binlog even when no ackers exist. This means we need to disable the vtgate buffer (above), because it + // will attempt the write on the promoted, unblocked primary - and this will hit a dupe key error. + _, err := conn.ExecuteFetch(writeSQL, 0, false) + require.ErrorContains(t, err, "context deadline exceeded (errno 1317) (sqlstate 70100) during query: "+writeSQL) + + // Verify vtgate really processed the insert in case something unrelated caused the deadline exceeded. + vtgateVars := clusterInstance.VtgateProcess.GetVars() + require.NotNil(t, vtgateVars) + require.NotNil(t, vtgateVars["QueryRoutes"]) + require.NotNil(t, vtgateVars["VtgateApiErrorCounts"]) + require.EqualValues(t, map[string]interface{}{ + "DDL.DirectDDL.PRIMARY": float64(1), + "INSERT.Passthrough.PRIMARY": float64(1), + }, vtgateVars["QueryRoutes"]) + require.EqualValues(t, map[string]interface{}{ + "Execute.ks.primary.DEADLINE_EXCEEDED": float64(1), + }, vtgateVars["VtgateApiErrorCounts"]) + }() + + wg.Add(1) + waitReplicasTimeout := time.Second * 10 + go func() { + defer wg.Done() + + // Ensure the write (other goroutine above) is blocked waiting on ACKs on the primary. + utils.WaitForQueryWithStateInProcesslist(context.Background(), t, tablets[0], writeSQL, "Waiting for semi-sync ACK from replica", time.Second*20) + + // Send SIGSTOP to primary to simulate it being unresponsive. + tablets[0].VttabletProcess.Stop() + + // Run forced reparent operation, this should now proceed unimpeded. + out, err := utils.Ers(clusterInstance, tablets[1], "15s", waitReplicasTimeout.String()) + require.NoError(t, err, out) + }() + + wg.Wait() + + // We need to wait at least 10 seconds here to ensure the wait-for-replicas-timeout has passed, + // before we resume the old primary - otherwise the old primary will receive a `SetReplicationSource` call. + time.Sleep(waitReplicasTimeout * 2) + + // Bring back the demoted primary + tablets[0].VttabletProcess.Resume() + + // Give the old primary some time to realize it's no longer the primary, + // and for a new primary to be promoted. + require.EventuallyWithT(t, func(c *assert.CollectT) { + // Ensure the old primary was demoted correctly + tabletInfo, err := clusterInstance.VtctldClientProcess.GetTablet(tablets[0].Alias) + require.NoError(c, err) + + // The old primary should have noticed there's a new primary tablet now and should + // have demoted itself to REPLICA. + require.Equal(c, topodatapb.TabletType_REPLICA, tabletInfo.GetType()) + + // The old primary should be in not serving mode because we should be unable to re-attach it + // as a replica due to the errant GTID caused by semi-sync writes that were never replicated out. + // + // Note: The writes that were not replicated were caused by the semi sync unblocker, which + // performed writes after ERS. + require.Equal(c, "NOT_SERVING", tablets[0].VttabletProcess.GetTabletStatus()) + require.Equal(c, "replica", tablets[0].VttabletProcess.GetTabletType()) + + // Check the 2nd tablet becomes PRIMARY. + require.Equal(c, "SERVING", tablets[1].VttabletProcess.GetTabletStatus()) + require.Equal(c, "primary", tablets[1].VttabletProcess.GetTabletType()) + }, 30*time.Second, time.Second, "could not validate primary was demoted") +} + func TestReparentNoChoiceDownPrimary(t *testing.T) { clusterInstance := utils.SetupReparentCluster(t, policy.DurabilitySemiSync) defer utils.TeardownCluster(clusterInstance) diff --git a/go/test/endtoend/reparent/utils/utils.go b/go/test/endtoend/reparent/utils/utils.go index 08a97a91ed7..64b67e87054 100644 --- a/go/test/endtoend/reparent/utils/utils.go +++ b/go/test/endtoend/reparent/utils/utils.go @@ -31,15 +31,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - querypb "vitess.io/vitess/go/vt/proto/query" - "vitess.io/vitess/go/vt/vtctl/reparentutil/policy" - "vitess.io/vitess/go/vt/vttablet/tabletconn" - "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/test/endtoend/cluster" "vitess.io/vitess/go/vt/log" + querypb "vitess.io/vitess/go/vt/proto/query" topodatapb "vitess.io/vitess/go/vt/proto/topodata" + "vitess.io/vitess/go/vt/vtctl/reparentutil/policy" + "vitess.io/vitess/go/vt/vttablet/tabletconn" ) var ( @@ -365,7 +364,8 @@ func PrsAvoid(t *testing.T, clusterInstance *cluster.LocalProcessCluster, tab *c func PrsWithTimeout(t *testing.T, clusterInstance *cluster.LocalProcessCluster, tab *cluster.Vttablet, avoid bool, actionTimeout, waitTimeout string, extraArgs ...string) (string, error) { args := []string{ "PlannedReparentShard", - fmt.Sprintf("%s/%s", KeyspaceName, ShardName)} + fmt.Sprintf("%s/%s", KeyspaceName, ShardName), + } if actionTimeout != "" { args = append(args, "--action_timeout", actionTimeout) } @@ -839,6 +839,7 @@ func CheckReplicationStatus(ctx context.Context, t *testing.T, tablet *cluster.V } } +// WaitForTabletToBeServing waits for a tablet to reach a serving state. func WaitForTabletToBeServing(ctx context.Context, t *testing.T, clusterInstance *cluster.LocalProcessCluster, tablet *cluster.Vttablet, timeout time.Duration) { vTablet, err := clusterInstance.VtctldClientProcess.GetTablet(tablet.Alias) require.NoError(t, err) @@ -859,3 +860,22 @@ func WaitForTabletToBeServing(ctx context.Context, t *testing.T, clusterInstance t.Fatal(err.Error()) } } + +// WaitForQueryWithStateInProcesslist waits for a query to be present in the processlist with a specific state. +func WaitForQueryWithStateInProcesslist(ctx context.Context, t *testing.T, tablet *cluster.Vttablet, sql, state string, timeout time.Duration) { + require.Eventually(t, func() bool { + qr := RunSQL(ctx, t, "select Command, State, Info from information_schema.processlist", tablet) + for _, row := range qr.Rows { + if len(row) != 3 { + continue + } + if strings.EqualFold(row[0].ToString(), "Query") { + continue + } + if strings.EqualFold(row[1].ToString(), state) && strings.EqualFold(row[2].ToString(), sql) { + return true + } + } + return false + }, timeout, time.Second, "query with state not in processlist") +} diff --git a/go/test/endtoend/transaction/twopc/fuzz/fuzzer_test.go b/go/test/endtoend/transaction/twopc/fuzz/fuzzer_test.go index f4e18c2b220..3a1601529ce 100644 --- a/go/test/endtoend/transaction/twopc/fuzz/fuzzer_test.go +++ b/go/test/endtoend/transaction/twopc/fuzz/fuzzer_test.go @@ -60,6 +60,7 @@ var ( insertIntoFuzzInsert = "INSERT INTO twopc_fuzzer_insert (id, updateSet, threadId) VALUES (%d, %d, %d)" selectFromFuzzUpdate = "SELECT col FROM twopc_fuzzer_update WHERE id = %d" selectIdFromFuzzInsert = "SELECT threadId FROM twopc_fuzzer_insert WHERE updateSet = %d AND id = %d ORDER BY col" + vtgateQueryTimeout = 5 * time.Second ) // TestTwoPCFuzzTest tests 2PC transactions in a fuzzer environment. @@ -277,7 +278,7 @@ func (fz *fuzzer) runFuzzerThread(t *testing.T, threadId int) { return } // Run an atomic transaction - fz.generateAndExecuteTransaction(threadId) + fz.generateAndExecuteTransaction(t, threadId) } } @@ -306,13 +307,15 @@ func (fz *fuzzer) initialize(t *testing.T, conn *mysql.Conn) { } // generateAndExecuteTransaction generates the queries of the transaction and then executes them. -func (fz *fuzzer) generateAndExecuteTransaction(threadId int) { +func (fz *fuzzer) generateAndExecuteTransaction(t *testing.T, threadId int) { // Create a connection to the vtgate to run transactions. - conn, err := mysql.Connect(context.Background(), &vtParams) - if err != nil { - return - } + ctx, cancel := context.WithTimeout(context.Background(), vtgateQueryTimeout) + defer cancel() + conn, err := mysql.Connect(ctx, &vtParams) + require.NoError(t, err) defer conn.Close() + _, err = conn.ExecuteFetch(fmt.Sprintf("set @@query_timeout = %d", vtgateQueryTimeout.Milliseconds()), 0, false) + require.NoError(t, err) // randomly generate an update set to use and the value to increment it by. updateSetVal := rand.IntN(fz.updateSets) incrementVal := rand.Int32() @@ -335,7 +338,12 @@ func (fz *fuzzer) generateAndExecuteTransaction(threadId int) { break } } - _, _ = conn.ExecuteFetch(finalCommand, 0, false) + _, err = conn.ExecuteFetch(finalCommand, 0, false) + // We don't care about the following case of errors here as the transaction is aborted, which is what we ultimately wanted: + // target: ks.80-.primary: vttablet: rpc error: code = Aborted desc = transaction 1771351525769549550: in use: for query (CallerID: userData1) (errno 1317) (sqlstate 70100) during query: rollback + if finalCommand != "rollback" { + require.NoError(t, err) + } } func getUpdateQuery(incrementVal int32, id int) string { @@ -485,6 +493,7 @@ func vttabletRestarts(t *testing.T) { return } tablet.VttabletProcess.ServingStatus = "SERVING" + deadline := time.Now().Add(2 * time.Minute) for { err = tablet.VttabletProcess.Setup() if err == nil { @@ -493,6 +502,10 @@ func vttabletRestarts(t *testing.T) { // Sometimes vttablets fail to connect to the topo server due to a minor blip there. // We don't want to fail the test, so we retry setting up the vttablet. log.Errorf("error restarting vttablet - %v", err) + if time.Now().After(deadline) { + log.Errorf("giving up restarting vttablet after timeout: %v", tablet.Alias) + return + } time.Sleep(1 * time.Second) } } diff --git a/go/test/endtoend/vtgate/queries/misc/misc_test.go b/go/test/endtoend/vtgate/queries/misc/misc_test.go index 0755b98ec55..b720a4c04eb 100644 --- a/go/test/endtoend/vtgate/queries/misc/misc_test.go +++ b/go/test/endtoend/vtgate/queries/misc/misc_test.go @@ -374,6 +374,51 @@ func TestHighNumberOfParams(t *testing.T) { require.Equal(t, 5, count) } +// TestPreparedStatementInOLAP verifies that streaming prepared statements +// return correct binary-encoded rows when result fields are only sent in the +// first chunk. +func TestPreparedStatementInOLAP(t *testing.T) { + _, closer := start(t) + defer closer() + + // Use the binary protocol by disabling client-side parameter interpolation. + db, err := sql.Open("mysql", fmt.Sprintf("@tcp(%s:%v)/%s?interpolateParams=false", vtParams.Host, vtParams.Port, vtParams.DbName)) + require.NoError(t, err) + defer db.Close() + + // Pin a single connection so the session variable persists across operations. + conn, err := db.Conn(t.Context()) + require.NoError(t, err) + defer conn.Close() + + // Seed test data and switch to OLAP streaming mode. + _, err = conn.ExecContext(t.Context(), "delete from t1") + require.NoError(t, err) + _, err = conn.ExecContext(t.Context(), "insert into t1(id1, id2) values (1, 2)") + require.NoError(t, err) + _, err = conn.ExecContext(t.Context(), "set workload = olap") + require.NoError(t, err) + + // Select 7 columns: the null bitmap crosses a byte boundary at this count, + // making corruption from missing fields visible. + stmt, err := conn.PrepareContext(t.Context(), "select id1, id2, id1, id2, id1, id2, id1 from t1 where id1 = ?") + require.NoError(t, err) + defer stmt.Close() + + // Verify every column decoded correctly; corruption would show as NULL or + // wrong values. + var c1, c2, c3, c4, c5, c6, c7 int64 + err = stmt.QueryRow(1).Scan(&c1, &c2, &c3, &c4, &c5, &c6, &c7) + require.NoError(t, err) + require.Equal(t, int64(1), c1) + require.Equal(t, int64(2), c2) + require.Equal(t, int64(1), c3) + require.Equal(t, int64(2), c4) + require.Equal(t, int64(1), c5) + require.Equal(t, int64(2), c6) + require.Equal(t, int64(1), c7) +} + func TestPrepareStatements(t *testing.T) { mcmp, closer := start(t) defer closer() diff --git a/go/test/endtoend/vtgate/reservedconn/reconnect3/main_test.go b/go/test/endtoend/vtgate/reservedconn/reconnect3/main_test.go index decf2f0dfdd..02fed03c258 100644 --- a/go/test/endtoend/vtgate/reservedconn/reconnect3/main_test.go +++ b/go/test/endtoend/vtgate/reservedconn/reconnect3/main_test.go @@ -82,6 +82,12 @@ func TestMysqlDownServingChange(t *testing.T) { utils.Exec(t, conn, "set default_week_format = 1") _ = utils.Exec(t, conn, "select /*vt+ PLANNER=gen4 */ * from test") + // Disable VTOrc recoveries to prevent VTOrc from racing with the manual ERS below. + clusterInstance.DisableVTOrcRecoveries(t) + t.Cleanup(func() { + clusterInstance.EnableVTOrcRecoveries(t) + }) + primaryTablet := clusterInstance.Keyspaces[0].Shards[0].PrimaryTablet() require.NoError(t, primaryTablet.MysqlctlProcess.Stop()) diff --git a/go/test/endtoend/vtgate/reservedconn/reconnect4/main_test.go b/go/test/endtoend/vtgate/reservedconn/reconnect4/main_test.go index 320cbc87172..802a5533316 100644 --- a/go/test/endtoend/vtgate/reservedconn/reconnect4/main_test.go +++ b/go/test/endtoend/vtgate/reservedconn/reconnect4/main_test.go @@ -82,6 +82,12 @@ func TestVttabletDownServingChange(t *testing.T) { utils.Exec(t, conn, "set default_week_format = 1") _ = utils.Exec(t, conn, "select /*vt+ PLANNER=gen4 */ * from test") + // Disable VTOrc recoveries to prevent VTOrc from racing with the manual ERS below. + clusterInstance.DisableVTOrcRecoveries(t) + t.Cleanup(func() { + clusterInstance.EnableVTOrcRecoveries(t) + }) + primaryTablet := clusterInstance.Keyspaces[0].Shards[0].PrimaryTablet() require.NoError(t, primaryTablet.MysqlctlProcess.Stop()) diff --git a/go/test/endtoend/vtgate/reservedconn/sysvar_test.go b/go/test/endtoend/vtgate/reservedconn/sysvar_test.go index 8bda7dea121..6bb5762b4a8 100644 --- a/go/test/endtoend/vtgate/reservedconn/sysvar_test.go +++ b/go/test/endtoend/vtgate/reservedconn/sysvar_test.go @@ -195,6 +195,35 @@ func TestSetSystemVariableAndThenSuccessfulAutocommitDML(t *testing.T) { utils.AssertMatches(t, conn, `select @@sql_safe_updates`, `[[INT64(1)]]`) } +// This test ensures that when autocommit is disabled, `SET` commands do not +// cause an implicit transaction to be started. +// +// We test this via `set session transaction isolation level` because +// changing the session transaction isolation level affects only the next +// transaction that's started. +func TestSetSystemVariableWithAutocommitDisabled(t *testing.T) { + conn1, err := mysql.Connect(context.Background(), &vtParams) + require.NoError(t, err) + defer conn1.Close() + + conn2, err := mysql.Connect(context.Background(), &vtParams) + require.NoError(t, err) + defer conn2.Close() + + utils.Exec(t, conn1, "delete from test") + utils.Exec(t, conn1, "delete from test_vdx") + + utils.Exec(t, conn1, "set autocommit = 0") + + utils.Exec(t, conn1, "set session transaction isolation level read uncommitted") + utils.AssertMatches(t, conn1, "select @@transaction_isolation", `[[VARCHAR("READ-UNCOMMITTED")]]`) + + utils.Exec(t, conn2, "begin") + utils.Exec(t, conn2, "insert into test (id, val1) values (80, null)") + + utils.AssertMatches(t, conn1, "select id from test where id = 80", `[[INT64(80)]]`) +} + func TestStartTxAndSetSystemVariableAndThenSuccessfulCommit(t *testing.T) { conn, err := mysql.Connect(context.Background(), &vtParams) @@ -422,42 +451,74 @@ func checkOltpAndOlapInterchangingTx(t *testing.T, conn *mysql.Conn) { } func TestSysVarTxIsolation(t *testing.T) { - conn, err := mysql.Connect(context.Background(), &vtParams) - require.NoError(t, err) - defer conn.Close() - - // will run every check twice to see that the isolation level is set for all the queries in the session and - - // default from mysql - utils.AssertMatches(t, conn, "select @@transaction_isolation", `[[VARCHAR("REPEATABLE-READ")]]`) - // ensuring it goes to mysql - utils.AssertContains(t, conn, "select @@transaction_isolation, connection_id()", `REPEATABLE-READ`) - // second run, ensuring it has the same value. - utils.AssertContains(t, conn, "select @@transaction_isolation, connection_id()", `REPEATABLE-READ`) - - // setting to different value. - utils.Exec(t, conn, "set @@transaction_isolation = 'read-committed'") - utils.AssertMatches(t, conn, "select @@transaction_isolation", `[[VARCHAR("READ-COMMITTED")]]`) - // ensuring it goes to mysql - utils.AssertContains(t, conn, "select @@transaction_isolation, connection_id()", `READ-COMMITTED`) - // second run, to ensuring the setting is applied on the session and not just on next query after settings. - utils.AssertContains(t, conn, "select @@transaction_isolation, connection_id()", `READ-COMMITTED`) - - // changing setting to different value. - utils.Exec(t, conn, "set session transaction isolation level read uncommitted") - utils.AssertMatches(t, conn, "select @@transaction_isolation", `[[VARCHAR("READ-UNCOMMITTED")]]`) - // ensuring it goes to mysql - utils.AssertContains(t, conn, "select @@transaction_isolation, connection_id()", `READ-UNCOMMITTED`) - // second run, to ensuring the setting is applied on the session and not just on next query after settings. - utils.AssertContains(t, conn, "select @@transaction_isolation, connection_id()", `READ-UNCOMMITTED`) - - // changing setting to different value. - utils.Exec(t, conn, "set transaction isolation level serializable") - utils.AssertMatches(t, conn, "select @@transaction_isolation", `[[VARCHAR("SERIALIZABLE")]]`) - // ensuring it goes to mysql - utils.AssertContains(t, conn, "select @@transaction_isolation, connection_id()", `SERIALIZABLE`) - // second run, to ensuring the setting is applied on the session and not just on next query after settings. - utils.AssertContains(t, conn, "select @@transaction_isolation, connection_id()", `SERIALIZABLE`) + t.Run("returns the default isolation level if unchanged", func(t *testing.T) { + conn, err := mysql.Connect(context.Background(), &vtParams) + require.NoError(t, err) + defer conn.Close() + + utils.Exec(t, conn, "delete from test") + utils.Exec(t, conn, "delete from test_vdx") + + // default from mysql + utils.AssertMatches(t, conn, "select @@transaction_isolation", `[[VARCHAR("REPEATABLE-READ")]]`) + // ensuring it goes to mysql + utils.AssertContains(t, conn, "select @@transaction_isolation, connection_id()", `REPEATABLE-READ`) + // second run, ensuring it has the same value. + utils.AssertContains(t, conn, "select @@transaction_isolation, connection_id()", `REPEATABLE-READ`) + + // Switch to shard targeting + utils.Exec(t, conn, "use `"+keyspaceName+":-80`") + + utils.AssertMatches(t, conn, "select @@transaction_isolation", `[[VARCHAR("REPEATABLE-READ")]]`) + utils.AssertContains(t, conn, "select @@transaction_isolation, connection_id()", `REPEATABLE-READ`) + utils.AssertContains(t, conn, "select @@transaction_isolation, connection_id()", `REPEATABLE-READ`) + }) + + t.Run("allows changing the isolation level via special syntax", func(t *testing.T) { + conn, err := mysql.Connect(context.Background(), &vtParams) + require.NoError(t, err) + defer conn.Close() + + utils.Exec(t, conn, "delete from test") + utils.Exec(t, conn, "delete from test_vdx") + + // setting to different value. + utils.Exec(t, conn, "set session transaction isolation level read committed") + + utils.AssertMatches(t, conn, "select @@transaction_isolation", `[[VARCHAR("READ-COMMITTED")]]`) + utils.AssertContains(t, conn, "select @@transaction_isolation, connection_id()", `READ-COMMITTED`) + utils.AssertContains(t, conn, "select @@transaction_isolation, connection_id()", `READ-COMMITTED`) + + // Switch to shard targeting + utils.Exec(t, conn, "use `"+keyspaceName+":-80`") + utils.AssertMatches(t, conn, "select @@transaction_isolation", `[[VARCHAR("READ-COMMITTED")]]`) + + utils.Exec(t, conn, "set session transaction isolation level read uncommitted") + utils.AssertMatches(t, conn, "select @@transaction_isolation", `[[VARCHAR("READ-UNCOMMITTED")]]`) + }) + + t.Run("allows changing the isolation level via session variable", func(t *testing.T) { + conn, err := mysql.Connect(context.Background(), &vtParams) + require.NoError(t, err) + defer conn.Close() + + utils.Exec(t, conn, "delete from test") + utils.Exec(t, conn, "delete from test_vdx") + + // setting to different value. + utils.Exec(t, conn, "set @@session.transaction_isolation = 'read-committed'") + + utils.AssertMatches(t, conn, "select @@transaction_isolation", `[[VARCHAR("READ-COMMITTED")]]`) + utils.AssertContains(t, conn, "select @@transaction_isolation, connection_id()", `READ-COMMITTED`) + utils.AssertContains(t, conn, "select @@transaction_isolation, connection_id()", `READ-COMMITTED`) + + // Switch to shard targeting + utils.Exec(t, conn, "use `"+keyspaceName+":-80`") + utils.AssertMatches(t, conn, "select @@transaction_isolation", `[[VARCHAR("READ-COMMITTED")]]`) + + utils.Exec(t, conn, "set @@session.transaction_isolation = 'read-uncommitted'") + utils.AssertMatches(t, conn, "select @@transaction_isolation", `[[VARCHAR("READ-UNCOMMITTED")]]`) + }) } // TestSysVarInnodbWaitTimeout tests the innodb_lock_wait_timeout system variable @@ -491,3 +552,338 @@ func TestSysVarInnodbWaitTimeout(t *testing.T) { // second run, to ensuring the setting is applied on the session and not just on next query after settings. utils.AssertContains(t, conn, "select @@innodb_lock_wait_timeout, connection_id()", `INT64(240)`) } + +// TestImplicitTxOnAutocommitOff verifies that vtgate only starts implicit +// transactions for statements that access real table data when autocommit=0, +// matching MySQL's behavior. +func TestImplicitTxOnAutocommitOff(t *testing.T) { + tests := []struct { + name string + query string + startsTx bool + }{ + { + name: "SELECT from real table starts tx", + query: "select id from test where id = 1", + startsTx: true, + }, + { + name: "SELECT @@variable does not start tx", + query: "select @@autocommit", + startsTx: false, + }, + { + name: "SELECT 1 does not start tx", + query: "select 1", + startsTx: false, + }, + { + name: "SELECT from dual does not start tx", + query: "select 1 from dual", + startsTx: false, + }, + { + name: "INSERT starts tx", + query: "insert into test (id, val1) values (999, null)", + startsTx: true, + }, + { + name: "UPDATE starts tx", + query: "update test set val1 = 'x' where id = 999", + startsTx: true, + }, + { + name: "DELETE starts tx", + query: "delete from test where id = 999", + startsTx: true, + }, + { + name: "SET variable does not start tx", + query: "set sql_safe_updates = 1", + startsTx: false, + }, + { + name: "COMMIT does not start tx", + query: "commit", + startsTx: false, + }, + { + name: "ROLLBACK does not start tx", + query: "rollback", + startsTx: false, + }, + // SHOW commands that start implicit transactions (access information_schema / data dictionaries): + { + name: "SHOW TABLES starts tx", + query: "show tables", + startsTx: true, + }, + { + name: "SHOW DATABASES starts tx", + query: "show databases", + startsTx: true, + }, + { + name: "SHOW COLUMNS starts tx", + query: "show columns from test", + startsTx: true, + }, + { + name: "SHOW INDEX starts tx", + query: "show index from test", + startsTx: true, + }, + { + name: "SHOW TABLE STATUS starts tx", + query: "show table status", + startsTx: true, + }, + { + name: "SHOW TRIGGERS starts tx", + query: "show triggers", + startsTx: true, + }, + { + name: "SHOW CHARSET starts tx", + query: "show charset", + startsTx: true, + }, + { + name: "SHOW COLLATION starts tx", + query: "show collation", + startsTx: true, + }, + { + name: "SHOW FUNCTION STATUS starts tx", + query: "show function status", + startsTx: true, + }, + { + name: "SHOW PROCEDURE STATUS starts tx", + query: "show procedure status", + startsTx: true, + }, + // SHOW commands that do NOT start implicit transactions (read server state only): + { + name: "SHOW VARIABLES does not start tx", + query: "show variables like 'version'", + startsTx: false, + }, + { + name: "SHOW SESSION VARIABLES does not start tx", + query: "show session variables like 'version'", + startsTx: false, + }, + { + name: "SHOW GLOBAL VARIABLES does not start tx", + query: "show global variables like 'version'", + startsTx: false, + }, + { + name: "SHOW STATUS does not start tx", + query: "show status like 'Uptime'", + startsTx: false, + }, + { + name: "SHOW GLOBAL STATUS does not start tx", + query: "show global status like 'Uptime'", + startsTx: false, + }, + { + name: "SHOW WARNINGS does not start tx", + query: "show warnings", + startsTx: false, + }, + { + name: "SHOW ENGINES does not start tx", + query: "show engines", + startsTx: false, + }, + { + name: "SHOW PLUGINS does not start tx", + query: "show plugins", + startsTx: false, + }, + { + name: "SHOW PRIVILEGES does not start tx", + query: "show privileges", + startsTx: false, + }, + { + name: "SHOW OPEN TABLES does not start tx", + query: "show open tables", + startsTx: false, + }, + // ShowCreate commands do not start implicit transactions. + { + name: "SHOW CREATE TABLE does not start tx", + query: "show create table test", + startsTx: false, + }, + { + name: "SHOW CREATE DATABASE does not start tx", + query: "show create database " + keyspaceName, + startsTx: false, + }, + // ShowOther commands are sent to MySQL as-is and do not start implicit transactions. + { + name: "SHOW PROCESSLIST does not start tx", + query: "show processlist", + startsTx: false, + }, + { + name: "SHOW BINARY LOGS does not start tx", + query: "show binary logs", + startsTx: false, + }, + { + name: "SHOW GRANTS does not start tx", + query: "show grants", + startsTx: false, + }, + { + name: "SHOW ERRORS does not start tx", + query: "show errors", + startsTx: false, + }, + { + name: "SHOW EVENTS does not start tx", + query: "show events", + startsTx: false, + }, + { + name: "SHOW PROFILES does not start tx", + query: "show profiles", + startsTx: false, + }, + { + name: "SHOW REPLICA STATUS does not start tx", + query: "show replica status", + startsTx: false, + }, + { + name: "SHOW ENGINE INNODB STATUS does not start tx", + query: "show engine innodb status", + startsTx: false, + }, + // Vitess-specific SHOW commands are handled internally by vtgate + // and should not start implicit transactions. + { + name: "SHOW VITESS_TABLETS does not start tx", + query: "show vitess_tablets", + startsTx: false, + }, + { + name: "SHOW VITESS_SHARDS does not start tx", + query: "show vitess_shards", + startsTx: false, + }, + { + name: "SHOW VITESS_TARGET does not start tx", + query: "show vitess_target", + startsTx: false, + }, + { + name: "SHOW VSCHEMA TABLES does not start tx", + query: "show vschema tables", + startsTx: false, + }, + { + name: "SHOW VSCHEMA KEYSPACES does not start tx", + query: "show vschema keyspaces", + startsTx: false, + }, + { + name: "SHOW VSCHEMA VINDEXES does not start tx", + query: "show vschema vindexes", + startsTx: false, + }, + { + name: "SHOW KEYSPACES does not start tx", + query: "show keyspaces", + startsTx: false, + }, + { + name: "SHOW VITESS_MIGRATIONS does not start tx", + query: "show vitess_migrations", + startsTx: false, + }, + { + name: "SHOW VITESS_REPLICATION_STATUS does not start tx", + query: "show vitess_replication_status", + startsTx: false, + }, + { + name: "SHOW GLOBAL GTID_EXECUTED does not start tx", + query: "show global gtid_executed", + startsTx: false, + }, + { + name: "SHOW GLOBAL VGTID_EXECUTED does not start tx", + query: "show global vgtid_executed", + startsTx: false, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + conn, err := mysql.Connect(context.Background(), &vtParams) + require.NoError(t, err) + defer conn.Close() + + utils.Exec(t, conn, "delete from test") + utils.Exec(t, conn, "delete from test_vdx") + + utils.Exec(t, conn, "set autocommit = 0") + + result := utils.Exec(t, conn, tc.query) + + inTx := result.StatusFlags&mysql.ServerStatusInTrans != 0 + if tc.startsTx { + assert.True(t, inTx, "expected %q to start an implicit transaction", tc.query) + } else { + assert.False(t, inTx, "expected %q to NOT start an implicit transaction", tc.query) + } + }) + } + + t.Run("ROLLBACK TO SAVEPOINT returns an error when no transaction has been started", func(t *testing.T) { + conn, err := mysql.Connect(context.Background(), &vtParams) + require.NoError(t, err) + defer conn.Close() + + utils.Exec(t, conn, "set autocommit = 0") + + _, err = utils.ExecAllowError(t, conn, "ROLLBACK TO SAVEPOINT sp1") + require.Error(t, err) + sqlErr, ok := err.(*sqlerror.SQLError) + require.True(t, ok, "not a mysql error: %T", err) + assert.Equal(t, sqlerror.ERSPDoesNotExist, sqlErr.Number()) + assert.Equal(t, sqlerror.SSClientError, sqlErr.SQLState()) + assert.Contains(t, sqlErr.Error(), "SAVEPOINT does not exist: ROLLBACK TO SAVEPOINT sp1 (errno 1305) (sqlstate 42000)") + + result := utils.Exec(t, conn, "select 1") + inTx := result.StatusFlags&mysql.ServerStatusInTrans != 0 + assert.False(t, inTx, "expected ROLLBACK TO SAVEPOINT to not start a transaction") + }) + + t.Run("RELEASE SAVEPOINT returns an error when no transaction has been started", func(t *testing.T) { + conn, err := mysql.Connect(context.Background(), &vtParams) + require.NoError(t, err) + defer conn.Close() + + utils.Exec(t, conn, "set autocommit = 0") + + _, err = utils.ExecAllowError(t, conn, "RELEASE SAVEPOINT sp1") + require.Error(t, err) + sqlErr, ok := err.(*sqlerror.SQLError) + require.True(t, ok, "not a mysql error: %T", err) + assert.Equal(t, sqlerror.ERSPDoesNotExist, sqlErr.Number()) + assert.Equal(t, sqlerror.SSClientError, sqlErr.SQLState()) + assert.Contains(t, sqlErr.Error(), "SAVEPOINT does not exist: RELEASE SAVEPOINT sp1 (errno 1305) (sqlstate 42000)") + + result := utils.Exec(t, conn, "select 1") + inTx := result.StatusFlags&mysql.ServerStatusInTrans != 0 + assert.False(t, inTx, "expected RELEASE SAVEPOINT to not start a transaction") + }) +} diff --git a/go/test/endtoend/vtorc/general/vtorc_test.go b/go/test/endtoend/vtorc/general/vtorc_test.go index 4e6cf8abf16..eb554707345 100644 --- a/go/test/endtoend/vtorc/general/vtorc_test.go +++ b/go/test/endtoend/vtorc/general/vtorc_test.go @@ -18,7 +18,9 @@ package general import ( "context" + "encoding/json" "fmt" + "strconv" "testing" "time" @@ -31,6 +33,7 @@ import ( "vitess.io/vitess/go/test/endtoend/vtorc/utils" "vitess.io/vitess/go/vt/log" topodatapb "vitess.io/vitess/go/vt/proto/topodata" + "vitess.io/vitess/go/vt/vtctl/reparentutil/policy" "vitess.io/vitess/go/vt/vtorc/inst" "vitess.io/vitess/go/vt/vtorc/logic" ) @@ -401,6 +404,168 @@ func TestRepairAfterTER(t *testing.T) { utils.CheckReplication(t, clusterInfo, newPrimary, []*cluster.Vttablet{curPrimary}, 15*time.Second) } +// TestStalePrimary tests that an old primary that remains writable and of tablet type PRIMARY in the topo +// is properly demoted to a read-only replica by VTOrc. +func TestStalePrimary(t *testing.T) { + ctx := t.Context() + + defer utils.PrintVTOrcLogsOnFailure(t, clusterInfo.ClusterInstance) + utils.SetupVttabletsAndVTOrcs(t, clusterInfo, 4, 0, []string{"--topo-information-refresh-duration", "1s"}, cluster.VTOrcConfiguration{ + PreventCrossCellFailover: true, + }, 1, policy.DurabilitySemiSync) + keyspace := &clusterInfo.ClusterInstance.Keyspaces[0] + shard0 := &keyspace.Shards[0] + + curPrimary := utils.ShardPrimaryTablet(t, clusterInfo, keyspace, shard0) + assert.NotNil(t, curPrimary, "should have elected a primary") + utils.CheckPrimaryTablet(t, clusterInfo, curPrimary, true) + + var badPrimary, healthyReplica *cluster.Vttablet + for _, tablet := range shard0.Vttablets { + if tablet.Alias == curPrimary.Alias { + continue + } + + if badPrimary == nil { + badPrimary = tablet + continue + } + + healthyReplica = tablet + } + + utils.CheckReplication(t, clusterInfo, curPrimary, []*cluster.Vttablet{badPrimary, healthyReplica}, 15*time.Second) + + curPrimaryTopo, err := clusterInfo.Ts.GetTablet(ctx, curPrimary.GetAlias()) + require.NoError(t, err, "expected to read current primary topo record") + + curPrimaryTermStart := protoutil.TimeFromProto(curPrimaryTopo.PrimaryTermStartTime) + require.False(t, curPrimaryTermStart.IsZero(), "expected current primary term start time to be set") + + err = utils.RunSQLs(t, []string{"SET GLOBAL read_only = OFF"}, badPrimary, "") + require.NoError(t, err) + require.True(t, utils.WaitForReadOnlyValue(t, badPrimary, 0)) + + // We set the tablet's type in the topology to PRIMARY. This mimics the situation where during a demotion + // in a hypothetical ERS, the old primary starts running as a replica, but fails before updating the topology + // accordingly. + _, err = clusterInfo.Ts.UpdateTabletFields(ctx, badPrimary.GetAlias(), func(tablet *topodatapb.Tablet) error { + tablet.Type = topodatapb.TabletType_PRIMARY + tablet.PrimaryTermStartTime = protoutil.TimeToProto(curPrimaryTermStart.Add(-1 * time.Minute)) + return nil + }) + require.NoError(t, err) + + // Expect VTOrc to demote the stale primary to a read-only replica. + require.Eventuallyf(t, func() bool { + topoTablet, topoErr := clusterInfo.Ts.GetTablet(ctx, badPrimary.GetAlias()) + if topoErr != nil { + t.Logf("stale primary probe: topo error=%v", topoErr) + return false + } + + readOnly, readErr := badPrimary.VttabletProcess.GetDBVar("read_only", "") + if readErr != nil { + t.Logf("stale primary probe: alias=%s topo=%v read_only error=%v", badPrimary.Alias, topoTablet.Type, readErr) + return false + } + + return topoTablet.Type == topodatapb.TabletType_REPLICA && readOnly == "ON" + }, 30*time.Second, time.Second, "expected demotion to REPLICA with read_only=ON") +} + +// TestDemotePrimaryHang tests that when the `DemotePrimary` RPC hangs, VTOrc is not indefinitely blocked +// on future recoveries. +func TestDemotePrimaryHang(t *testing.T) { + ctx := t.Context() + + utils.SetupVttabletsAndVTOrcs(t, clusterInfo, 4, 0, []string{"--topo-information-refresh-duration", "1s"}, cluster.VTOrcConfiguration{ + PreventCrossCellFailover: true, + }, 1, policy.DurabilitySemiSync) + + keyspace := &clusterInfo.ClusterInstance.Keyspaces[0] + shard0 := &keyspace.Shards[0] + vtorc := clusterInfo.ClusterInstance.VTOrcProcesses[0] + + curPrimary := utils.ShardPrimaryTablet(t, clusterInfo, keyspace, shard0) + require.NotNil(t, curPrimary, "expected VTOrc to elect an initial primary") + + var stalePrimary *cluster.Vttablet + var blockedReplica *cluster.Vttablet + var healthyReplica *cluster.Vttablet + + for _, tablet := range shard0.Vttablets { + if tablet.Alias == curPrimary.Alias { + continue + } + + if stalePrimary == nil { + stalePrimary = tablet + continue + } + + if blockedReplica == nil { + blockedReplica = tablet + continue + } + + healthyReplica = tablet + } + + require.NotNil(t, stalePrimary, "expected a candidate tablet to mark as stale topo primary") + require.NotNil(t, blockedReplica, "expected a second replica to inject a separate failure") + require.NotNil(t, healthyReplica, "expected a healthy replica to keep normal replication coverage") + + utils.CheckReplication(t, clusterInfo, curPrimary, []*cluster.Vttablet{stalePrimary, blockedReplica, healthyReplica}, 15*time.Second) + + // Hold the stale primary candidate's action queue for a long time. This guarantees that VTOrc's + // DemotePrimary RPC will block on the tablet lock. + sleepDuration := 90 * time.Second + go func() { + clusterInfo.ClusterInstance.VtctldClientProcess.ExecuteCommandWithOutput( + "SleepTablet", + stalePrimary.Alias, + sleepDuration.String(), + ) + }() + + // Make the tablet a stale primary by updating its type to PRIMARY and primary term start time + // to an older time than the current primary. This will trigger the StaleTopoPrimary recovery. + err := utils.RunSQLs(t, []string{"SET GLOBAL read_only = OFF"}, stalePrimary, "") + require.NoError(t, err) + + _, err = clusterInfo.Ts.UpdateTabletFields(ctx, stalePrimary.GetAlias(), func(tablet *topodatapb.Tablet) error { + tablet.Type = topodatapb.TabletType_PRIMARY + tablet.PrimaryTermStartTime = protoutil.TimeToProto(time.Now().Add(-1 * time.Minute)) + return nil + }) + require.NoError(t, err) + + // Wait until VTOrc has detected the stale topo primary. + utils.WaitForDetectedProblems(t, vtorc, string(inst.StaleTopoPrimary), stalePrimary.Alias, keyspace.Name, shard0.Name, 1) + + // Inject a second problem on a different replica while the stale-primary recovery is still hanging. + _, err = clusterInfo.ClusterInstance.VtctldClientProcess.ExecuteCommandWithOutput("StopReplication", blockedReplica.Alias) + require.NoError(t, err) + + utils.WaitForDetectedProblems(t, vtorc, string(inst.ReplicationStopped), blockedReplica.Alias, keyspace.Name, shard0.Name, 1) + + // If DemotePrimary is properly bounded by a context timeout, the stale primary recovery should + // fail, close the recovery row, and unblock the shard for further recoveries. + assert.EventuallyWithT(t, func(c *assert.CollectT) { + vars := vtorc.GetVars() + recoveries, ok := vars["RecoveriesCount"].(map[string]any) + require.True(c, ok, "RecoveriesCount metric not yet available") + + mapKey := logic.DemoteStaleTopoPrimaryRecoveryName + count := utils.GetIntFromValue(recoveries[mapKey]) + assert.GreaterOrEqual(c, count, 1) + }, 30*time.Second, time.Second, "expected VTOrc to attempt stale primary recovery") + + // The FixReplica recovery should run once the stale primary recovery unblocks the shard. + utils.WaitForSuccessfulRecoveryCount(t, vtorc, logic.FixReplicaRecoveryName, 1) +} + // TestSemiSync tests that semi-sync is setup correctly by vtorc if it is incorrectly set func TestSemiSync(t *testing.T) { // stop any vtorc instance running due to a previous test. @@ -729,3 +894,85 @@ func TestFullStatusConnectionPooling(t *testing.T) { assert.Equal(t, 200, status) assert.Equal(t, "null", resp) } + +// TestSemiSyncRecoveryOrdering verifies that when the durability policy changes +// to semi_sync, VTOrc fixes ReplicaSemiSyncMustBeSet before PrimarySemiSyncMustBeSet. +// This ordering is enforced by the AfterAnalyses/BeforeAnalyses dependencies. +func TestSemiSyncRecoveryOrdering(t *testing.T) { + defer utils.PrintVTOrcLogsOnFailure(t, clusterInfo.ClusterInstance) + // Start with durability "none" so no semi-sync is required initially. + utils.SetupVttabletsAndVTOrcs(t, clusterInfo, 2, 0, nil, cluster.VTOrcConfiguration{ + PreventCrossCellFailover: true, + }, 1, policy.DurabilityNone) + keyspace := &clusterInfo.ClusterInstance.Keyspaces[0] + shard0 := &keyspace.Shards[0] + + // Wait for primary election and healthy replication. + primary := utils.ShardPrimaryTablet(t, clusterInfo, keyspace, shard0) + assert.NotNil(t, primary, "should have elected a primary") + utils.CheckReplication(t, clusterInfo, primary, shard0.Vttablets, 10*time.Second) + + vtorc := clusterInfo.ClusterInstance.VTOrcProcesses[0] + utils.WaitForSuccessfulRecoveryCount(t, vtorc, logic.ElectNewPrimaryRecoveryName, 1) + + // Change durability to semi_sync. VTOrc should detect that replicas and primary + // need semi-sync enabled, and fix them in the correct order. + out, err := clusterInfo.ClusterInstance.VtctldClientProcess.ExecuteCommandWithOutput( + "SetKeyspaceDurabilityPolicy", keyspace.Name, "--durability-policy="+policy.DurabilitySemiSync) + require.NoError(t, err, out) + + // Poll the database-state API to verify recovery ordering. + // The topology_recovery table has auto-incremented recovery_id values that + // reflect execution order. All ReplicaSemiSyncMustBeSet recovery_ids should + // be less than any PrimarySemiSyncMustBeSet recovery_id. + type tableState struct { + TableName string + Rows []map[string]any + } + + assert.EventuallyWithT(t, func(c *assert.CollectT) { + status, response, err := utils.MakeAPICall(t, vtorc, "/api/database-state") + assert.NoError(c, err) + assert.Equal(c, 200, status) + + var tables []tableState + if !assert.NoError(c, json.Unmarshal([]byte(response), &tables)) { + return + } + + var maxReplicaRecoveryID, minPrimaryRecoveryID int + var replicaCount, primaryCount int + for _, table := range tables { + if table.TableName != "topology_recovery" { + continue + } + for _, row := range table.Rows { + analysis, _ := row["analysis"].(string) + recoveryIDStr, _ := row["recovery_id"].(string) + recoveryID, err := strconv.Atoi(recoveryIDStr) + if err != nil { + continue + } + switch inst.AnalysisCode(analysis) { + case inst.ReplicaSemiSyncMustBeSet: + replicaCount++ + if replicaCount == 1 || recoveryID > maxReplicaRecoveryID { + maxReplicaRecoveryID = recoveryID + } + case inst.PrimarySemiSyncMustBeSet: + primaryCount++ + if primaryCount == 1 || recoveryID < minPrimaryRecoveryID { + minPrimaryRecoveryID = recoveryID + } + } + } + } + + assert.Greater(c, replicaCount, 0, "should have ReplicaSemiSyncMustBeSet recoveries") + assert.Greater(c, primaryCount, 0, "should have PrimarySemiSyncMustBeSet recoveries") + if replicaCount > 0 && primaryCount > 0 { + assert.Less(c, maxReplicaRecoveryID, minPrimaryRecoveryID, + "all ReplicaSemiSyncMustBeSet recoveries should have lower recovery_id than PrimarySemiSyncMustBeSet") + } + }, 30*time.Second, time.Second) +} diff --git a/go/test/endtoend/vtorc/utils/utils.go b/go/test/endtoend/vtorc/utils/utils.go index 34ef326535b..8ab20e82ab8 100644 --- a/go/test/endtoend/vtorc/utils/utils.go +++ b/go/test/endtoend/vtorc/utils/utils.go @@ -141,7 +141,7 @@ func createVttablets(clusterInstance *cluster.LocalProcessCluster, cellInfos []* if err != nil { return err } - //Start MySql + // Start MySql var mysqlCtlProcessList []*exec.Cmd for _, tablet := range shard0.Vttablets { log.Infof("Starting MySql for tablet %v", tablet.Alias) @@ -591,7 +591,7 @@ func RunSQL(t *testing.T, sql string, tablet *cluster.Vttablet, db string) (*sql func RunSQLs(t *testing.T, sqls []string, tablet *cluster.Vttablet, db string) error { // Get Connection tabletParams := getMysqlConnParam(tablet, db) - var timeoutDuration = time.Duration(5 * len(sqls)) + timeoutDuration := time.Duration(5 * len(sqls)) ctx, cancel := context.WithTimeout(context.Background(), timeoutDuration*time.Second) defer cancel() conn, err := mysql.Connect(ctx, &tabletParams) @@ -614,7 +614,6 @@ func execute(t *testing.T, conn *mysql.Conn, query string) (*sqltypes.Result, er // StartVttablet is used to start a vttablet from the given cell and type func StartVttablet(t *testing.T, clusterInfo *VTOrcClusterInfo, cell string, isRdonly bool) *cluster.Vttablet { - var tablet *cluster.Vttablet for _, cellInfo := range clusterInfo.CellInfos { if cellInfo.CellName == cell { @@ -818,7 +817,7 @@ func SetupNewClusterSemiSync(t *testing.T) *VTOrcClusterInfo { err = clusterInstance.SetupCluster(keyspace, []cluster.Shard{*shard}) require.NoError(t, err, "Cannot launch cluster: %v", err) - //Start MySql + // Start MySql var mysqlCtlProcessList []*exec.Cmd for _, shard := range clusterInstance.Keyspaces[0].Shards { for _, tablet := range shard.Vttablets { @@ -892,7 +891,7 @@ func AddSemiSyncKeyspace(t *testing.T, clusterInfo *VTOrcClusterInfo) { err := clusterInfo.ClusterInstance.SetupCluster(keyspace, []cluster.Shard{*shard}) require.NoError(t, err, "Cannot launch cluster: %v", err) - //Start MySql + // Start MySql var mysqlCtlProcessList []*exec.Cmd for _, shard := range clusterInfo.ClusterInstance.Keyspaces[1].Shards { for _, tablet := range shard.Vttablets { @@ -994,7 +993,8 @@ func WaitForSuccessfulRecoveryCount(t *testing.T, vtorcInstance *cluster.VTOrcPr startTime := time.Now() for time.Since(startTime) < timeout { vars := vtorcInstance.GetVars() - successfulRecoveriesMap := vars["SuccessfulRecoveries"].(map[string]interface{}) + successfulRecoveriesMap, ok := vars["SuccessfulRecoveries"].(map[string]any) + require.True(t, ok, "SuccessfulRecoveries metric not yet available") successCount := GetIntFromValue(successfulRecoveriesMap[recoveryName]) if successCount == countExpected { return @@ -1002,7 +1002,8 @@ func WaitForSuccessfulRecoveryCount(t *testing.T, vtorcInstance *cluster.VTOrcPr time.Sleep(time.Second) } vars := vtorcInstance.GetVars() - successfulRecoveriesMap := vars["SuccessfulRecoveries"].(map[string]interface{}) + successfulRecoveriesMap, ok := vars["SuccessfulRecoveries"].(map[string]any) + require.True(t, ok, "SuccessfulRecoveries metric not yet available") successCount := GetIntFromValue(successfulRecoveriesMap[recoveryName]) assert.EqualValues(t, countExpected, successCount) } @@ -1083,33 +1084,22 @@ func WaitForDetectedProblems(t *testing.T, vtorcInstance *cluster.VTOrcProcess, t.Helper() key := strings.Join([]string{code, alias, ks, shard}, ".") timeout := 15 * time.Second - startTime := time.Now() - - for time.Since(startTime) < timeout { + require.EventuallyWithT(t, func(c *assert.CollectT) { vars := vtorcInstance.GetVars() - problems := vars["DetectedProblems"].(map[string]interface{}) - actual := GetIntFromValue(problems[key]) - if actual == expect { - return - } - time.Sleep(time.Second) - } - - vars := vtorcInstance.GetVars() - problems := vars["DetectedProblems"].(map[string]interface{}) - actual, ok := problems[key] - actual = GetIntFromValue(actual) - - assert.True(t, ok, - "The metric DetectedProblems[%s] should exist but does not (all problems: %+v)", - key, problems, - ) - - assert.EqualValues(t, expect, actual, - "The metric DetectedProblems[%s] should be %v but is %v (all problems: %+v)", - key, expect, actual, - problems, - ) + problems, ok := vars["DetectedProblems"].(map[string]any) + require.True(c, ok, "DetectedProblems metric not yet available") + actual, ok := problems[key] + actual = GetIntFromValue(actual) + require.True(c, ok, + "The metric DetectedProblems[%s] should exist but does not (all problems: %+v)", + key, problems, + ) + require.EqualValues(c, expect, actual, + "The metric DetectedProblems[%s] should be %v but is %v (all problems: %+v)", + key, expect, actual, + problems, + ) + }, timeout, time.Second, "timed out waiting for detected problem(s)") } // WaitForTabletType waits for the tablet to reach a certain type. @@ -1123,7 +1113,7 @@ func WaitForTabletType(t *testing.T, tablet *cluster.Vttablet, expectedTabletTyp // It expects to find minimum occurrence or exact count of `keyName` provided. func WaitForInstancePollSecondsExceededCount(t *testing.T, vtorcInstance *cluster.VTOrcProcess, keyName string, minCountExpected float64, enforceEquality bool) { t.Helper() - var sinceInSeconds = 30 + sinceInSeconds := 30 duration := time.Duration(sinceInSeconds) time.Sleep(duration * time.Second) diff --git a/go/tools/go-upgrade/go-upgrade.go b/go/tools/go-upgrade/go-upgrade.go index 7b36fd14c02..f1187f1f746 100644 --- a/go/tools/go-upgrade/go-upgrade.go +++ b/go/tools/go-upgrade/go-upgrade.go @@ -31,6 +31,8 @@ import ( "encoding/json" + "github.com/google/go-containerregistry/pkg/crane" + gocr "github.com/google/go-containerregistry/pkg/v1" "github.com/hashicorp/go-version" "github.com/spf13/cobra" ) @@ -38,6 +40,12 @@ import ( const ( goDevAPI = "https://go.dev/dl/?mode=json" + // dockerPlatformOS is the target OS for the Go base image. + dockerPlatformOS = "linux" + + // dockerPlatformArch is the target architecture for the Go base image. + dockerPlatformArch = "amd64" + // regexpFindBootstrapVersion greps the current bootstrap version from the Makefile. The bootstrap // version is composed of either one or two numbers, for instance: 18.1 or 18. // The expected format of the input is BOOTSTRAP_VERSION=18 or BOOTSTRAP_VERSION=18.1 @@ -65,6 +73,20 @@ const ( regexpReplaceTestGoBootstrapVersion = `\"bootstrap-version\",[[:space:]]*\"([0-9.]+)\"` ) +// regexpReplaceGolangDockerImage matches Go image references that the upgrader rewrites. +// +// Supported forms include: +// - ARG image=golang:1.25.3-bookworm@sha256:abc +// - FROM golang:1.25.3-trixie@sha256:abc AS builder +// - FROM --platform=linux/amd64 golang:1.25.3-bookworm@sha256:abc AS builder +// +// The first capture group retains the reference prefix. The second capture group retains the distro. +var regexpReplaceGolangDockerImage = fmt.Sprintf( + `(?i)((?:ARG[[:space:]]+image=|FROM(?:[[:space:]]+--platform=%s/%s)?[[:space:]]+)golang:)[0-9.]+-([a-z0-9]+)@sha256:[a-f0-9]{64}`, + dockerPlatformOS, + dockerPlatformArch, +) + type ( latestGolangRelease struct { Version string `json:"version"` @@ -333,13 +355,13 @@ func chooseNewVersion(curVersion *version.Version, latestVersions version.Collec } // replaceGoVersionInCodebase goes through all the files in the codebase where the -// Golang version must be updated +// Golang version must be updated. func replaceGoVersionInCodebase(old, new *version.Version) error { if old.Equal(new) { return nil } + explore := []string{ - "./test/templates", "./build.env", "./docker/bootstrap/Dockerfile.common", "./docker/lite/Dockerfile", @@ -365,12 +387,19 @@ func replaceGoVersionInCodebase(old, new *version.Version) error { } } - if !isSameMajorMinorVersion(old, new) { + for _, fileToChange := range filesToChange { + err = replaceGolangImageReferencesInFile(fileToChange, new) + if err != nil { + return err + } + } + + if !isSameVersion(old, new) { goModFiles := []string{"./go.mod"} for _, file := range goModFiles { err = replaceInFile( []*regexp.Regexp{regexp.MustCompile(regexpReplaceGoModGoVersion)}, - []string{fmt.Sprintf("go %d.%d", new.Segments()[0], new.Segments()[1])}, + []string{fmt.Sprintf("go %d.%d.%d", new.Segments()[0], new.Segments()[1], new.Segments()[2])}, file, ) if err != nil { @@ -381,13 +410,96 @@ func replaceGoVersionInCodebase(old, new *version.Version) error { return nil } +// replaceGolangImageReferencesInFile rewrites pinned Go image references in the given file. +func replaceGolangImageReferencesInFile(fileToChange string, goVersion *version.Version) error { + contentRaw, err := os.ReadFile(fileToChange) + if err != nil { + return err + } + + content, err := replaceGolangImageReferences(string(contentRaw), goVersion) + if err != nil { + return err + } + + return os.WriteFile(fileToChange, []byte(content), 0o644) +} + +// replaceGolangImageReferences rewrites pinned Go image references while preserving each matched distro. +func replaceGolangImageReferences(content string, goVersion *version.Version) (string, error) { + golangImageRegexp := regexp.MustCompile(regexpReplaceGolangDockerImage) + matches := golangImageRegexp.FindAllStringSubmatch(content, -1) + if len(matches) == 0 { + return content, nil + } + + digestsByDistro := map[string]string{} + for _, match := range matches { + distro := match[2] + if _, ok := digestsByDistro[distro]; ok { + continue + } + + digest, err := resolveGolangImageDigest(goVersion, distro) + if err != nil { + return "", err + } + + digestsByDistro[distro] = digest + } + + var replaceErr error + replaced := golangImageRegexp.ReplaceAllStringFunc(content, func(match string) string { + if replaceErr != nil { + return match + } + + submatch := golangImageRegexp.FindStringSubmatch(match) + if len(submatch) != 3 { + replaceErr = fmt.Errorf("malformatted golang image reference: %s", match) + return match + } + + prefix := submatch[1] + distro := submatch[2] + digest, ok := digestsByDistro[distro] + if !ok { + replaceErr = fmt.Errorf("missing golang digest for distro %s", distro) + return match + } + + return fmt.Sprintf("%s%s@%s", prefix, golangDockerTag(goVersion, distro), digest) + }) + if replaceErr != nil { + return "", replaceErr + } + + return replaced, nil +} + +// resolveGolangImageDigest resolves the pinned digest for the given Go version and distro. +func resolveGolangImageDigest(goVersion *version.Version, distro string) (string, error) { + ref := "golang:" + golangDockerTag(goVersion, distro) + + digest, err := crane.Digest(ref, crane.WithPlatform(&gocr.Platform{OS: dockerPlatformOS, Architecture: dockerPlatformArch})) + if err != nil { + return "", fmt.Errorf("resolve golang digest for %s: %w", ref, err) + } + + return digest, nil +} + +// golangDockerTag returns the Golang Docker tag for the given version and distro. +func golangDockerTag(goVersion *version.Version, distro string) string { + return goVersion.String() + "-" + distro +} + func updateBootstrapVersionInCodebase(old, new string, newGoVersion *version.Version) error { if old == new { return nil } files, err := getListOfFilesInPaths([]string{ "./Makefile", - "./test/templates", }) if err != nil { return err @@ -428,7 +540,7 @@ func updateBootstrapVersionInCodebase(old, new string, newGoVersion *version.Ver } func updateBootstrapChangelog(new string, goVersion *version.Version) error { - file, err := os.OpenFile("./docker/bootstrap/CHANGELOG.md", os.O_RDWR, 0600) + file, err := os.OpenFile("./docker/bootstrap/CHANGELOG.md", os.O_RDWR, 0o644) if err != nil { return err } @@ -451,6 +563,10 @@ func updateBootstrapChangelog(new string, goVersion *version.Version) error { return nil } +func isSameVersion(a, b *version.Version) bool { + return a.Segments()[0] == b.Segments()[0] && a.Segments()[1] == b.Segments()[1] && a.Segments()[2] == b.Segments()[2] +} + func isSameMajorMinorVersion(a, b *version.Version) bool { return a.Segments()[0] == b.Segments()[0] && a.Segments()[1] == b.Segments()[1] } @@ -486,7 +602,7 @@ func replaceInFile(oldexps []*regexp.Regexp, new []string, fileToChange string) panic("old and new should be of the same length") } - f, err := os.OpenFile(fileToChange, os.O_RDWR, 0600) + f, err := os.OpenFile(fileToChange, os.O_RDWR, 0o644) if err != nil { return err } diff --git a/go/tools/go-upgrade/go-upgrade_test.go b/go/tools/go-upgrade/go-upgrade_test.go index 6995ccb4002..8556009ca1c 100644 --- a/go/tools/go-upgrade/go-upgrade_test.go +++ b/go/tools/go-upgrade/go-upgrade_test.go @@ -87,6 +87,38 @@ func TestRegularExpressions(t *testing.T) { require.Equal(t, `flag.String("bootstrap-version", "18.2", "the version identifier to use for the docker images")`, res) }, }, + { + regexp: regexpReplaceGolangDockerImage, + input: "FROM --platform=linux/amd64 golang:1.25.3-bookworm@sha256:414a753c2f67d0efccb01b5f58b3d3a8a2cbb7c012ce9e535418b5b3492b2c24 AS builder", + checkF: func(t *testing.T, regexp *regexp.Regexp, input string) { + res := regexp.ReplaceAllString(input, "${1}1.25.4-${2}@sha256:1111111111111111111111111111111111111111111111111111111111111111") + require.Equal(t, "FROM --platform=linux/amd64 golang:1.25.4-bookworm@sha256:1111111111111111111111111111111111111111111111111111111111111111 AS builder", res) + }, + }, + { + regexp: regexpReplaceGolangDockerImage, + input: "FROM --platform=linux/arm64 golang:1.25.3-bookworm@sha256:414a753c2f67d0efccb01b5f58b3d3a8a2cbb7c012ce9e535418b5b3492b2c24 AS builder", + checkF: func(t *testing.T, regexp *regexp.Regexp, input string) { + res := regexp.ReplaceAllString(input, "${1}1.25.4-${2}@sha256:1111111111111111111111111111111111111111111111111111111111111111") + require.Equal(t, input, res) + }, + }, + { + regexp: regexpReplaceGolangDockerImage, + input: "FROM golang:1.25.3-trixie@sha256:414a753c2f67d0efccb01b5f58b3d3a8a2cbb7c012ce9e535418b5b3492b2c24 AS builder", + checkF: func(t *testing.T, regexp *regexp.Regexp, input string) { + res := regexp.ReplaceAllString(input, "${1}1.25.4-${2}@sha256:1111111111111111111111111111111111111111111111111111111111111111") + require.Equal(t, "FROM golang:1.25.4-trixie@sha256:1111111111111111111111111111111111111111111111111111111111111111 AS builder", res) + }, + }, + { + regexp: regexpReplaceGolangDockerImage, + input: "ARG image=golang:1.25.3-bookworm@sha256:414a753c2f67d0efccb01b5f58b3d3a8a2cbb7c012ce9e535418b5b3492b2c24", + checkF: func(t *testing.T, regexp *regexp.Regexp, input string) { + res := regexp.ReplaceAllString(input, "${1}1.25.4-${2}@sha256:1111111111111111111111111111111111111111111111111111111111111111") + require.Equal(t, "ARG image=golang:1.25.4-bookworm@sha256:1111111111111111111111111111111111111111111111111111111111111111", res) + }, + }, } for _, list := range lists { diff --git a/go/vt/binlog/binlogplayer/message_truncate_test.go b/go/vt/binlog/binlogplayer/message_truncate_test.go new file mode 100644 index 00000000000..ee1b52c1630 --- /dev/null +++ b/go/vt/binlog/binlogplayer/message_truncate_test.go @@ -0,0 +1,103 @@ +/* +Copyright 2026 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package binlogplayer + +import ( + "fmt" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/sqltypes" +) + +// TestMessageTruncateWithBinaryData documents a known encoding asymmetry +// between how binary data is encoded into INSERT queries vs how error messages +// are re-encoded for storage in _vt.vreplication.message (varbinary(1000)). +// +// The INSERT query is built using encodeBytesSQLBytes2 which iterates over +// []byte (byte-by-byte) and uses WriteByte, preserving raw high bytes (128-255) +// as single bytes in the Go string. But when the error message is re-encoded by +// EncodeStringSQL for the UPDATE, it iterates over string (rune-by-rune with +// UTF-8 decoding) and uses WriteRune. Invalid UTF-8 bytes get expanded to +// 3-byte U+FFFD replacement characters, causing the stored value to potentially +// exceed the column limit. +// +// The controller's runBlp() handles this by falling back to a simplified error +// message when setState() fails, preventing an infinite retry loop. +// See: controller.go runBlp() and the fail-binary-no-default-value e2e test. +func TestMessageTruncateWithBinaryData(t *testing.T) { + // Build a realistic error message. The binary data in the INSERT query + // was encoded by encodeBytesSQLBytes2 which preserves raw bytes. So the + // Go string contains raw high bytes (0x80-0xFF) that are NOT valid UTF-8. + var msg strings.Builder + + msg.WriteString("task error: failed inserting rows: Field 'workspace_id' doesn't have a default value (errno 1364) (sqlstate HY000) during query: insert into _vt_vrp_2354fd5f43b850e8a66b2375d6c09642_20260218201401_(chunk,type,`name`,`data`,environment_id) values ") + + // Simulate how encodeBytesSQLBytes2 writes binary values: raw bytes are + // preserved as-is (not re-encoded as UTF-8 runes). Build values that + // contain raw high bytes, similar to bitmap data. + for i := range 30 { + if i > 0 { + msg.WriteString(", ") + } + msg.WriteString(fmt.Sprintf("(0,%d,_binary'", i%4)) + msg.WriteString("id") + msg.WriteString("',_binary'") + // Write raw binary data the way encodeBytesSQLBytes2 does: raw bytes + // including invalid UTF-8 sequences. + msg.WriteByte(0x00) // null byte + msg.WriteByte(0x80) // invalid UTF-8 standalone + msg.WriteByte(0x0d) // carriage return + msg.WriteByte(0xc2) // start of 2-byte UTF-8 sequence... + msg.WriteByte(0xa6) // ...valid pair (U+00A6) + msg.WriteByte(0xff) // invalid UTF-8 + msg.WriteByte(0x80) // invalid UTF-8 standalone + msg.WriteByte(0xfe) // invalid UTF-8 + msg.WriteByte(0x90) // invalid UTF-8 standalone + msg.WriteString("',0)") + } + + fullMessage := msg.String() + require.Greater(t, len(fullMessage), 950, "message should be longer than truncation limit") + + // MessageTruncate correctly limits the raw string to 950 bytes. + truncated := MessageTruncate(fullMessage) + assert.LessOrEqual(t, len(truncated), 950, "MessageTruncate should limit to 950 bytes") + + // Encode for SQL (as setState/setMessage does via encodeString). + encoded := sqltypes.EncodeStringSQL(truncated) + + // Decode (simulating what MySQL stores after processing the UPDATE). + decoded, err := sqltypes.DecodeStringSQL(encoded) + require.NoError(t, err, "DecodeStringSQL should not error") + + // Document the known asymmetry: EncodeStringSQL iterates the string by + // rune (UTF-8 decoding), producing U+FFFD for each invalid byte. WriteRune + // then re-encodes U+FFFD as 3 bytes. The round-trip is NOT symmetric for + // strings containing invalid UTF-8, so the decoded value is larger than + // the input. This can cause the stored value to exceed varbinary(1000). + // + // The controller handles this gracefully by falling back to a simplified + // error message when setState() fails. See controller.go runBlp(). + assert.Greater(t, len(decoded), len(truncated), + "encoding round-trip should expand invalid UTF-8 bytes (known asymmetry)") + assert.Greater(t, len(decoded), 1000, + "decoded value should exceed varbinary(1000) limit (known asymmetry that controller.runBlp handles)") +} diff --git a/go/vt/external/golib/sqlutils/sqlutils.go b/go/vt/external/golib/sqlutils/sqlutils.go index 38b0b0c9e62..8c686f29737 100644 --- a/go/vt/external/golib/sqlutils/sqlutils.go +++ b/go/vt/external/golib/sqlutils/sqlutils.go @@ -135,6 +135,11 @@ func (rm *RowMap) GetTime(key string) time.Time { if t, err := time.Parse(DateTimeFormat, rm.GetString(key)); err == nil { return t } + + if t, err := time.Parse(time.RFC3339Nano, rm.GetString(key)); err == nil { + return t + } + return time.Time{} } diff --git a/go/vt/hook/hook.go b/go/vt/hook/hook.go index 4f402cdcb44..88f42b8efdf 100644 --- a/go/vt/hook/hook.go +++ b/go/vt/hook/hook.go @@ -23,11 +23,12 @@ import ( "io" "os" "os/exec" - "path" + "path/filepath" "strings" "syscall" "time" + "vitess.io/vitess/go/fileutil" vtenv "vitess.io/vitess/go/vt/env" "vitess.io/vitess/go/vt/log" ) @@ -98,11 +99,6 @@ func NewHookWithEnv(name string, params []string, env map[string]string) *Hook { // findHook tries to locate the hook, and returns the exec.Cmd for it. func (hook *Hook) findHook(ctx context.Context) (*exec.Cmd, int, error) { - // Check the hook path. - if strings.Contains(hook.Name, "/") { - return nil, HOOK_INVALID_NAME, fmt.Errorf("hook cannot contain '/'") - } - // Find our root. root, err := vtenv.VtRoot() if err != nil { @@ -110,7 +106,10 @@ func (hook *Hook) findHook(ctx context.Context) (*exec.Cmd, int, error) { } // See if the hook exists. - vthook := path.Join(root, "vthook", hook.Name) + vthook, err := fileutil.SafePathJoin(filepath.Join(root, "vthook"), hook.Name) + if err != nil { + return nil, HOOK_INVALID_NAME, fmt.Errorf("invalid hook name %q: %v", hook.Name, err) + } _, err = os.Stat(vthook) if err != nil { if os.IsNotExist(err) { diff --git a/go/vt/mysqlctl/blackbox/backup_test.go b/go/vt/mysqlctl/blackbox/backup_test.go index b7e35304904..b7eafbbb335 100644 --- a/go/vt/mysqlctl/blackbox/backup_test.go +++ b/go/vt/mysqlctl/blackbox/backup_test.go @@ -20,6 +20,7 @@ package blackbox import ( "bytes" "context" + "encoding/json" "errors" "fmt" "io" @@ -926,3 +927,60 @@ func TestExecuteRestoreFailToReadEachFileTwice(t *testing.T) { require.Equal(t, 5, ss.SourceOpenStats) require.Equal(t, 5, ss.SourceReadStats) } + +func TestBackupRetryPropagatesHashToManifest(t *testing.T) { + ctx := utils.LeakCheckContext(t) + backupRoot, keyspace, shard, ts := SetupCluster(ctx, t, 2, 2) + + bufferPerFiles := make(map[string]*rwCloseFailFirstCall) + be := &mysqlctl.BuiltinBackupEngine{} + bh := &mysqlctl.FakeBackupHandle{} + bh.AddFileReturnF = func(filename string) mysqlctl.FakeBackupHandleAddFileReturn { + _, isRetry := bufferPerFiles[filename] + newBuffer := newWriteCloseFailFirstWrite(isRetry) + bufferPerFiles[filename] = newBuffer + return mysqlctl.FakeBackupHandleAddFileReturn{WriteCloser: newBuffer} + } + + fakedb := fakesqldb.New(t) + defer fakedb.Close() + mysqld := mysqlctl.NewFakeMysqlDaemon(fakedb) + defer mysqld.Close() + mysqld.ExpectedExecuteSuperQueryList = []string{"STOP REPLICA", "START REPLICA"} + + ctx, cancel := context.WithCancel(ctx) + backupResult, err := be.ExecuteBackup(ctx, mysqlctl.BackupParams{ + Logger: logutil.NewMemoryLogger(), + Mysqld: mysqld, + Cnf: &mysqlctl.Mycnf{ + InnodbDataHomeDir: path.Join(backupRoot, "innodb"), + InnodbLogGroupHomeDir: path.Join(backupRoot, "log"), + DataDir: path.Join(backupRoot, "datadir"), + }, + Stats: backupstats.NewFakeStats(), + Concurrency: 1, + HookExtraEnv: map[string]string{}, + TopoServer: ts, + Keyspace: keyspace, + Shard: shard, + MysqlShutdownTimeout: MysqlShutdownTimeout, + }, bh) + cancel() + + require.NoError(t, err) + require.Equal(t, mysqlctl.BackupUsable, backupResult) + + // Parse the MANIFEST and verify all file entries have non-empty hashes. + manifestBuf, ok := bufferPerFiles["MANIFEST"] + require.True(t, ok, "MANIFEST should have been written") + + var manifest struct { + FileEntries []mysqlctl.FileEntry + } + require.NoError(t, json.Unmarshal(manifestBuf.Bytes(), &manifest)) + + require.NotEmpty(t, manifest.FileEntries, "manifest should contain file entries") + for _, fe := range manifest.FileEntries { + assert.NotEmptyf(t, fe.Hash, "file %s should have a non-empty hash in the manifest", fe.Name) + } +} diff --git a/go/vt/mysqlctl/builtinbackupengine.go b/go/vt/mysqlctl/builtinbackupengine.go index 61855ee9db6..fa1fee4d186 100644 --- a/go/vt/mysqlctl/builtinbackupengine.go +++ b/go/vt/mysqlctl/builtinbackupengine.go @@ -36,6 +36,7 @@ import ( "github.com/spf13/pflag" "golang.org/x/sync/errgroup" + "vitess.io/vitess/go/fileutil" "vitess.io/vitess/go/ioutil" "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/mysql/replication" @@ -178,7 +179,9 @@ func registerBuiltinBackupEngineFlags(fs *pflag.FlagSet) { fs.StringVar(&builtinIncrementalRestorePath, "builtinbackup-incremental-restore-path", builtinIncrementalRestorePath, "the directory where incremental restore files, namely binlog files, are extracted to. In k8s environments, this should be set to a directory that is shared between the vttablet and mysqld pods. The path should exist. When empty, the default OS temp dir is assumed.") } -// fullPath returns the full path of the entry, based on its type +// fullPath returns the full path of the entry, based on its type. +// It validates that the resolved path does not escape the base directory +// via path traversal (e.g. "../../" sequences in fe.Name). func (fe *FileEntry) fullPath(cnf *Mycnf) (string, error) { // find the root to use var root string @@ -195,7 +198,7 @@ func (fe *FileEntry) fullPath(cnf *Mycnf) (string, error) { return "", vterrors.Errorf(vtrpcpb.Code_UNKNOWN, "unknown base: %v", fe.Base) } - return path.Join(fe.ParentPath, root, fe.Name), nil + return fileutil.SafePathJoin(path.Join(fe.ParentPath, root), fe.Name) } // open attempts to open the file @@ -653,6 +656,13 @@ func (be *BuiltinBackupEngine) backupFiles( if err != nil { return err } + // Propagate retry results back to the original entries so the + // manifest records correct hashes and metadata. + for i, fe := range newFEs { + if fe.Name != "" { + fes[i] = fe + } + } } // Backup the MANIFEST file and apply retry logic. @@ -1316,10 +1326,7 @@ func (be *BuiltinBackupEngine) restoreFile(ctx context.Context, params RestorePa // for backward compatibility deCompressionEngine = PgzipCompressor } - externalDecompressorCmd := ExternalDecompressorCmd - if externalDecompressorCmd == "" && bm.ExternalDecompressor != "" { - externalDecompressorCmd = bm.ExternalDecompressor - } + externalDecompressorCmd := resolveExternalDecompressor(bm.ExternalDecompressor) if externalDecompressorCmd != "" { if deCompressionEngine == ExternalCompressor { deCompressionEngine = externalDecompressorCmd diff --git a/go/vt/mysqlctl/builtinbackupengine_test.go b/go/vt/mysqlctl/builtinbackupengine_test.go index 39e4aa7ae1c..61b1abdf3c2 100644 --- a/go/vt/mysqlctl/builtinbackupengine_test.go +++ b/go/vt/mysqlctl/builtinbackupengine_test.go @@ -21,7 +21,9 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/fileutil" tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" ) @@ -70,6 +72,93 @@ func TestGetIncrementalFromPosGTIDSet(t *testing.T) { } } +func TestFileEntryFullPath(t *testing.T) { + cnf := &Mycnf{ + DataDir: "/vt/data", + InnodbDataHomeDir: "/vt/innodb-data", + InnodbLogGroupHomeDir: "/vt/innodb-log", + BinLogPath: "/vt/binlogs/mysql-bin", + } + + tests := []struct { + name string + entry FileEntry + wantPath string + wantError error + }{ + { + name: "valid relative path in DataDir", + entry: FileEntry{Base: backupData, Name: "mydb/table1.ibd"}, + wantPath: "/vt/data/mydb/table1.ibd", + }, + { + name: "valid relative path in InnodbDataHomeDir", + entry: FileEntry{Base: backupInnodbDataHomeDir, Name: "ibdata1"}, + wantPath: "/vt/innodb-data/ibdata1", + }, + { + name: "valid relative path in InnodbLogGroupHomeDir", + entry: FileEntry{Base: backupInnodbLogGroupHomeDir, Name: "ib_logfile0"}, + wantPath: "/vt/innodb-log/ib_logfile0", + }, + { + name: "valid relative path in BinlogDir", + entry: FileEntry{Base: backupBinlogDir, Name: "mysql-bin.000001"}, + wantPath: "/vt/binlogs/mysql-bin.000001", + }, + { + name: "valid path with ParentPath", + entry: FileEntry{Base: backupData, Name: "mydb/table1.ibd", ParentPath: "/tmp/restore"}, + wantPath: "/tmp/restore/vt/data/mydb/table1.ibd", + }, + { + name: "path traversal escapes base directory", + entry: FileEntry{Base: backupData, Name: "../../etc/passwd"}, + wantError: fileutil.ErrInvalidJoinedPath, + }, + { + name: "path traversal with deeper nesting", + entry: FileEntry{Base: backupData, Name: "mydb/../../../etc/shadow"}, + wantError: fileutil.ErrInvalidJoinedPath, + }, + { + name: "path traversal to root", + entry: FileEntry{Base: backupData, Name: "../../../../../etc/crontab"}, + wantError: fileutil.ErrInvalidJoinedPath, + }, + { + name: "path traversal escapes ParentPath", + entry: FileEntry{Base: backupData, Name: "../../../../etc/passwd", ParentPath: "/tmp/restore"}, + wantError: fileutil.ErrInvalidJoinedPath, + }, + { + name: "relative path with dot-dot that stays within base", + entry: FileEntry{Base: backupData, Name: "mydb/../mydb/table1.ibd"}, + wantPath: "/vt/data/mydb/table1.ibd", + }, + } + + // Test unknown base separately since it returns a different error type. + t.Run("unknown base", func(t *testing.T) { + entry := FileEntry{Base: "unknown", Name: "file"} + _, err := entry.fullPath(cnf) + require.Error(t, err) + assert.Contains(t, err.Error(), "unknown base") + }) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := tt.entry.fullPath(cnf) + if tt.wantError != nil { + require.ErrorIs(t, err, tt.wantError) + } else { + require.NoError(t, err) + assert.Equal(t, tt.wantPath, got) + } + }) + } +} + func TestShouldDrainForBackupBuiltIn(t *testing.T) { be := &BuiltinBackupEngine{} diff --git a/go/vt/mysqlctl/compression.go b/go/vt/mysqlctl/compression.go index c2d3cbbe18b..5737b70b791 100644 --- a/go/vt/mysqlctl/compression.go +++ b/go/vt/mysqlctl/compression.go @@ -52,9 +52,10 @@ var ( ExternalCompressorCmd string ExternalCompressorExt string ExternalDecompressorCmd string + ExternalDecompressorUseManifest bool ManifestExternalDecompressorCmd string - errUnsupportedDeCompressionEngine = errors.New("unsupported engine in MANIFEST. You need to provide --external-decompressor if using 'external' compression engine") + errUnsupportedDeCompressionEngine = errors.New("unsupported engine in MANIFEST. You need to provide --external-decompressor if using 'external' compression engine. Alternatively, set --external-decompressor-use-manifest to use the decompressor command from the backup manifest, but this is NOT RECOMMENDED as it is a security risk") errUnsupportedCompressionEngine = errors.New("unsupported engine value for --compression-engine-name. supported values are 'external', 'pgzip', 'pargzip', 'zstd', 'lz4'") // this is used by getEngineFromExtension() to figure out which engine to use in case the user didn't specify @@ -77,6 +78,7 @@ func registerBackupCompressionFlags(fs *pflag.FlagSet) { fs.StringVar(&ExternalCompressorCmd, "external-compressor", ExternalCompressorCmd, "command with arguments to use when compressing a backup.") fs.StringVar(&ExternalCompressorExt, "external-compressor-extension", ExternalCompressorExt, "extension to use when using an external compressor.") fs.StringVar(&ExternalDecompressorCmd, "external-decompressor", ExternalDecompressorCmd, "command with arguments to use when decompressing a backup.") + fs.BoolVar(&ExternalDecompressorUseManifest, "external-decompressor-use-manifest", ExternalDecompressorUseManifest, "allows the decompressor command stored in the backup manifest to be used at restore time. Enabling this is a security risk: an attacker with write access to the backup storage could modify the manifest to execute arbitrary commands on the tablet as the Vitess user. NOT RECOMMENDED.") fs.StringVar(&ManifestExternalDecompressorCmd, "manifest-external-decompressor", ManifestExternalDecompressorCmd, "command with arguments to store in the backup manifest when compressing a backup with an external compression engine.") } @@ -91,6 +93,20 @@ func getExtensionFromEngine(engine string) (string, error) { return "", fmt.Errorf("%w %q", errUnsupportedCompressionEngine, engine) } +// resolveExternalDecompressor returns the external decompressor command to use +// at restore time. The CLI flag (--external-decompressor) takes precedence. The +// backup manifest value is only used when --external-decompressor-use-manifest +// is explicitly set to true. +func resolveExternalDecompressor(manifestDecompressor string) string { + if ExternalDecompressorCmd != "" { + return ExternalDecompressorCmd + } + if ExternalDecompressorUseManifest && manifestDecompressor != "" { + return manifestDecompressor + } + return "" +} + // Validates if the external decompressor exists and return its path. func validateExternalCmd(cmd string) (string, error) { if cmd == "" { diff --git a/go/vt/mysqlctl/compression_external_decompressor_test.go b/go/vt/mysqlctl/compression_external_decompressor_test.go new file mode 100644 index 00000000000..fd4732aff24 --- /dev/null +++ b/go/vt/mysqlctl/compression_external_decompressor_test.go @@ -0,0 +1,93 @@ +/* +Copyright 2026 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package mysqlctl + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestResolveExternalDecompressor(t *testing.T) { + tests := []struct { + name string + cliDecompressorCmd string + useManifest bool + manifestDecompressor string + expected string + }{ + { + name: "CLI flag takes precedence over manifest", + cliDecompressorCmd: "zstd -d", + useManifest: true, + manifestDecompressor: "gzip -d", + expected: "zstd -d", + }, + { + name: "CLI flag takes precedence even when use-manifest is false", + cliDecompressorCmd: "zstd -d", + useManifest: false, + manifestDecompressor: "gzip -d", + expected: "zstd -d", + }, + { + name: "manifest used when use-manifest is true and no CLI flag", + cliDecompressorCmd: "", + useManifest: true, + manifestDecompressor: "gzip -d", + expected: "gzip -d", + }, + { + name: "manifest ignored when use-manifest is false", + cliDecompressorCmd: "", + useManifest: false, + manifestDecompressor: "gzip -d", + expected: "", + }, + { + name: "empty when nothing is set", + cliDecompressorCmd: "", + useManifest: false, + manifestDecompressor: "", + expected: "", + }, + { + name: "empty when use-manifest is true but manifest is empty", + cliDecompressorCmd: "", + useManifest: true, + manifestDecompressor: "", + expected: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + origCmd := ExternalDecompressorCmd + origAllow := ExternalDecompressorUseManifest + t.Cleanup(func() { + ExternalDecompressorCmd = origCmd + ExternalDecompressorUseManifest = origAllow + }) + + ExternalDecompressorCmd = tt.cliDecompressorCmd + ExternalDecompressorUseManifest = tt.useManifest + + result := resolveExternalDecompressor(tt.manifestDecompressor) + assert.Equal(t, tt.expected, result) + }) + } +} diff --git a/go/vt/mysqlctl/fakemysqldaemon.go b/go/vt/mysqlctl/fakemysqldaemon.go index a2b5e66bd49..eccf6011278 100644 --- a/go/vt/mysqlctl/fakemysqldaemon.go +++ b/go/vt/mysqlctl/fakemysqldaemon.go @@ -137,6 +137,9 @@ type FakeMysqlDaemon struct { // SetReplicationSourceError is used by SetReplicationSource. SetReplicationSourceError error + // SetReplicationSourceFunc overrides SetReplicationSource when it is set. + SetReplicationSourceFunc func(ctx context.Context, host string, port int32, heartbeatInterval float64, stopReplicationBefore bool, startReplicationAfter bool) error + // StopReplicationError error is used by StopReplication. StopReplicationError error @@ -515,6 +518,10 @@ func (fmd *FakeMysqlDaemon) SetReplicationPosition(ctx context.Context, pos repl // SetReplicationSource is part of the MysqlDaemon interface. func (fmd *FakeMysqlDaemon) SetReplicationSource(ctx context.Context, host string, port int32, heartbeatInterval float64, stopReplicationBefore bool, startReplicationAfter bool) error { + if fmd.SetReplicationSourceFunc != nil { + return fmd.SetReplicationSourceFunc(ctx, host, port, heartbeatInterval, stopReplicationBefore, startReplicationAfter) + } + input := fmt.Sprintf("%v:%v", host, port) found := false for _, sourceInput := range fmd.SetReplicationSourceInputs { @@ -763,6 +770,11 @@ func (fmd *FakeMysqlDaemon) SemiSyncReplicationStatus(ctx context.Context) (bool return fmd.SemiSyncReplicaEnabled, nil } +// IsSemiSyncBlocked is part of the MysqlDaemon interface. +func (fmd *FakeMysqlDaemon) IsSemiSyncBlocked(ctx context.Context) (bool, error) { + return false, nil +} + // GetVersionString is part of the MysqlDaemon interface. func (fmd *FakeMysqlDaemon) GetVersionString(ctx context.Context) (string, error) { return fmd.Version, nil diff --git a/go/vt/mysqlctl/filebackupstorage/file.go b/go/vt/mysqlctl/filebackupstorage/file.go index bff054692dc..c841e4ce479 100644 --- a/go/vt/mysqlctl/filebackupstorage/file.go +++ b/go/vt/mysqlctl/filebackupstorage/file.go @@ -23,7 +23,6 @@ import ( "fmt" "io" "os" - "path" "github.com/spf13/pflag" @@ -96,7 +95,10 @@ func (fbh *FileBackupHandle) AddFile(ctx context.Context, filename string, files if fbh.readOnly { return nil, fmt.Errorf("AddFile cannot be called on read-only backup") } - p := path.Join(FileBackupStorageRoot, fbh.dir, fbh.name, filename) + p, err := fileutil.SafePathJoin(FileBackupStorageRoot, fbh.dir, fbh.name, filename) + if err != nil { + return nil, err + } f, err := os2.Create(p) if err != nil { return nil, err @@ -188,7 +190,10 @@ func (fbs *FileBackupStorage) StartBackup(ctx context.Context, dir, name string) } // Create the subdirectory for this named backup. - p = path.Join(p, name) + p, err = fileutil.SafePathJoin(p, name) + if err != nil { + return nil, err + } if err = os2.Mkdir(p); err != nil { return nil, err } diff --git a/go/vt/mysqlctl/mysql_daemon.go b/go/vt/mysqlctl/mysql_daemon.go index f7a564c7bec..048f1bd89c8 100644 --- a/go/vt/mysqlctl/mysql_daemon.go +++ b/go/vt/mysqlctl/mysql_daemon.go @@ -74,6 +74,7 @@ type MysqlDaemon interface { SemiSyncClients(ctx context.Context) (count uint32) SemiSyncSettings(ctx context.Context) (timeout uint64, numReplicas uint32) SemiSyncReplicationStatus(ctx context.Context) (bool, error) + IsSemiSyncBlocked(ctx context.Context) (bool, error) ResetReplicationParameters(ctx context.Context) error GetBinlogInformation(ctx context.Context) (binlogFormat string, logEnabled bool, logReplicaUpdate bool, binlogRowImage string, err error) GetGTIDMode(ctx context.Context) (gtidMode string, err error) diff --git a/go/vt/mysqlctl/mysqlshellbackupengine.go b/go/vt/mysqlctl/mysqlshellbackupengine.go index ac40d9adc17..74bc312dee6 100644 --- a/go/vt/mysqlctl/mysqlshellbackupengine.go +++ b/go/vt/mysqlctl/mysqlshellbackupengine.go @@ -18,6 +18,7 @@ package mysqlctl import ( "bufio" + "bytes" "context" "encoding/json" "errors" @@ -26,18 +27,22 @@ import ( "os" "os/exec" "path" + "path/filepath" "slices" "strings" "sync" "time" + "github.com/google/shlex" "github.com/spf13/pflag" + "vitess.io/vitess/go/fileutil" "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/mysql/capabilities" "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/mysqlctl/backupstorage" tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" + vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" "vitess.io/vitess/go/vt/servenv" "vitess.io/vitess/go/vt/vterrors" ) @@ -117,9 +122,12 @@ const ( func (be *MySQLShellBackupEngine) ExecuteBackup(ctx context.Context, params BackupParams, bh backupstorage.BackupHandle) (result BackupResult, finalErr error) { params.Logger.Infof("Starting ExecuteBackup in %s", params.TabletAlias) - location := path.Join(mysqlShellBackupLocation, bh.Directory(), bh.Name()) + location, err := be.backupLocation(bh.Directory(), bh.Name()) + if err != nil { + return BackupUnusable, vterrors.Wrap(err, "cannot safely determine backup location") + } - err := be.backupPreCheck(location) + err = be.backupPreCheck(location) if err != nil { return BackupUnusable, vterrors.Wrap(err, "failed backup precheck") } @@ -134,14 +142,20 @@ func (be *MySQLShellBackupEngine) ExecuteBackup(ctx context.Context, params Back return BackupUnusable, vterrors.Wrap(err, "can't get MySQL version") } - args := []string{} - if mysqlShellFlags != "" { - args = append(args, strings.Fields(mysqlShellFlags)...) + args, err := shlex.Split(mysqlShellFlags) + if err != nil { + return BackupUnusable, vterrors.Wrap(err, "failed to parse --mysql-shell-flags") + } + + // compact and validate the json input from mysqlShellDumpFlags. + var compactDumpFlags bytes.Buffer + if err := json.Compact(&compactDumpFlags, []byte(mysqlShellDumpFlags)); err != nil { + return BackupUnusable, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "failed to parse --mysql-shell-dump-flags as JSON: %v", err) } args = append(args, "-e", fmt.Sprintf("util.dumpInstance(%q, %s)", location, - mysqlShellDumpFlags, + compactDumpFlags.String(), )) // to be able to get the consistent GTID sets, we will acquire a global read lock before starting mysql shell. @@ -254,6 +268,24 @@ func (be *MySQLShellBackupEngine) ExecuteRestore(ctx context.Context, params Res return nil, err } + // Validate bm.BackupLocation from the MANIFEST. For local filesystem + // mode, use SafePathJoin to prevent path traversal. For object storage, + // trust the manifest location directly since SafePathJoin relies on + // OS-native path operations that don't understand cloud URIs. + var location string + if isObjectStoreFlags(mysqlShellLoadFlags) { + location = bm.BackupLocation + } else { + relLocation, err := filepath.Rel(mysqlShellBackupLocation, bm.BackupLocation) + if err != nil { + return nil, vterrors.Wrapf(err, "cannot determine relative backup location from manifest") + } + location, err = fileutil.SafePathJoin(mysqlShellBackupLocation, relLocation) + if err != nil { + return nil, vterrors.Wrapf(err, "backup location %q in manifest is outside the backup root %q", bm.BackupLocation, mysqlShellBackupLocation) + } + } + // mark restore as in progress if err := createStateFile(params.Cnf); err != nil { return nil, err @@ -331,15 +363,20 @@ func (be *MySQLShellBackupEngine) ExecuteRestore(ctx context.Context, params Res } defer resetFunc() - args := []string{} + args, err := shlex.Split(mysqlShellFlags) + if err != nil { + return nil, vterrors.Wrap(err, "failed to parse --mysql-shell-flags") + } - if mysqlShellFlags != "" { - args = append(args, strings.Fields(mysqlShellFlags)...) + // compact and validate the json input from mysqlShellLoadFlags. + var compactLoadFlags bytes.Buffer + if err := json.Compact(&compactLoadFlags, []byte(mysqlShellLoadFlags)); err != nil { + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "failed to parse --mysql-shell-load-flags as JSON: %v", err) } args = append(args, "-e", fmt.Sprintf("util.loadDump(%q, %s)", - bm.BackupLocation, - mysqlShellLoadFlags, + location, + compactLoadFlags.String(), )) cmd := exec.CommandContext(ctx, "mysqlsh", args...) @@ -396,6 +433,30 @@ func (be *MySQLShellBackupEngine) ShouldStartMySQLAfterRestore() bool { func (be *MySQLShellBackupEngine) Name() string { return mysqlShellBackupEngineName } +// isObjectStoreFlags returns true if the given flags JSON string contains +// any known object store parameters, indicating cloud storage is in use. +func isObjectStoreFlags(flags string) bool { + for _, objStore := range knownObjectStoreParams { + if strings.Contains(flags, objStore) { + return true + } + } + return false +} + +// backupLocation returns a backup location path by joining the configured +// mysqlShellBackupLocation with the provided directory and name components. +// For local filesystem mode, it uses fileutil.SafePathJoin to prevent path +// traversal outside the configured backup location. For object storage, +// path.Join is used since SafePathJoin relies on OS-native path operations +// that don't understand cloud URIs. +func (be *MySQLShellBackupEngine) backupLocation(dir, name string) (string, error) { + if isObjectStoreFlags(mysqlShellDumpFlags) { + return path.Join(mysqlShellBackupLocation, dir, name), nil + } + return fileutil.SafePathJoin(mysqlShellBackupLocation, dir, name) +} + func (be *MySQLShellBackupEngine) backupPreCheck(location string) error { if mysqlShellBackupLocation == "" { return fmt.Errorf("%w: no backup location set via --mysql-shell-backup-location", ErrMySQLShellPreCheck) @@ -405,17 +466,9 @@ func (be *MySQLShellBackupEngine) backupPreCheck(location string) error { return fmt.Errorf("%w: at least the --js flag is required in the value of the flag --mysql-shell-flags", ErrMySQLShellPreCheck) } - // make sure the targe directory exists if the target location for the backup is not an object store + // make sure the target directory exists if the target location for the backup is not an object store // (e.g. is the local filesystem) as MySQL Shell doesn't create the entire path beforehand: - isObjectStorage := false - for _, objStore := range knownObjectStoreParams { - if strings.Contains(mysqlShellDumpFlags, objStore) { - isObjectStorage = true - break - } - } - - if !isObjectStorage { + if !isObjectStoreFlags(mysqlShellDumpFlags) { err := os.MkdirAll(location, 0o750) if err != nil { return fmt.Errorf("failure creating directory %s: %w", location, err) diff --git a/go/vt/mysqlctl/replication.go b/go/vt/mysqlctl/replication.go index bd244d4f5c7..1aabafe85f1 100644 --- a/go/vt/mysqlctl/replication.go +++ b/go/vt/mysqlctl/replication.go @@ -819,3 +819,30 @@ func (mysqld *Mysqld) SemiSyncExtensionLoaded(ctx context.Context) (mysql.SemiSy return conn.Conn.SemiSyncExtensionLoaded() } + +func (mysqld *Mysqld) IsSemiSyncBlocked(ctx context.Context) (bool, error) { + conn, err := getPoolReconnect(ctx, mysqld.dbaPool) + if err != nil { + return false, err + } + defer conn.Recycle() + + // Execute the query to check if the primary is blocked on semi-sync. + semiSyncWaitSessionsRead := "select variable_value from performance_schema.global_status where regexp_like(variable_name, 'Rpl_semi_sync_(source|master)_wait_sessions')" + res, err := conn.Conn.ExecuteFetch(semiSyncWaitSessionsRead, 1, false) + if err != nil { + return false, err + } + // If we have no rows, then the primary doesn't have semi-sync enabled. + // It then follows, that the primary isn't blocked :) + if len(res.Rows) == 0 { + return false, nil + } + + // Read the status value and check if it is non-zero. + if len(res.Rows) != 1 || len(res.Rows[0]) != 1 { + return false, fmt.Errorf("unexpected number of rows received - %v", res.Rows) + } + value, err := res.Rows[0][0].ToCastInt64() + return value != 0, err +} diff --git a/go/vt/mysqlctl/xtrabackupengine.go b/go/vt/mysqlctl/xtrabackupengine.go index 639f30d7f4d..cdd5ebadba9 100644 --- a/go/vt/mysqlctl/xtrabackupengine.go +++ b/go/vt/mysqlctl/xtrabackupengine.go @@ -30,6 +30,7 @@ import ( "sync" "time" + "github.com/google/shlex" "github.com/spf13/pflag" "vitess.io/vitess/go/ioutil" @@ -306,7 +307,11 @@ func (be *XtrabackupEngine) backupFiles( flagsToExec = append(flagsToExec, "--stream="+xtrabackupStreamMode) } if xtrabackupBackupFlags != "" { - flagsToExec = append(flagsToExec, strings.Fields(xtrabackupBackupFlags)...) + backupFlags, err := shlex.Split(xtrabackupBackupFlags) + if err != nil { + return replicationPosition, vterrors.Wrap(err, "failed to parse --xtrabackup-backup-flags") + } + flagsToExec = append(flagsToExec, backupFlags...) } // Create a cancellable Context for calls to bh.AddFile(). @@ -535,7 +540,11 @@ func (be *XtrabackupEngine) restoreFromBackup(ctx context.Context, cnf *Mycnf, b "--target-dir=" + tempDir, } if xtrabackupPrepareFlags != "" { - flagsToExec = append(flagsToExec, strings.Fields(xtrabackupPrepareFlags)...) + prepareFlags, err := shlex.Split(xtrabackupPrepareFlags) + if err != nil { + return vterrors.Wrap(err, "failed to parse --xtrabackup-prepare-flags") + } + flagsToExec = append(flagsToExec, prepareFlags...) } prepareCmd := exec.CommandContext(ctx, restoreProgram, flagsToExec...) prepareOut, err := prepareCmd.StdoutPipe() @@ -638,10 +647,7 @@ func (be *XtrabackupEngine) extractFiles(ctx context.Context, logger logutil.Log // then we assign the default value of compressionEngine. deCompressionEngine = PgzipCompressor } - externalDecompressorCmd := ExternalDecompressorCmd - if externalDecompressorCmd == "" && bm.ExternalDecompressor != "" { - externalDecompressorCmd = bm.ExternalDecompressor - } + externalDecompressorCmd := resolveExternalDecompressor(bm.ExternalDecompressor) if externalDecompressorCmd != "" { if deCompressionEngine == ExternalCompressor { deCompressionEngine = externalDecompressorCmd @@ -711,7 +717,11 @@ func (be *XtrabackupEngine) extractFiles(ctx context.Context, logger logutil.Log xbstreamProgram := path.Join(xtrabackupEnginePath, xbstream) flagsToExec := []string{"-C", tempDir, "-xv"} if xbstreamRestoreFlags != "" { - flagsToExec = append(flagsToExec, strings.Fields(xbstreamRestoreFlags)...) + restoreFlags, err := shlex.Split(xbstreamRestoreFlags) + if err != nil { + return vterrors.Wrap(err, "failed to parse --xbstream-restore-flags") + } + flagsToExec = append(flagsToExec, restoreFlags...) } xbstreamCmd := exec.CommandContext(ctx, xbstreamProgram, flagsToExec...) logger.Infof("Executing xbstream cmd: %v %v", xbstreamProgram, flagsToExec) diff --git a/go/vt/proto/tabletmanagerdata/tabletmanagerdata.pb.go b/go/vt/proto/tabletmanagerdata/tabletmanagerdata.pb.go index 7540ee2b4e5..9e3d9f2e384 100644 --- a/go/vt/proto/tabletmanagerdata/tabletmanagerdata.pb.go +++ b/go/vt/proto/tabletmanagerdata/tabletmanagerdata.pb.go @@ -4380,6 +4380,7 @@ func (*InitReplicaResponse) Descriptor() ([]byte, []int) { type DemotePrimaryRequest struct { state protoimpl.MessageState `protogen:"open.v1"` + Force bool `protobuf:"varint,1,opt,name=force,proto3" json:"force,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -4414,6 +4415,13 @@ func (*DemotePrimaryRequest) Descriptor() ([]byte, []int) { return file_tabletmanagerdata_proto_rawDescGZIP(), []int{90} } +func (x *DemotePrimaryRequest) GetForce() bool { + if x != nil { + return x.Force + } + return false +} + type DemotePrimaryResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // PrimaryStatus represents the response from calling `SHOW BINARY LOG STATUS` on a primary that has been demoted. @@ -8507,724 +8515,725 @@ var file_tabletmanagerdata_proto_rawDesc = string([]byte{ 0x0a, 0x08, 0x73, 0x65, 0x6d, 0x69, 0x53, 0x79, 0x6e, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x73, 0x65, 0x6d, 0x69, 0x53, 0x79, 0x6e, 0x63, 0x22, 0x15, 0x0a, 0x13, 0x49, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x16, 0x0a, 0x14, 0x44, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x72, 0x69, 0x6d, 0x61, - 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x64, 0x0a, 0x15, 0x44, 0x65, 0x6d, - 0x6f, 0x74, 0x65, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0e, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x72, 0x65, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x50, 0x72, 0x69, - 0x6d, 0x61, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0d, 0x70, 0x72, 0x69, 0x6d, - 0x61, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x22, - 0x36, 0x0a, 0x18, 0x55, 0x6e, 0x64, 0x6f, 0x44, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x72, 0x69, - 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, - 0x65, 0x6d, 0x69, 0x53, 0x79, 0x6e, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x73, - 0x65, 0x6d, 0x69, 0x53, 0x79, 0x6e, 0x63, 0x22, 0x1b, 0x0a, 0x19, 0x55, 0x6e, 0x64, 0x6f, 0x44, - 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x0a, 0x19, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x57, - 0x61, 0x73, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x22, 0x1c, 0x0a, 0x1a, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x57, 0x61, 0x73, 0x50, - 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x23, 0x0a, 0x21, 0x52, 0x65, 0x73, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x22, 0x24, 0x0a, 0x22, 0x52, 0x65, 0x73, 0x65, 0x74, 0x52, 0x65, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, - 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x13, 0x0a, 0x11, 0x46, 0x75, - 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, - 0x49, 0x0a, 0x12, 0x46, 0x75, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x46, 0x75, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x9c, 0x02, 0x0a, 0x1b, 0x53, - 0x65, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x06, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x6f, 0x70, - 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, - 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x74, 0x69, 0x6d, - 0x65, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0d, 0x74, 0x69, 0x6d, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x4e, - 0x73, 0x12, 0x36, 0x0a, 0x17, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, - 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x15, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x77, 0x61, 0x69, - 0x74, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x77, 0x61, 0x69, 0x74, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, - 0x0a, 0x08, 0x73, 0x65, 0x6d, 0x69, 0x53, 0x79, 0x6e, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x08, 0x73, 0x65, 0x6d, 0x69, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x2d, 0x0a, 0x12, 0x68, 0x65, - 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x11, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, - 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x22, 0x1e, 0x0a, 0x1c, 0x53, 0x65, 0x74, - 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4b, 0x0a, 0x1a, 0x52, 0x65, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x57, 0x61, 0x73, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, - 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x52, 0x06, - 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x22, 0x1d, 0x0a, 0x1b, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x57, 0x61, 0x73, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x7e, 0x0a, 0x22, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x47, 0x65, 0x74, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x58, 0x0a, 0x15, 0x73, - 0x74, 0x6f, 0x70, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x72, 0x65, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x74, 0x6f, - 0x70, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, - 0x52, 0x13, 0x73, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0x6b, 0x0a, 0x23, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x47, 0x65, 0x74, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x72, - 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, - 0x74, 0x6f, 0x70, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x4a, 0x04, 0x08, 0x01, - 0x10, 0x02, 0x22, 0x33, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, - 0x65, 0x6d, 0x69, 0x53, 0x79, 0x6e, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x73, - 0x65, 0x6d, 0x69, 0x53, 0x79, 0x6e, 0x63, 0x22, 0x34, 0x0a, 0x16, 0x50, 0x72, 0x6f, 0x6d, 0x6f, - 0x74, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xaf, 0x02, - 0x0a, 0x0d, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, - 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, - 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x50, - 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x30, 0x0a, 0x14, 0x69, 0x6e, 0x63, 0x72, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x70, 0x6f, 0x73, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x69, 0x6e, 0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, - 0x6c, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x6f, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x70, 0x67, 0x72, - 0x61, 0x64, 0x65, 0x5f, 0x73, 0x61, 0x66, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, - 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x53, 0x61, 0x66, 0x65, 0x12, 0x28, 0x0a, 0x0d, 0x62, - 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x45, 0x6e, 0x67, 0x69, - 0x6e, 0x65, 0x88, 0x01, 0x01, 0x12, 0x46, 0x0a, 0x16, 0x6d, 0x79, 0x73, 0x71, 0x6c, 0x5f, 0x73, - 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x44, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x14, 0x6d, 0x79, 0x73, 0x71, 0x6c, 0x53, 0x68, - 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x42, 0x10, 0x0a, - 0x0e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x22, - 0x36, 0x0a, 0x0e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x24, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0e, 0x2e, 0x6c, 0x6f, 0x67, 0x75, 0x74, 0x69, 0x6c, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0xfe, 0x01, 0x0a, 0x18, 0x52, 0x65, 0x73, 0x74, - 0x6f, 0x72, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x0b, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x74, - 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x76, 0x74, 0x74, 0x69, - 0x6d, 0x65, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x0a, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x54, - 0x69, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x74, - 0x6f, 0x5f, 0x70, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, - 0x74, 0x6f, 0x72, 0x65, 0x54, 0x6f, 0x50, 0x6f, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, - 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, - 0x75, 0x6e, 0x12, 0x3e, 0x0a, 0x14, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x74, 0x6f, - 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0c, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x12, - 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x54, 0x6f, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x12, 0x34, 0x0a, 0x16, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x62, 0x61, - 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x14, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x42, 0x61, 0x63, 0x6b, 0x75, - 0x70, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x41, 0x0a, 0x19, 0x52, 0x65, 0x73, 0x74, - 0x6f, 0x72, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6c, 0x6f, 0x67, 0x75, 0x74, 0x69, 0x6c, 0x2e, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0xee, 0x04, 0x0a, 0x21, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x65, 0x22, 0x2c, 0x0a, 0x14, 0x44, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x72, 0x69, 0x6d, 0x61, + 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, + 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x22, + 0x64, 0x0a, 0x15, 0x44, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0e, 0x70, 0x72, 0x69, 0x6d, + 0x61, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1e, 0x2e, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x64, 0x61, + 0x74, 0x61, 0x2e, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x0d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x4a, + 0x04, 0x08, 0x01, 0x10, 0x02, 0x22, 0x36, 0x0a, 0x18, 0x55, 0x6e, 0x64, 0x6f, 0x44, 0x65, 0x6d, + 0x6f, 0x74, 0x65, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x6d, 0x69, 0x53, 0x79, 0x6e, 0x63, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x08, 0x73, 0x65, 0x6d, 0x69, 0x53, 0x79, 0x6e, 0x63, 0x22, 0x1b, 0x0a, + 0x19, 0x55, 0x6e, 0x64, 0x6f, 0x44, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x72, 0x69, 0x6d, 0x61, + 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x0a, 0x19, 0x52, 0x65, + 0x70, 0x6c, 0x69, 0x63, 0x61, 0x57, 0x61, 0x73, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x64, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x1c, 0x0a, 0x1a, 0x52, 0x65, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x57, 0x61, 0x73, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x0a, 0x21, 0x52, 0x65, 0x73, 0x65, 0x74, 0x52, 0x65, + 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, + 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x24, 0x0a, 0x22, 0x52, 0x65, + 0x73, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, + 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x13, 0x0a, 0x11, 0x46, 0x75, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x49, 0x0a, 0x12, 0x46, 0x75, 0x6c, 0x6c, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x65, + 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x46, 0x75, + 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x22, 0x9c, 0x02, 0x0a, 0x1b, 0x53, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x2d, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x15, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, + 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, + 0x26, 0x0a, 0x0f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, + 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x74, 0x69, 0x6d, 0x65, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x64, 0x4e, 0x73, 0x12, 0x36, 0x0a, 0x17, 0x66, 0x6f, 0x72, 0x63, 0x65, + 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x53, + 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x23, 0x0a, 0x0d, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x77, 0x61, 0x69, 0x74, 0x50, 0x6f, 0x73, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x6d, 0x69, 0x53, 0x79, 0x6e, 0x63, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x73, 0x65, 0x6d, 0x69, 0x53, 0x79, 0x6e, 0x63, + 0x12, 0x2d, 0x0a, 0x12, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x5f, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x11, 0x68, 0x65, + 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x22, + 0x1e, 0x0a, 0x1c, 0x53, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x4b, 0x0a, 0x1a, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x57, 0x61, 0x73, 0x52, 0x65, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, + 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, + 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, + 0x6c, 0x69, 0x61, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x22, 0x1d, 0x0a, 0x1b, + 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x57, 0x61, 0x73, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x7e, 0x0a, 0x22, 0x53, + 0x74, 0x6f, 0x70, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, + 0x64, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x58, 0x0a, 0x15, 0x73, 0x74, 0x6f, 0x70, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x24, 0x2e, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x64, 0x61, + 0x74, 0x61, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x13, 0x73, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x70, 0x6c, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0x6b, 0x0a, 0x23, 0x53, + 0x74, 0x6f, 0x70, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, + 0x64, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x22, 0x33, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x6d, + 0x6f, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x6d, 0x69, 0x53, 0x79, 0x6e, 0x63, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x08, 0x73, 0x65, 0x6d, 0x69, 0x53, 0x79, 0x6e, 0x63, 0x22, 0x34, 0x0a, + 0x16, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x22, 0xaf, 0x02, 0x0a, 0x0d, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, + 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, + 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, + 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x30, 0x0a, 0x14, + 0x69, 0x6e, 0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x5f, 0x66, 0x72, 0x6f, 0x6d, + 0x5f, 0x70, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x69, 0x6e, 0x63, 0x72, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x6f, 0x73, 0x12, 0x21, + 0x0a, 0x0c, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x5f, 0x73, 0x61, 0x66, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x53, 0x61, 0x66, + 0x65, 0x12, 0x28, 0x0a, 0x0d, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x65, 0x6e, 0x67, 0x69, + 0x6e, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x62, 0x61, 0x63, 0x6b, + 0x75, 0x70, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x88, 0x01, 0x01, 0x12, 0x46, 0x0a, 0x16, 0x6d, + 0x79, 0x73, 0x71, 0x6c, 0x5f, 0x73, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, + 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x14, 0x6d, + 0x79, 0x73, 0x71, 0x6c, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x54, 0x69, 0x6d, 0x65, + 0x6f, 0x75, 0x74, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x65, + 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x22, 0x36, 0x0a, 0x0e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6c, 0x6f, 0x67, 0x75, 0x74, 0x69, 0x6c, + 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0xfe, 0x01, + 0x0a, 0x18, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x42, 0x61, 0x63, + 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x0b, 0x62, 0x61, + 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0c, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x0a, 0x62, + 0x61, 0x63, 0x6b, 0x75, 0x70, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x65, 0x73, + 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x70, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x54, 0x6f, 0x50, 0x6f, 0x73, 0x12, + 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x12, 0x3e, 0x0a, 0x14, 0x72, 0x65, 0x73, 0x74, + 0x6f, 0x72, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x52, 0x12, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x54, 0x6f, 0x54, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x34, 0x0a, 0x16, 0x61, 0x6c, 0x6c, 0x6f, + 0x77, 0x65, 0x64, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x65, 0x6e, 0x67, 0x69, 0x6e, + 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x14, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, + 0x64, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x41, + 0x0a, 0x19, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x42, 0x61, 0x63, + 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x05, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6c, 0x6f, 0x67, + 0x75, 0x74, 0x69, 0x6c, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x22, 0xee, 0x04, 0x0a, 0x21, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x52, 0x65, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, + 0x6c, 0x6f, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, + 0x6c, 0x6f, 0x77, 0x12, 0x3d, 0x0a, 0x0d, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x5f, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x62, 0x69, 0x6e, + 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x42, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x53, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x52, 0x0c, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x53, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x12, 0x37, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, + 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x14, + 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, + 0x73, 0x12, 0x6c, 0x0a, 0x1b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, + 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, + 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x52, 0x19, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x53, 0x65, 0x6c, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, + 0x49, 0x0a, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, + 0x61, 0x74, 0x61, 0x2e, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x77, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x79, 0x70, 0x65, 0x12, 0x53, 0x0a, 0x11, 0x77, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x73, 0x75, 0x62, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, + 0x74, 0x61, 0x2e, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x75, 0x62, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0f, + 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x75, 0x62, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x30, 0x0a, 0x14, 0x64, 0x65, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, + 0x72, 0x79, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x64, + 0x65, 0x66, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x4b, 0x65, 0x79, + 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x75, 0x74, 0x6f, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x5f, 0x63, + 0x6f, 0x70, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x73, 0x74, 0x6f, 0x70, 0x41, + 0x66, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x70, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x22, 0x50, 0x0a, 0x22, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x52, 0x65, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x22, 0xda, 0x01, 0x0a, 0x16, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, + 0x61, 0x62, 0x6c, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x60, 0x0a, 0x0d, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, + 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, + 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x62, 0x61, 0x74, 0x63, 0x68, 0x53, 0x69, 0x7a, 0x65, + 0x1a, 0x3f, 0x0a, 0x11, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x22, 0x19, 0x0a, 0x17, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, + 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3f, 0x0a, 0x21, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x3d, 0x0a, - 0x0d, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x42, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0c, - 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, - 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, 0x6c, - 0x6c, 0x73, 0x12, 0x37, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x6c, 0x0a, 0x1b, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x2c, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, - 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x19, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, - 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x49, 0x0a, 0x0d, 0x77, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x24, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x52, - 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, - 0x6f, 0x77, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x53, 0x0a, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, - 0x5f, 0x73, 0x75, 0x62, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x27, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x52, 0x65, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, - 0x77, 0x53, 0x75, 0x62, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, - 0x6f, 0x77, 0x53, 0x75, 0x62, 0x54, 0x79, 0x70, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x64, 0x65, 0x66, - 0x65, 0x72, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x5f, 0x6b, 0x65, 0x79, - 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x64, 0x65, 0x66, 0x65, 0x72, 0x53, 0x65, - 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x61, - 0x75, 0x74, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x09, 0x61, 0x75, 0x74, 0x6f, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x74, - 0x6f, 0x70, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0d, 0x73, 0x74, 0x6f, 0x70, 0x41, 0x66, 0x74, 0x65, 0x72, 0x43, 0x6f, - 0x70, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0b, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x50, 0x0a, 0x22, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0xda, - 0x01, 0x0a, 0x16, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x61, - 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x60, 0x0a, 0x0d, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x3b, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, - 0x64, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, - 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x61, 0x62, 0x6c, - 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x62, - 0x61, 0x74, 0x63, 0x68, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x09, 0x62, 0x61, 0x74, 0x63, 0x68, 0x53, 0x69, 0x7a, 0x65, 0x1a, 0x3f, 0x0a, 0x11, 0x54, 0x61, - 0x62, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x19, 0x0a, 0x17, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3f, 0x0a, 0x21, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x77, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x22, 0x50, 0x0a, 0x22, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, - 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x21, 0x0a, 0x1f, 0x48, 0x61, 0x73, - 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x34, 0x0a, 0x20, - 0x48, 0x61, 0x73, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x10, 0x0a, 0x03, 0x68, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x68, - 0x61, 0x73, 0x22, 0xe0, 0x02, 0x0a, 0x20, 0x52, 0x65, 0x61, 0x64, 0x56, 0x52, 0x65, 0x70, 0x6c, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x63, 0x6c, 0x75, - 0x64, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x52, 0x0a, 0x69, 0x6e, - 0x63, 0x6c, 0x75, 0x64, 0x65, 0x49, 0x64, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x69, 0x6e, 0x63, 0x6c, - 0x75, 0x64, 0x65, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x10, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x57, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x12, 0x4c, 0x0a, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, - 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x25, 0x2e, - 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x52, 0x65, 0x70, 0x6c, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x77, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, - 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, - 0x12, 0x4c, 0x0a, 0x0e, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, - 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, - 0x0d, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x12, 0x25, - 0x0a, 0x0e, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x66, 0x72, 0x6f, 0x7a, 0x65, 0x6e, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x46, - 0x72, 0x6f, 0x7a, 0x65, 0x6e, 0x22, 0x76, 0x0a, 0x21, 0x52, 0x65, 0x61, 0x64, 0x56, 0x52, 0x65, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, - 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x09, 0x77, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x22, 0x3d, 0x0a, - 0x1f, 0x52, 0x65, 0x61, 0x64, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x1a, 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x22, 0xe7, 0x0a, 0x0a, - 0x20, 0x52, 0x65, 0x61, 0x64, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x14, 0x0a, - 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, - 0x6c, 0x6c, 0x73, 0x12, 0x37, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x74, 0x6f, 0x70, 0x6f, - 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, - 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x6c, 0x0a, 0x1b, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x2c, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, - 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x53, 0x65, 0x6c, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, - 0x19, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x62, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x62, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x49, 0x0a, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x66, - 0x6c, 0x6f, 0x77, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x22, 0x50, 0x0a, + 0x22, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, + 0x21, 0x0a, 0x1f, 0x48, 0x61, 0x73, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x22, 0x34, 0x0a, 0x20, 0x48, 0x61, 0x73, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x68, 0x61, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x03, 0x68, 0x61, 0x73, 0x22, 0xe0, 0x02, 0x0a, 0x20, 0x52, 0x65, 0x61, + 0x64, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, + 0x0b, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x05, 0x52, 0x0a, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x49, 0x64, 0x73, 0x12, 0x2b, + 0x0a, 0x11, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x6f, 0x77, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x69, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x12, 0x4c, 0x0a, 0x0e, 0x69, + 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, + 0x2e, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x69, 0x6e, 0x63, 0x6c, + 0x75, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x65, 0x78, 0x63, + 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x18, 0x04, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x57, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x12, 0x4c, 0x0a, 0x0e, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, + 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, - 0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x53, 0x0a, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x73, - 0x75, 0x62, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, - 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x52, 0x65, 0x70, 0x6c, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, - 0x75, 0x62, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, - 0x53, 0x75, 0x62, 0x54, 0x79, 0x70, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x64, 0x65, 0x66, 0x65, 0x72, - 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, - 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x64, 0x65, 0x66, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, - 0x6e, 0x64, 0x61, 0x72, 0x79, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x54, 0x0a, 0x07, 0x73, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x52, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, + 0x66, 0x72, 0x6f, 0x7a, 0x65, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x65, 0x78, + 0x63, 0x6c, 0x75, 0x64, 0x65, 0x46, 0x72, 0x6f, 0x7a, 0x65, 0x6e, 0x22, 0x76, 0x0a, 0x21, 0x52, 0x65, 0x61, 0x64, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, - 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x07, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x12, - 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x73, 0x0a, 0x10, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x18, 0x0d, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x48, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x51, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x1a, 0xc1, - 0x04, 0x0a, 0x06, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2a, 0x0a, 0x03, 0x62, 0x6c, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x42, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x52, 0x03, 0x62, 0x6c, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x70, 0x6f, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x74, 0x6f, 0x70, 0x5f, - 0x70, 0x6f, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x74, 0x6f, 0x70, 0x50, - 0x6f, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x6d, 0x61, 0x78, 0x5f, 0x74, 0x70, 0x73, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x06, 0x6d, 0x61, 0x78, 0x54, 0x70, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x6d, - 0x61, 0x78, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, - 0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x6d, 0x61, 0x78, 0x52, 0x65, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x61, 0x67, 0x12, 0x2f, 0x0a, 0x0c, 0x74, - 0x69, 0x6d, 0x65, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x6f, 0x77, 0x73, 0x22, 0x3d, 0x0a, 0x1f, 0x52, 0x65, 0x61, 0x64, 0x56, 0x52, 0x65, 0x70, 0x6c, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x6f, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x6f, 0x77, 0x22, 0xe7, 0x0a, 0x0a, 0x20, 0x52, 0x65, 0x61, 0x64, 0x56, 0x52, 0x65, 0x70, 0x6c, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, + 0x6c, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, + 0x6c, 0x6f, 0x77, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x12, 0x37, 0x0a, 0x0c, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0e, 0x32, + 0x14, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x73, 0x12, 0x6c, 0x0a, 0x1b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x73, 0x65, 0x6c, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, + 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, + 0x65, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x66, 0x65, + 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x19, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x53, 0x65, 0x6c, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, + 0x12, 0x17, 0x0a, 0x07, 0x64, 0x62, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x64, 0x62, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, + 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x49, 0x0a, + 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, + 0x61, 0x2e, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x77, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x79, 0x70, 0x65, 0x12, 0x53, 0x0a, 0x11, 0x77, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x73, 0x75, 0x62, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x09, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, + 0x2e, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x75, 0x62, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0f, 0x77, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x75, 0x62, 0x54, 0x79, 0x70, 0x65, 0x12, 0x30, 0x0a, + 0x14, 0x64, 0x65, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, + 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x64, 0x65, 0x66, + 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x4b, 0x65, 0x79, 0x73, 0x12, + 0x54, 0x0a, 0x07, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x3a, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, + 0x64, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x07, 0x73, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x73, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, + 0x64, 0x65, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x48, 0x2e, 0x74, 0x61, 0x62, 0x6c, + 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x65, + 0x61, 0x64, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x73, 0x1a, 0xc1, 0x04, 0x0a, 0x06, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x2a, 0x0a, 0x03, 0x62, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x62, + 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x42, 0x69, 0x6e, 0x6c, 0x6f, 0x67, + 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x03, 0x62, 0x6c, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x70, + 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x6f, 0x73, 0x12, 0x19, 0x0a, + 0x08, 0x73, 0x74, 0x6f, 0x70, 0x5f, 0x70, 0x6f, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x73, 0x74, 0x6f, 0x70, 0x50, 0x6f, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x6d, 0x61, 0x78, 0x5f, + 0x74, 0x70, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6d, 0x61, 0x78, 0x54, 0x70, + 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, + 0x6d, 0x61, 0x78, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x61, + 0x67, 0x12, 0x2f, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x64, 0x12, 0x41, 0x0a, 0x15, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x52, - 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x41, 0x0a, 0x15, - 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x76, 0x74, - 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x14, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, - 0x3b, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, - 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x52, 0x65, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x6f, 0x77, 0x73, 0x5f, 0x63, - 0x6f, 0x70, 0x69, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x6f, 0x77, - 0x73, 0x43, 0x6f, 0x70, 0x69, 0x65, 0x64, 0x12, 0x33, 0x0a, 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x5f, - 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0c, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x0d, 0x74, - 0x69, 0x6d, 0x65, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x12, 0x33, 0x0a, 0x0e, - 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x18, 0x0d, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x52, 0x0d, 0x74, 0x69, 0x6d, 0x65, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, - 0x64, 0x12, 0x2f, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x74, - 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, - 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, - 0x65, 0x64, 0x1a, 0x42, 0x0a, 0x14, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x28, 0x0a, 0x26, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x14, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3b, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, + 0x61, 0x2e, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1f, 0x0a, 0x0b, + 0x72, 0x6f, 0x77, 0x73, 0x5f, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0a, 0x72, 0x6f, 0x77, 0x73, 0x43, 0x6f, 0x70, 0x69, 0x65, 0x64, 0x12, 0x33, 0x0a, + 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x18, + 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x54, + 0x69, 0x6d, 0x65, 0x52, 0x0d, 0x74, 0x69, 0x6d, 0x65, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, + 0x61, 0x74, 0x12, 0x33, 0x0a, 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x68, 0x72, 0x6f, 0x74, + 0x74, 0x6c, 0x65, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x76, 0x74, 0x74, + 0x69, 0x6d, 0x65, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x0d, 0x74, 0x69, 0x6d, 0x65, 0x54, 0x68, + 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x12, 0x2f, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x70, 0x6f, + 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x18, 0x0e, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x54, + 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x1a, 0x42, 0x0a, 0x14, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x28, 0x0a, 0x26, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x4d, 0x0a, 0x27, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, - 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x22, 0x4d, 0x0a, 0x27, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x56, 0x52, 0x65, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, - 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, - 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x6f, 0x6b, 0x22, - 0xd7, 0x01, 0x0a, 0x0c, 0x56, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x1a, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, - 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x72, 0x67, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x67, 0x12, - 0x1d, 0x0a, 0x0a, 0x76, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x76, 0x64, 0x69, 0x66, 0x66, 0x55, 0x75, 0x69, 0x64, 0x12, 0x39, - 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1f, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x56, 0x44, 0x69, 0x66, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x6a, 0x0a, 0x0d, 0x56, 0x44, 0x69, - 0x66, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2a, 0x0a, 0x06, 0x6f, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x71, 0x75, 0x65, - 0x72, 0x79, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, - 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x76, 0x64, 0x69, 0x66, 0x66, 0x5f, - 0x75, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x76, 0x64, 0x69, 0x66, - 0x66, 0x55, 0x75, 0x69, 0x64, 0x22, 0x79, 0x0a, 0x12, 0x56, 0x44, 0x69, 0x66, 0x66, 0x50, 0x69, - 0x63, 0x6b, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x1f, - 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x65, 0x6c, 0x6c, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x12, - 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x63, 0x65, 0x6c, 0x6c, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x65, 0x6c, 0x6c, - 0x22, 0xce, 0x01, 0x0a, 0x12, 0x56, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x6e, 0x6c, 0x79, 0x5f, - 0x70, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x6f, 0x6e, 0x6c, 0x79, 0x50, - 0x6b, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x71, 0x75, 0x65, 0x72, - 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x64, 0x65, 0x62, 0x75, 0x67, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x6d, - 0x61, 0x78, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x72, 0x6f, 0x77, 0x73, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, - 0x6f, 0x77, 0x73, 0x12, 0x3c, 0x0a, 0x1b, 0x72, 0x6f, 0x77, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x5f, - 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x5f, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x5f, - 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x72, 0x6f, 0x77, 0x44, 0x69, 0x66, - 0x66, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x54, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x41, - 0x74, 0x22, 0x8d, 0x03, 0x0a, 0x10, 0x56, 0x44, 0x69, 0x66, 0x66, 0x43, 0x6f, 0x72, 0x65, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x1d, - 0x0a, 0x0a, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x09, 0x61, 0x75, 0x74, 0x6f, 0x52, 0x65, 0x74, 0x72, 0x79, 0x12, 0x19, 0x0a, - 0x08, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x6f, 0x77, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x07, 0x6d, 0x61, 0x78, 0x52, 0x6f, 0x77, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x65, 0x63, - 0x6b, 0x73, 0x75, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x63, 0x68, 0x65, 0x63, - 0x6b, 0x73, 0x75, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x70, - 0x63, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, - 0x50, 0x63, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x73, - 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x74, 0x69, - 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x38, 0x0a, 0x19, - 0x6d, 0x61, 0x78, 0x5f, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x72, 0x6f, 0x77, 0x73, 0x5f, 0x74, - 0x6f, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x15, 0x6d, 0x61, 0x78, 0x45, 0x78, 0x74, 0x72, 0x61, 0x52, 0x6f, 0x77, 0x73, 0x54, 0x6f, 0x43, - 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x10, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x53, - 0x74, 0x61, 0x74, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, 0x64, 0x69, 0x66, 0x66, - 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, - 0x6d, 0x61, 0x78, 0x44, 0x69, 0x66, 0x66, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x22, - 0x0a, 0x0a, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x08, 0x48, 0x00, 0x52, 0x09, 0x61, 0x75, 0x74, 0x6f, 0x53, 0x74, 0x61, 0x72, 0x74, 0x88, - 0x01, 0x01, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x72, - 0x74, 0x22, 0xf2, 0x01, 0x0a, 0x0c, 0x56, 0x44, 0x69, 0x66, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x4c, 0x0a, 0x0e, 0x70, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x5f, 0x6f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, + 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x02, 0x6f, 0x6b, 0x22, 0xd7, 0x01, 0x0a, 0x0c, 0x56, 0x44, 0x69, 0x66, 0x66, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x16, + 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x61, 0x72, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x41, 0x72, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x76, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x75, + 0x75, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x76, 0x64, 0x69, 0x66, 0x66, + 0x55, 0x75, 0x69, 0x64, 0x12, 0x39, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, + 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x44, 0x69, 0x66, 0x66, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, + 0x6a, 0x0a, 0x0d, 0x56, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, + 0x12, 0x2a, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x1d, 0x0a, 0x0a, + 0x76, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x76, 0x64, 0x69, 0x66, 0x66, 0x55, 0x75, 0x69, 0x64, 0x22, 0x79, 0x0a, 0x12, 0x56, 0x44, 0x69, 0x66, 0x66, 0x50, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x52, 0x0d, 0x70, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x46, 0x0a, 0x0c, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, - 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x44, 0x69, 0x66, 0x66, - 0x43, 0x6f, 0x72, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0b, 0x63, 0x6f, 0x72, - 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4c, 0x0a, 0x0e, 0x72, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x54, + 0x79, 0x70, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, + 0x65, 0x6c, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, + 0x63, 0x65, 0x6c, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x43, 0x65, 0x6c, 0x6c, 0x22, 0xce, 0x01, 0x0a, 0x12, 0x56, 0x44, 0x69, 0x66, 0x66, + 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x19, 0x0a, + 0x08, 0x6f, 0x6e, 0x6c, 0x79, 0x5f, 0x70, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x07, 0x6f, 0x6e, 0x6c, 0x79, 0x50, 0x6b, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x62, 0x75, + 0x67, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x64, + 0x65, 0x62, 0x75, 0x67, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x72, + 0x6d, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, + 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, + 0x72, 0x6f, 0x77, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x53, + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x6f, 0x77, 0x73, 0x12, 0x3c, 0x0a, 0x1b, 0x72, 0x6f, 0x77, + 0x5f, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x5f, 0x74, 0x72, 0x75, + 0x6e, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, + 0x72, 0x6f, 0x77, 0x44, 0x69, 0x66, 0x66, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x54, 0x72, 0x75, + 0x6e, 0x63, 0x61, 0x74, 0x65, 0x41, 0x74, 0x22, 0x8d, 0x03, 0x0a, 0x10, 0x56, 0x44, 0x69, 0x66, + 0x66, 0x43, 0x6f, 0x72, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x16, 0x0a, 0x06, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x74, + 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x75, 0x74, 0x6f, 0x52, 0x65, + 0x74, 0x72, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x6f, 0x77, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x52, 0x6f, 0x77, 0x73, 0x12, 0x1a, + 0x0a, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x70, 0x63, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, + 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x50, 0x63, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x69, 0x6d, + 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, + 0x64, 0x73, 0x12, 0x38, 0x0a, 0x19, 0x6d, 0x61, 0x78, 0x5f, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, + 0x72, 0x6f, 0x77, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x6d, 0x61, 0x78, 0x45, 0x78, 0x74, 0x72, 0x61, 0x52, + 0x6f, 0x77, 0x73, 0x54, 0x6f, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x12, 0x2c, 0x0a, 0x12, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x74, 0x61, + 0x74, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x54, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x61, + 0x78, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x44, 0x69, 0x66, 0x66, 0x53, 0x65, 0x63, + 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x22, 0x0a, 0x0a, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x09, 0x61, 0x75, 0x74, 0x6f, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x88, 0x01, 0x01, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x61, 0x75, 0x74, + 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x22, 0xf2, 0x01, 0x0a, 0x0c, 0x56, 0x44, 0x69, 0x66, + 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4c, 0x0a, 0x0e, 0x70, 0x69, 0x63, 0x6b, + 0x65, 0x72, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, - 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0d, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x7a, 0x0a, 0x10, 0x56, 0x44, 0x69, 0x66, 0x66, 0x54, - 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x61, 0x73, 0x74, 0x50, 0x4b, 0x12, 0x2a, 0x0a, 0x06, 0x74, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x71, 0x75, 0x65, - 0x72, 0x79, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x2f, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x48, 0x00, 0x52, 0x06, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x22, 0xaa, 0x05, 0x0a, 0x21, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x52, 0x65, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, - 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x12, 0x37, 0x0a, 0x0c, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0e, - 0x32, 0x14, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, - 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x54, 0x79, - 0x70, 0x65, 0x73, 0x12, 0x71, 0x0a, 0x1b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x73, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, - 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, - 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, - 0x6c, 0x65, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x66, - 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x48, 0x00, 0x52, 0x19, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, - 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, - 0x6e, 0x63, 0x65, 0x88, 0x01, 0x01, 0x12, 0x33, 0x0a, 0x06, 0x6f, 0x6e, 0x5f, 0x64, 0x64, 0x6c, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x4f, 0x6e, 0x44, 0x44, 0x4c, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, - 0x01, 0x52, 0x05, 0x6f, 0x6e, 0x44, 0x64, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x40, 0x0a, 0x05, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x62, 0x69, 0x6e, - 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x48, 0x02, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x88, 0x01, 0x01, 0x12, 0x16, 0x0a, - 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, - 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x74, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, - 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x49, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x07, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x07, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x1a, 0x42, 0x0a, 0x14, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x1e, - 0x0a, 0x1c, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x09, - 0x0a, 0x07, 0x5f, 0x6f, 0x6e, 0x5f, 0x64, 0x64, 0x6c, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, - 0x50, 0x0a, 0x22, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x22, 0xd6, 0x02, 0x0a, 0x22, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x52, 0x65, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x5f, - 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0c, 0x61, 0x6c, 0x6c, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x12, 0x2b, 0x0a, - 0x11, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, - 0x77, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, - 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x65, 0x78, - 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x18, - 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x57, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x12, 0x40, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, 0x48, 0x00, 0x52, - 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x07, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x28, 0x0a, 0x0d, 0x73, 0x74, 0x6f, 0x70, - 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, - 0x02, 0x52, 0x0c, 0x73, 0x74, 0x6f, 0x70, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x88, - 0x01, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x0a, 0x0a, 0x08, - 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x73, 0x74, 0x6f, - 0x70, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x51, 0x0a, 0x23, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x2f, 0x0a, - 0x15, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x22, 0x18, - 0x0a, 0x16, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc6, 0x01, 0x0a, 0x15, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, - 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x63, - 0x6f, 0x70, 0x65, 0x12, 0x36, 0x0a, 0x17, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x72, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x73, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x73, 0x6b, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x10, 0x6f, - 0x6b, 0x5f, 0x69, 0x66, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x6f, 0x6b, 0x49, 0x66, 0x4e, 0x6f, 0x74, 0x45, 0x78, - 0x69, 0x73, 0x74, 0x73, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x52, 0x15, 0x6d, 0x75, 0x6c, 0x74, - 0x69, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x64, 0x22, 0xf6, 0x05, 0x0a, 0x16, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x68, 0x72, 0x6f, 0x74, - 0x74, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, - 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x5f, 0x63, 0x68, 0x65, - 0x63, 0x6b, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x72, 0x65, 0x63, 0x65, - 0x6e, 0x74, 0x6c, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x50, 0x0a, 0x07, 0x6d, - 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x74, + 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x44, 0x69, 0x66, 0x66, 0x50, 0x69, 0x63, 0x6b, 0x65, 0x72, + 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0d, 0x70, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x46, 0x0a, 0x0c, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x6f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, + 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, + 0x2e, 0x56, 0x44, 0x69, 0x66, 0x66, 0x43, 0x6f, 0x72, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x52, 0x0b, 0x63, 0x6f, 0x72, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4c, + 0x0a, 0x0e, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, + 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x44, 0x69, 0x66, 0x66, + 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0d, 0x72, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x7a, 0x0a, 0x10, + 0x56, 0x44, 0x69, 0x66, 0x66, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x61, 0x73, 0x74, 0x50, 0x4b, + 0x12, 0x2a, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x2f, 0x0a, 0x06, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x71, + 0x75, 0x65, 0x72, 0x79, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x48, 0x00, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, + 0x07, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0xaa, 0x05, 0x0a, 0x21, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, + 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x65, + 0x6c, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, + 0x12, 0x37, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, + 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x71, 0x0a, 0x1b, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, + 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, + 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, + 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x48, 0x00, 0x52, 0x19, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, + 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x88, 0x01, 0x01, 0x12, 0x33, 0x0a, 0x06, + 0x6f, 0x6e, 0x5f, 0x64, 0x64, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x62, + 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4f, 0x6e, 0x44, 0x44, 0x4c, 0x41, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x01, 0x52, 0x05, 0x6f, 0x6e, 0x44, 0x64, 0x6c, 0x88, 0x01, + 0x01, 0x12, 0x40, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x25, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x52, + 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, 0x48, 0x02, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x88, 0x01, 0x01, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, 0x07, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x74, 0x0a, 0x10, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x18, + 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, + 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, + 0x73, 0x12, 0x1d, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x03, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, + 0x1a, 0x42, 0x0a, 0x14, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, + 0x64, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x42, 0x1e, 0x0a, 0x1c, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, + 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x6f, 0x6e, 0x5f, 0x64, 0x64, 0x6c, 0x42, + 0x08, 0x0a, 0x06, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x50, 0x0a, 0x22, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, + 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, + 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x72, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, + 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0xd6, 0x02, 0x0a, 0x22, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, + 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x61, 0x6c, 0x6c, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x6f, 0x77, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x77, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, + 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, + 0x12, 0x2b, 0x0a, 0x11, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x77, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x65, 0x78, 0x63, + 0x6c, 0x75, 0x64, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x12, 0x40, 0x0a, + 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x62, + 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x48, 0x00, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x88, 0x01, 0x01, 0x12, + 0x1d, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x48, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x28, + 0x0a, 0x0d, 0x73, 0x74, 0x6f, 0x70, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x0c, 0x73, 0x74, 0x6f, 0x70, 0x50, 0x6f, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x10, + 0x0a, 0x0e, 0x5f, 0x73, 0x74, 0x6f, 0x70, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x51, 0x0a, 0x23, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x52, 0x65, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x22, 0x2f, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x65, 0x71, 0x75, + 0x65, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x73, 0x22, 0x18, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x65, 0x71, + 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc6, + 0x01, 0x0a, 0x15, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, + 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x36, 0x0a, 0x17, 0x73, 0x6b, 0x69, + 0x70, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, + 0x65, 0x61, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x73, 0x6b, 0x69, 0x70, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, + 0x73, 0x12, 0x27, 0x0a, 0x10, 0x6f, 0x6b, 0x5f, 0x69, 0x66, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x65, + 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x6f, 0x6b, 0x49, + 0x66, 0x4e, 0x6f, 0x74, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, + 0x52, 0x15, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, + 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0xf6, 0x05, 0x0a, 0x16, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x68, 0x72, 0x65, + 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x74, 0x68, 0x72, + 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x63, 0x65, 0x6e, 0x74, + 0x6c, 0x79, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0f, 0x72, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x65, + 0x64, 0x12, 0x50, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x07, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, + 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x68, 0x72, 0x6f, + 0x74, 0x74, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, + 0x74, 0x72, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, + 0x69, 0x63, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x52, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x2d, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, + 0x61, 0x74, 0x61, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, + 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x0c, + 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x1a, 0xf0, 0x01, 0x0a, + 0x06, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, + 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, + 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x73, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x19, 0x0a, - 0x08, 0x61, 0x70, 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, - 0x61, 0x72, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, - 0x72, 0x79, 0x12, 0x52, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x63, - 0x6f, 0x64, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x74, 0x61, 0x62, 0x6c, - 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x1a, 0xf0, 0x01, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x72, 0x69, - 0x63, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, - 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, - 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, - 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, - 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x12, - 0x52, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, - 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, - 0x6f, 0x64, 0x65, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x1a, 0x6c, 0x0a, 0x0c, 0x4d, 0x65, 0x74, - 0x72, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x46, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x52, 0x0b, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x22, 0x1b, 0x0a, 0x19, 0x47, 0x65, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x0c, 0x72, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x1a, + 0x6c, 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x46, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x30, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, + 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, + 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x72, + 0x69, 0x63, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04, 0x08, + 0x01, 0x10, 0x02, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x63, 0x6f, 0x64, 0x65, + 0x22, 0x1b, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x9b, 0x10, + 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x0c, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, + 0x1a, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, + 0x68, 0x61, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, + 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x73, 0x5f, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x17, + 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x06, 0x69, 0x73, 0x4f, 0x70, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x65, 0x6e, + 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x45, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x64, 0x6f, 0x72, + 0x6d, 0x61, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x44, 0x6f, + 0x72, 0x6d, 0x61, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x65, 0x74, + 0x72, 0x69, 0x63, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0e, 0x6c, 0x61, 0x67, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, + 0x2e, 0x0a, 0x13, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, + 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x63, 0x75, + 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, + 0x2b, 0x0a, 0x11, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, + 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x01, 0x52, 0x10, 0x64, 0x65, 0x66, 0x61, + 0x75, 0x6c, 0x74, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x3c, 0x0a, 0x1b, + 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x64, + 0x5f, 0x61, 0x73, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x17, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x55, 0x73, 0x65, + 0x64, 0x41, 0x73, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x73, 0x0a, 0x12, 0x61, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, + 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, + 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x68, + 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, + 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x61, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, + 0x70, 0x0a, 0x11, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, + 0x6f, 0x6c, 0x64, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, + 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, + 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x10, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, + 0x73, 0x12, 0x67, 0x0a, 0x0e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x68, 0x65, 0x61, + 0x6c, 0x74, 0x68, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x74, 0x61, 0x62, 0x6c, + 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x9b, 0x10, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x54, - 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, - 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6b, 0x65, 0x79, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6b, 0x65, 0x79, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x69, - 0x73, 0x5f, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, - 0x69, 0x73, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x6f, - 0x70, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x73, 0x4f, 0x70, 0x65, - 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, - 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x64, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x74, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x44, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x74, 0x12, - 0x28, 0x0a, 0x10, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x71, 0x75, - 0x65, 0x72, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6c, 0x61, 0x67, 0x4d, 0x65, - 0x74, 0x72, 0x69, 0x63, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x75, 0x73, - 0x74, 0x6f, 0x6d, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, - 0x74, 0x72, 0x69, 0x63, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x64, 0x65, 0x66, - 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x01, 0x52, 0x10, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x54, 0x68, 0x72, - 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x3c, 0x0a, 0x1b, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x61, 0x73, 0x5f, 0x64, 0x65, - 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x6d, 0x65, 0x74, - 0x72, 0x69, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x55, 0x73, 0x65, 0x64, 0x41, 0x73, 0x44, 0x65, 0x66, - 0x61, 0x75, 0x6c, 0x74, 0x12, 0x73, 0x0a, 0x12, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, - 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, + 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x6d, 0x65, 0x74, + 0x72, 0x69, 0x63, 0x73, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x67, 0x0a, 0x0e, 0x74, 0x68, + 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x5f, 0x61, 0x70, 0x70, 0x73, 0x18, 0x0f, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, + 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, + 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x2e, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x41, 0x70, 0x70, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x74, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x41, + 0x70, 0x70, 0x73, 0x12, 0x74, 0x0a, 0x13, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, + 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, - 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, - 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x70, 0x0a, 0x11, 0x6d, 0x65, 0x74, - 0x72, 0x69, 0x63, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x73, 0x18, 0x0d, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, - 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, - 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, - 0x6f, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x10, 0x6d, 0x65, 0x74, 0x72, 0x69, - 0x63, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x73, 0x12, 0x67, 0x0a, 0x0e, 0x6d, - 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x18, 0x0e, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, - 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, - 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x48, 0x65, - 0x61, 0x6c, 0x74, 0x68, 0x12, 0x67, 0x0a, 0x0e, 0x74, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, - 0x64, 0x5f, 0x61, 0x70, 0x70, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x74, + 0x41, 0x70, 0x70, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x61, 0x70, 0x70, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x63, + 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x11, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0f, 0x72, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x65, 0x64, 0x12, 0x5e, 0x0a, 0x0b, 0x72, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x5f, 0x61, + 0x70, 0x70, 0x73, 0x18, 0x12, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x74, 0x61, 0x62, 0x6c, + 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, + 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x41, + 0x70, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x72, 0x65, 0x63, 0x65, 0x6e, 0x74, + 0x41, 0x70, 0x70, 0x73, 0x1a, 0x3a, 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x1a, 0x80, 0x01, 0x0a, 0x16, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, + 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x50, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x68, 0x72, 0x6f, - 0x74, 0x74, 0x6c, 0x65, 0x64, 0x41, 0x70, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, - 0x74, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x41, 0x70, 0x70, 0x73, 0x12, 0x74, 0x0a, - 0x13, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x74, - 0x72, 0x69, 0x63, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, - 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x11, 0x61, 0x70, 0x70, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, - 0x69, 0x63, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x5f, - 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x72, - 0x65, 0x63, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x5e, - 0x0a, 0x0b, 0x72, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x70, 0x70, 0x73, 0x18, 0x12, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, + 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x72, + 0x69, 0x63, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, + 0x02, 0x38, 0x01, 0x1a, 0x43, 0x0a, 0x15, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x68, 0x72, + 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x81, 0x01, 0x0a, 0x0c, 0x4d, 0x65, 0x74, + 0x72, 0x69, 0x63, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x34, 0x0a, 0x0f, 0x6c, 0x61, 0x73, + 0x74, 0x5f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x52, 0x0d, 0x6c, 0x61, 0x73, 0x74, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x41, 0x74, 0x12, + 0x3b, 0x0a, 0x1a, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x5f, 0x73, 0x69, 0x6e, 0x63, 0x65, + 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x17, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x53, 0x69, 0x6e, 0x63, + 0x65, 0x4c, 0x61, 0x73, 0x74, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x1a, 0x7c, 0x0a, 0x12, + 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x50, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2e, 0x52, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x41, 0x70, 0x70, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x0a, 0x72, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x41, 0x70, 0x70, 0x73, 0x1a, 0x3a, - 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x1a, 0x80, 0x01, 0x0a, 0x16, 0x41, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x50, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, - 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x68, - 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x43, 0x0a, - 0x15, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, + 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x5c, 0x0a, 0x12, 0x54, 0x68, + 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x41, 0x70, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x68, 0x72, + 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x41, 0x70, 0x70, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x44, 0x0a, 0x16, 0x41, 0x70, 0x70, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x92, + 0x01, 0x0a, 0x09, 0x52, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x41, 0x70, 0x70, 0x12, 0x2b, 0x0a, 0x0a, + 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0c, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x09, + 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x41, 0x74, 0x12, 0x52, 0x0a, 0x0d, 0x72, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x2d, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, + 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, + 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x52, + 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x4a, 0x04, 0x08, + 0x02, 0x10, 0x03, 0x1a, 0x76, 0x0a, 0x0f, 0x52, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x41, 0x70, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x1a, 0x81, 0x01, 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x48, 0x65, 0x61, - 0x6c, 0x74, 0x68, 0x12, 0x34, 0x0a, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x79, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x76, - 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x0d, 0x6c, 0x61, 0x73, 0x74, - 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x41, 0x74, 0x12, 0x3b, 0x0a, 0x1a, 0x73, 0x65, 0x63, - 0x6f, 0x6e, 0x64, 0x73, 0x5f, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, - 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x73, - 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x53, 0x69, 0x6e, 0x63, 0x65, 0x4c, 0x61, 0x73, 0x74, 0x48, - 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x1a, 0x7c, 0x0a, 0x12, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, - 0x73, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x50, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, - 0x72, 0x69, 0x63, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x5c, 0x0a, 0x12, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, - 0x64, 0x41, 0x70, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x6f, - 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, - 0x41, 0x70, 0x70, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x1a, 0x44, 0x0a, 0x16, 0x41, 0x70, 0x70, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, - 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, + 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, + 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x41, 0x70, 0x70, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xaa, 0x01, 0x0a, 0x11, + 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x42, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x2e, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, + 0x61, 0x74, 0x61, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x1a, + 0x37, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x92, 0x01, 0x0a, 0x09, 0x52, 0x65, 0x63, - 0x65, 0x6e, 0x74, 0x41, 0x70, 0x70, 0x12, 0x2b, 0x0a, 0x0a, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, - 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x76, 0x74, 0x74, - 0x69, 0x6d, 0x65, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x09, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, - 0x64, 0x41, 0x74, 0x12, 0x52, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, - 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x1a, 0x76, 0x0a, - 0x0f, 0x52, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x41, 0x70, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x12, 0x4d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x37, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, - 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, - 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x2e, 0x52, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x41, 0x70, 0x70, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xaa, 0x01, 0x0a, 0x11, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x04, 0x74, - 0x61, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x74, 0x61, 0x62, 0x6c, - 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, - 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, - 0x18, 0x0a, 0x07, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x07, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x1a, 0x37, 0x0a, 0x09, 0x54, 0x61, 0x67, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x22, 0x92, 0x01, 0x0a, 0x12, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x61, 0x67, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x04, 0x74, 0x61, 0x67, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, - 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, - 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x1a, 0x37, - 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x2a, 0x3e, 0x0a, 0x19, 0x54, 0x61, 0x62, 0x6c, 0x65, - 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, - 0x65, 0x6e, 0x63, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4e, 0x59, 0x10, 0x00, 0x12, 0x0b, 0x0a, - 0x07, 0x49, 0x4e, 0x4f, 0x52, 0x44, 0x45, 0x52, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, - 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x03, 0x2a, 0x83, 0x01, 0x0a, 0x1a, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, - 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x4f, 0x4b, 0x10, 0x01, 0x12, 0x16, 0x0a, - 0x12, 0x54, 0x48, 0x52, 0x45, 0x53, 0x48, 0x4f, 0x4c, 0x44, 0x5f, 0x45, 0x58, 0x43, 0x45, 0x45, - 0x44, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x41, 0x50, 0x50, 0x5f, 0x44, 0x45, 0x4e, - 0x49, 0x45, 0x44, 0x10, 0x03, 0x12, 0x12, 0x0a, 0x0e, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, - 0x5f, 0x4d, 0x45, 0x54, 0x52, 0x49, 0x43, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x49, 0x4e, 0x54, - 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x05, 0x42, 0x30, 0x5a, - 0x2e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6f, 0x2f, 0x76, 0x69, 0x74, 0x65, 0x73, - 0x73, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x92, 0x01, 0x0a, 0x12, 0x43, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x43, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, + 0x61, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, + 0x74, 0x61, 0x67, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x2a, 0x3e, 0x0a, + 0x19, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4e, + 0x59, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x4f, 0x52, 0x44, 0x45, 0x52, 0x10, 0x01, + 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x03, 0x2a, 0x83, 0x01, + 0x0a, 0x1a, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x0d, 0x0a, 0x09, + 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x4f, + 0x4b, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x54, 0x48, 0x52, 0x45, 0x53, 0x48, 0x4f, 0x4c, 0x44, + 0x5f, 0x45, 0x58, 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x41, + 0x50, 0x50, 0x5f, 0x44, 0x45, 0x4e, 0x49, 0x45, 0x44, 0x10, 0x03, 0x12, 0x12, 0x0a, 0x0e, 0x55, + 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x4d, 0x45, 0x54, 0x52, 0x49, 0x43, 0x10, 0x04, 0x12, + 0x12, 0x0a, 0x0e, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x45, 0x52, 0x52, 0x4f, + 0x52, 0x10, 0x05, 0x42, 0x30, 0x5a, 0x2e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6f, + 0x2f, 0x76, 0x69, 0x74, 0x65, 0x73, 0x73, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x74, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, + 0x72, 0x64, 0x61, 0x74, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, }) var ( diff --git a/go/vt/proto/tabletmanagerdata/tabletmanagerdata_vtproto.pb.go b/go/vt/proto/tabletmanagerdata/tabletmanagerdata_vtproto.pb.go index 74e3cab9f1e..e6fe78e093d 100644 --- a/go/vt/proto/tabletmanagerdata/tabletmanagerdata_vtproto.pb.go +++ b/go/vt/proto/tabletmanagerdata/tabletmanagerdata_vtproto.pb.go @@ -1715,6 +1715,7 @@ func (m *DemotePrimaryRequest) CloneVT() *DemotePrimaryRequest { return (*DemotePrimaryRequest)(nil) } r := new(DemotePrimaryRequest) + r.Force = m.Force if len(m.unknownFields) > 0 { r.unknownFields = make([]byte, len(m.unknownFields)) copy(r.unknownFields, m.unknownFields) @@ -7029,6 +7030,16 @@ func (m *DemotePrimaryRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.Force { + i-- + if m.Force { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x8 + } return len(dAtA) - i, nil } @@ -11997,6 +12008,9 @@ func (m *DemotePrimaryRequest) SizeVT() (n int) { } var l int _ = l + if m.Force { + n += 2 + } n += len(m.unknownFields) return n } @@ -21793,6 +21807,26 @@ func (m *DemotePrimaryRequest) UnmarshalVT(dAtA []byte) error { return fmt.Errorf("proto: DemotePrimaryRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Force", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Force = bool(v != 0) default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) diff --git a/go/vt/schemadiff/onlineddl.go b/go/vt/schemadiff/onlineddl.go index 06f3384c8fd..4ae66dad401 100644 --- a/go/vt/schemadiff/onlineddl.go +++ b/go/vt/schemadiff/onlineddl.go @@ -671,7 +671,7 @@ func ValidateAndEditAlterTableStatement(originalTableName string, baseUUID strin validateWalk := func(node sqlparser.SQLNode) (kontinue bool, err error) { switch node := node.(type) { case *sqlparser.DropKey: - if node.Type == sqlparser.CheckKeyType || node.Type == sqlparser.ForeignKeyType { + if node.Type == sqlparser.CheckKeyType || node.Type == sqlparser.ForeignKeyType || node.Type == sqlparser.ConstraintType { // drop a check or a foreign key constraint mappedName, ok := constraintMap[node.Name.String()] if !ok { diff --git a/go/vt/schemadiff/onlineddl_test.go b/go/vt/schemadiff/onlineddl_test.go index fb8710f8498..a7e7f4494e8 100644 --- a/go/vt/schemadiff/onlineddl_test.go +++ b/go/vt/schemadiff/onlineddl_test.go @@ -1217,6 +1217,13 @@ func TestValidateAndEditAlterTableStatement(t *testing.T) { }, expect: []string{"alter table t drop foreign key ibfk_1_aaaaaaaaaaaaaa"}, }, + { + alter: "alter table t drop constraint t_ibfk_1", + m: map[string]string{ + "t_ibfk_1": "ibfk_1_aaaaaaaaaaaaaa", + }, + expect: []string{"alter table t drop constraint ibfk_1_aaaaaaaaaaaaaa"}, + }, } env := NewTestEnv() diff --git a/go/vt/schemadiff/schema.go b/go/vt/schemadiff/schema.go index 5b578834089..afa537fe7c0 100644 --- a/go/vt/schemadiff/schema.go +++ b/go/vt/schemadiff/schema.go @@ -133,6 +133,21 @@ func getForeignKeyParentTableNames(createTable *sqlparser.CreateTable) (names [] return names } +func findForeignKeyDefinition(createTable *sqlparser.CreateTable, constraintName string) *sqlparser.ForeignKeyDefinition { + if createTable == nil || createTable.TableSpec == nil { + return nil + } + for _, cs := range createTable.TableSpec.Constraints { + if strings.EqualFold(cs.Name.String(), constraintName) { + if fk, ok := cs.Details.(*sqlparser.ForeignKeyDefinition); ok { + return fk + } + return nil + } + } + return nil +} + // getViewDependentTableNames analyzes a CREATE VIEW definition and extracts all tables/views read by this view func getViewDependentTableNames(createView *sqlparser.CreateView) (names []string) { _ = sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { @@ -1006,21 +1021,21 @@ func (s *Schema) SchemaDiff(other *Schema, hints *DiffHints) (*SchemaDiff, error } return checkChildForeignKeyDefinition(fk, diff) case *sqlparser.DropKey: - if node.Type != sqlparser.ForeignKeyType { + switch node.Type { + case sqlparser.ForeignKeyType, sqlparser.ConstraintType: + // Possibly dropping a foreign key; we need to check if this constraint references another table. + // The DropKey statement itself only _names_ the constraint, but does not have information + // about the parent, columns, etc. So we need to find the constraint in the CreateTable statement. + fk := findForeignKeyDefinition(diff.from.CreateTable, node.Name.String()) + if fk == nil { + return true, nil + } + parentTableName := fk.ReferenceDefinition.ReferencedTable.Name.String() + checkDependencies(diff, []string{parentTableName}) + default: // Not interesting return true, nil } - // Dropping a foreign key; we need to understand which table this foreign key used to reference. - // The DropKey statement itself only _names_ the constraint, but does not have information - // about the parent, columns, etc. So we need to find the constraint in the CreateTable statement. - for _, cs := range diff.from.CreateTable.TableSpec.Constraints { - if strings.EqualFold(cs.Name.String(), node.Name.String()) { - if check, ok := cs.Details.(*sqlparser.ForeignKeyDefinition); ok { - parentTableName := check.ReferenceDefinition.ReferencedTable.Name.String() - checkDependencies(diff, []string{parentTableName}) - } - } - } } return true, nil diff --git a/go/vt/schemadiff/table.go b/go/vt/schemadiff/table.go index eb118555371..5e53178e221 100644 --- a/go/vt/schemadiff/table.go +++ b/go/vt/schemadiff/table.go @@ -2107,7 +2107,7 @@ func sortAlterOptions(diff *AlterTableEntityDiff) { optionOrder := func(opt sqlparser.AlterOption) int { switch opt := opt.(type) { case *sqlparser.DropKey: - if opt.Type == sqlparser.ForeignKeyType { + if opt.Type == sqlparser.ForeignKeyType || opt.Type == sqlparser.ConstraintType { return 1 } return 2 @@ -2267,13 +2267,25 @@ func (c *CreateTableEntity) apply(diff *AlterTableEntityDiff) error { break } } - case sqlparser.ForeignKeyType, sqlparser.CheckKeyType: + case sqlparser.ForeignKeyType, sqlparser.CheckKeyType, sqlparser.ConstraintType: for i, constraint := range c.TableSpec.Constraints { - if strings.EqualFold(constraint.Name.String(), opt.Name.String()) { - found = true - c.TableSpec.Constraints = append(c.TableSpec.Constraints[0:i], c.TableSpec.Constraints[i+1:]...) - break + if !strings.EqualFold(constraint.Name.String(), opt.Name.String()) { + continue + } + switch opt.Type { + case sqlparser.ForeignKeyType: + if _, ok := constraint.Details.(*sqlparser.ForeignKeyDefinition); !ok { + continue + } + case sqlparser.CheckKeyType: + if _, ok := constraint.Details.(*sqlparser.CheckConstraintDefinition); !ok { + continue + } + case sqlparser.ConstraintType: } + found = true + c.TableSpec.Constraints = append(c.TableSpec.Constraints[0:i], c.TableSpec.Constraints[i+1:]...) + break } default: return &UnsupportedApplyOperationError{Statement: sqlparser.CanonicalString(opt)} diff --git a/go/vt/schemadiff/table_test.go b/go/vt/schemadiff/table_test.go index ca907b58ac6..46925fb2068 100644 --- a/go/vt/schemadiff/table_test.go +++ b/go/vt/schemadiff/table_test.go @@ -2954,6 +2954,18 @@ func TestValidate(t *testing.T) { alter: "alter table t drop column e", to: "create table t (id int, dateT datetime, primary key (id), constraint unix_epoch check (dateT < '1970-01-01'))", }, + { + name: "drop check for foreign key constraint", + from: "create table t (id int primary key, i int, constraint f foreign key (i) references parent(id))", + alter: "alter table t drop check f", + expectErr: &ApplyKeyNotFoundError{Table: "t", Key: "f"}, + }, + { + name: "drop foreign key for check constraint", + from: "create table t (id int primary key, i int, constraint chk check (i > 0))", + alter: "alter table t drop foreign key chk", + expectErr: &ApplyKeyNotFoundError{Table: "t", Key: "chk"}, + }, // Foreign keys { name: "existing foreign key, no such column", @@ -3045,6 +3057,12 @@ func TestValidate(t *testing.T) { alter: "alter table t drop key `i`", to: "create table t (id int primary key, i int, key i2 (i), constraint f foreign key (i) references parent(id))", }, + { + name: "drop constraint foreign key", + from: "create table t (id int primary key, i int, key i_idx (i), constraint f foreign key (i) references parent(id))", + alter: "alter table t drop constraint f", + to: "create table t (id int primary key, i int, key i_idx (i))", + }, } hints := DiffHints{} env := NewTestEnv() diff --git a/go/vt/servenv/version.go b/go/vt/servenv/version.go index 6aea4b9c65d..861a7f29285 100644 --- a/go/vt/servenv/version.go +++ b/go/vt/servenv/version.go @@ -1,5 +1,5 @@ /* -Copyright 2025 The Vitess Authors. +Copyright 2026 The Vitess Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -19,4 +19,4 @@ package servenv // DO NOT EDIT // THIS FILE IS AUTO-GENERATED DURING NEW RELEASES BY THE VITESS-RELEASER -const versionName = "22.0.3-SNAPSHOT" +const versionName = "22.0.5-SNAPSHOT" diff --git a/go/vt/sidecardb/schema/vdiff/vdiff.sql b/go/vt/sidecardb/schema/vdiff/vdiff.sql index 862e6e0e9d3..447119dd748 100644 --- a/go/vt/sidecardb/schema/vdiff/vdiff.sql +++ b/go/vt/sidecardb/schema/vdiff/vdiff.sql @@ -30,7 +30,7 @@ CREATE TABLE IF NOT EXISTS vdiff `completed_at` timestamp NULL DEFAULT NULL, `last_error` varbinary(1024) DEFAULT NULL, PRIMARY KEY (`id`), - UNIQUE KEY `uuid_idx` (`vdiff_uuid`), + UNIQUE KEY `uuid_idx` (`vdiff_uuid`, `db_name`), KEY `state` (`state`), KEY `ks_wf_idx` (`keyspace`(64), `workflow`(64)) ) ENGINE = InnoDB CHARSET = utf8mb4 diff --git a/go/vt/sidecardb/sidecardb.go b/go/vt/sidecardb/sidecardb.go index 9cbe0540033..b8d79baa2bd 100644 --- a/go/vt/sidecardb/sidecardb.go +++ b/go/vt/sidecardb/sidecardb.go @@ -21,6 +21,7 @@ import ( "embed" "fmt" "io/fs" + "log/slog" "path/filepath" "regexp" "runtime" @@ -29,6 +30,8 @@ import ( "vitess.io/vitess/go/constants/sidecar" "vitess.io/vitess/go/history" + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/mysql/capabilities" "vitess.io/vitess/go/mysql/collations" "vitess.io/vitess/go/mysql/config" "vitess.io/vitess/go/mysql/sqlerror" @@ -51,6 +54,7 @@ const ( sidecarDBExistsQuery = "select 'true' as 'dbexists' from information_schema.SCHEMATA where SCHEMA_NAME = %a" showCreateTableQuery = "show create table %s.%s" sidecarCollationQuery = "select @@global.collation_server" + sidecarVersionQuery = "select @@version" maxDDLErrorHistoryLength = 100 @@ -202,6 +206,9 @@ type schemaInit struct { exec Exec dbCreated bool // The first upgrade/create query will also create the sidecar database if required. coll collations.ID + + // serverVersion is the version of the MySQL server. + serverVersion string } // Exec is a callback that has to be passed to Init() to @@ -389,6 +396,65 @@ func (si *schemaInit) getCurrentSchema(tableName string) (string, error) { return currentTableSchema, nil } +// serverVersionString returns the MySQL server version reported by the +// live sidecar connection. +func (si *schemaInit) serverVersionString() string { + if si.serverVersion != "" { + return si.serverVersion + } + + if si.exec == nil { + return si.env.MySQLVersion() + } + + rs, err := si.exec(si.ctx, sidecarVersionQuery, 1, false) + if err != nil { + log.Warningf("Error getting MySQL version during sidecar database initialization %s", slog.Any("error", err)) + return "" + } + + if len(rs.Rows) != 1 || len(rs.Rows[0]) == 0 { + log.Warningf("Invalid results for SidecarDB version query %s %s", slog.String("query", sidecarVersionQuery), slog.Int("rows", len(rs.Rows))) + return "" + } + + si.serverVersion = rs.Rows[0][0].ToString() + if si.serverVersion == "" { + log.Warning("MySQL version query returned empty result during sidecar database initialization") + } + + return si.serverVersion +} + +// alterTableAlgorithmStrategy returns the algorithm strategy to use for +// sidecar table ALTER statements. On MySQL < 8.0.32 we force ALGORITHM=COPY +// to work around a MySQL bug in the INSTANT DDL redo log format (8.0.29-8.0.31) +// that could cause data corruption during crash recovery. On MySQL >= 8.0.32 +// the bug is fixed and we omit the clause, letting MySQL choose the most +// efficient algorithm. +func (si *schemaInit) alterTableAlgorithmStrategy() int { + version := si.serverVersionString() + if version == "" { + return schemadiff.AlterTableAlgorithmStrategyCopy + } + + capableOf := mysql.ServerVersionCapableOf(version) + if capableOf == nil { + return schemadiff.AlterTableAlgorithmStrategyCopy + } + + capable, err := capableOf(capabilities.InstantDDLXtrabackupCapability) + if err != nil { + return schemadiff.AlterTableAlgorithmStrategyCopy + } + + if capable { + return schemadiff.AlterTableAlgorithmStrategyNone + } + + return schemadiff.AlterTableAlgorithmStrategyCopy +} + // findTableSchemaDiff gets the diff which needs to be applied // to the current table schema in order to reach the desired one. // The result will be an empty string if they match. @@ -397,7 +463,7 @@ func (si *schemaInit) getCurrentSchema(tableName string) (string, error) { func (si *schemaInit) findTableSchemaDiff(tableName, current, desired string) (string, error) { hints := &schemadiff.DiffHints{ TableCharsetCollateStrategy: schemadiff.TableCharsetCollateIgnoreEmpty, - AlterTableAlgorithmStrategy: schemadiff.AlterTableAlgorithmStrategyCopy, + AlterTableAlgorithmStrategy: si.alterTableAlgorithmStrategy(), } env := schemadiff.NewEnv(si.env, si.coll) diff, err := schemadiff.DiffCreateTablesQueries(env, current, desired, hints) @@ -514,6 +580,13 @@ func AddSchemaInitQueries(db *fakesqldb.DB, populateTables bool, parser *sqlpars sqlparser.String(sqlparser.NewIdentifierCS(table.name))).Query, result) } + mysqlVersionResult := sqltypes.MakeTestResult(sqltypes.MakeTestFields( + "@@version", + "varchar"), + config.DefaultMySQLVersion, + ) + db.AddQuery(sidecarVersionQuery, mysqlVersionResult) + sqlModeResult := sqltypes.MakeTestResult(sqltypes.MakeTestFields( "sql_mode", "varchar"), @@ -543,6 +616,9 @@ func MatchesInitQuery(query string) bool { if strings.EqualFold(sdbe, query) { return true } + if strings.EqualFold(sidecarVersionQuery, query) { + return true + } for _, q := range sidecar.DBInitQueryPatterns { q = strings.ToLower(q) if strings.Contains(query, q) { diff --git a/go/vt/sidecardb/sidecardb_test.go b/go/vt/sidecardb/sidecardb_test.go index 78210f19150..71c29ea094f 100644 --- a/go/vt/sidecardb/sidecardb_test.go +++ b/go/vt/sidecardb/sidecardb_test.go @@ -215,7 +215,9 @@ func TestValidateSchema(t *testing.T) { } } -// TestAlterTableAlgorithm confirms that we use ALGORITHM=COPY during alter tables +// TestAlterTableAlgorithm confirms that ALTER TABLE statements use +// ALGORITHM=COPY on MySQL < 8.0.32 (to work around a MySQL bug in the +// INSTANT DDL redo log format) and omit the clause on MySQL >= 8.0.32. func TestAlterTableAlgorithm(t *testing.T) { type testCase struct { testName string @@ -227,28 +229,81 @@ func TestAlterTableAlgorithm(t *testing.T) { {"add column", "t1", "create table if not exists _vt.t1(i int)", "create table if not exists _vt.t1(i int, i1 int)"}, {"modify column", "t1", "create table if not exists _vt.t1(i int)", "create table if not exists _vt.t(i float)"}, } - si := &schemaInit{ - env: vtenv.NewTestEnv(), - } + copyAlgo := sqlparser.AlgorithmValue("COPY") - for _, tc := range testCases { - t.Run(tc.testName, func(t *testing.T) { - diff, err := si.findTableSchemaDiff(tc.tableName, tc.currentSchema, tc.desiredSchema) - require.NoError(t, err) - stmt, err := si.env.Parser().Parse(diff) - require.NoError(t, err) - alterTable, ok := stmt.(*sqlparser.AlterTable) - require.True(t, ok) - require.NotNil(t, alterTable) - var alterAlgo sqlparser.AlterOption - for i, opt := range alterTable.AlterOptions { - if _, ok := opt.(sqlparser.AlgorithmValue); ok { - alterAlgo = alterTable.AlterOptions[i] - } + + newSchemaInit := func(t *testing.T, envVersion, serverVersion string) *schemaInit { + t.Helper() + + env, err := vtenv.New(vtenv.Options{MySQLServerVersion: envVersion}) + require.NoError(t, err) + + versionResult := sqltypes.MakeTestResult(sqltypes.MakeTestFields( + "@@version", + "varchar"), + serverVersion, + ) + + exec := func(ctx context.Context, query string, maxRows int, useDB bool) (*sqltypes.Result, error) { + if strings.EqualFold(query, sidecarVersionQuery) { + return versionResult, nil } - require.Equal(t, copyAlgo, alterAlgo) - }) + return nil, errors.New("unexpected query: " + query) + } + + return &schemaInit{ + env: env, + exec: exec, + } } + + t.Run("omitted on MySQL >= 8.0.32", func(t *testing.T) { + si := newSchemaInit(t, "8.0.31", "8.0.32") + + for _, tc := range testCases { + t.Run(tc.testName, func(t *testing.T) { + diff, err := si.findTableSchemaDiff(tc.tableName, tc.currentSchema, tc.desiredSchema) + require.NoError(t, err) + + stmt, err := si.env.Parser().Parse(diff) + require.NoError(t, err) + + alterTable, ok := stmt.(*sqlparser.AlterTable) + require.True(t, ok) + require.NotNil(t, alterTable) + + for _, opt := range alterTable.AlterOptions { + _, isAlgo := opt.(sqlparser.AlgorithmValue) + require.False(t, isAlgo, "expected no ALGORITHM hint on MySQL >= 8.0.32") + } + }) + } + }) + + t.Run("COPY on MySQL < 8.0.32", func(t *testing.T) { + si := newSchemaInit(t, "8.4.6", "8.0.31") + + for _, tc := range testCases { + t.Run(tc.testName, func(t *testing.T) { + diff, err := si.findTableSchemaDiff(tc.tableName, tc.currentSchema, tc.desiredSchema) + require.NoError(t, err) + + stmt, err := si.env.Parser().Parse(diff) + require.NoError(t, err) + + alterTable, ok := stmt.(*sqlparser.AlterTable) + require.True(t, ok) + require.NotNil(t, alterTable) + var found sqlparser.AlterOption + for _, opt := range alterTable.AlterOptions { + if _, ok := opt.(sqlparser.AlgorithmValue); ok { + found = opt + } + } + require.Equal(t, copyAlgo, found, "expected ALGORITHM=COPY on MySQL < 8.0.32") + }) + } + }) } // TestTableSchemaDiff ensures that the diff produced by schemaInit.findTableSchemaDiff @@ -272,7 +327,7 @@ func TestTableSchemaDiff(t *testing.T) { table: "t1", oldSchema: "create table if not exists _vt.t1(i int) charset=utf8mb4", newSchema: "create table if not exists _vt.t(i int) charset=utf8mb3", - expectedAlter: "alter table _vt.t1 charset utf8mb3, algorithm = copy", + expectedAlter: "alter table _vt.t1 charset utf8mb3", }, { name: "empty charset", @@ -286,35 +341,35 @@ func TestTableSchemaDiff(t *testing.T) { table: "t1", oldSchema: "create table if not exists _vt.t1(i int) engine=myisam", newSchema: "create table if not exists _vt.t(i int) engine=innodb", - expectedAlter: "alter table _vt.t1 engine innodb, algorithm = copy", + expectedAlter: "alter table _vt.t1 engine innodb", }, { name: "add, modify, transfer PK", table: "t1", oldSchema: "create table _vt.t1 (i int primary key, i1 varchar(10)) charset utf8mb4", newSchema: "create table _vt.t1 (i int, i1 varchar(20) character set utf8mb3 collate utf8mb3_bin, i2 int, primary key (i2)) charset utf8mb4", - expectedAlter: "alter table _vt.t1 drop primary key, modify column i1 varchar(20) character set utf8mb3 collate utf8mb3_bin, add column i2 int, add primary key (i2), algorithm = copy", + expectedAlter: "alter table _vt.t1 drop primary key, modify column i1 varchar(20) character set utf8mb3 collate utf8mb3_bin, add column i2 int, add primary key (i2)", }, { name: "modify visibility and add comment", table: "t1", oldSchema: "create table if not exists _vt.t1(c1 int, c2 int, c3 varchar(100)) charset utf8mb4", newSchema: "create table if not exists _vt.t1(c1 int, c2 int, c3 varchar(100) invisible comment 'hoping to drop') charset utf8mb4", - expectedAlter: "alter table _vt.t1 modify column c3 varchar(100) comment 'hoping to drop' invisible, algorithm = copy", + expectedAlter: "alter table _vt.t1 modify column c3 varchar(100) comment 'hoping to drop' invisible", }, { name: "add PK and remove index", table: "t1", oldSchema: "create table if not exists _vt.t1(c1 int, c2 int, c3 varchar(100), key (c2)) charset utf8mb4", newSchema: "create table if not exists _vt.t1(c1 int primary key, c2 int, c3 varchar(100)) charset utf8mb4", - expectedAlter: "alter table _vt.t1 drop key c2, add primary key (c1), algorithm = copy", + expectedAlter: "alter table _vt.t1 drop key c2, add primary key (c1)", }, { name: "add generated col", table: "t1", oldSchema: "create table if not exists _vt.t1(c1 int primary key) charset utf8mb4", newSchema: "create table if not exists _vt.t1(c1 int primary key, c2 varchar(10) generated always as ('hello')) charset utf8mb4", - expectedAlter: "alter table _vt.t1 add column c2 varchar(10) as ('hello') virtual, algorithm = copy", + expectedAlter: "alter table _vt.t1 add column c2 varchar(10) as ('hello') virtual", }, } diff --git a/go/vt/sqlparser/ast_funcs.go b/go/vt/sqlparser/ast_funcs.go index 90d73df9691..1a33b8728ff 100644 --- a/go/vt/sqlparser/ast_funcs.go +++ b/go/vt/sqlparser/ast_funcs.go @@ -2316,6 +2316,8 @@ func (key DropKeyType) ToString() string { return NormalKeyTypeStr case CheckKeyType: return CheckKeyTypeStr + case ConstraintType: + return ConstraintTypeStr default: return "Unknown DropKeyType" } diff --git a/go/vt/sqlparser/constants.go b/go/vt/sqlparser/constants.go index f1b614a12cf..37a8676ee50 100644 --- a/go/vt/sqlparser/constants.go +++ b/go/vt/sqlparser/constants.go @@ -353,6 +353,7 @@ const ( ForeignKeyTypeStr = "foreign key" NormalKeyTypeStr = "key" CheckKeyTypeStr = "check" + ConstraintTypeStr = "constraint" // TrimType strings BothTrimStr = "both" @@ -943,6 +944,7 @@ const ( ForeignKeyType NormalKeyType CheckKeyType + ConstraintType ) // LockOptionType constants diff --git a/go/vt/sqlparser/parse_test.go b/go/vt/sqlparser/parse_test.go index 4099e9f91fe..1e944dd5caf 100644 --- a/go/vt/sqlparser/parse_test.go +++ b/go/vt/sqlparser/parse_test.go @@ -1735,7 +1735,7 @@ var ( input: "alter table a drop check ch_1", }, { input: "alter table a drop constraint ch_1", - output: "alter table a drop check ch_1", + output: "alter table a drop constraint ch_1", }, { input: "alter table a drop foreign key kx", }, { @@ -6337,6 +6337,12 @@ var ( }, { input: "insert into t1 (a1) values row('a'), ('b')", output: "syntax error at position 39", + }, { + input: "select a, * from t", + output: "syntax error at position 12", + }, { + input: "select *, * from t", + output: "syntax error at position 12", }} ) diff --git a/go/vt/sqlparser/sql.go b/go/vt/sqlparser/sql.go index 5df698e434d..e8a5a05519f 100644 --- a/go/vt/sqlparser/sql.go +++ b/go/vt/sqlparser/sql.go @@ -1615,179 +1615,179 @@ var yyExca = [...]int{ 16, 110, -2, 6, -1, 57, - 1, 225, - 787, 225, - -2, 233, + 1, 227, + 787, 227, + -2, 235, -1, 58, - 148, 233, - 192, 233, - 376, 233, - -2, 593, + 148, 235, + 192, 235, + 376, 235, + -2, 595, -1, 66, - 37, 855, - 265, 855, - 276, 855, - 312, 869, - 313, 869, - -2, 857, + 37, 857, + 265, 857, + 276, 857, + 312, 871, + 313, 871, + -2, 859, -1, 71, - 267, 893, - -2, 891, + 267, 895, + -2, 893, -1, 132, - 1, 226, - 787, 226, - -2, 233, + 1, 228, + 787, 228, + -2, 235, -1, 143, - 149, 478, - 270, 478, - -2, 582, + 149, 480, + 270, 480, + -2, 584, -1, 162, - 148, 233, - 192, 233, - 376, 233, - -2, 602, + 148, 235, + 192, 235, + 376, 235, + -2, 604, -1, 780, 177, 102, -2, 104, -1, 989, - 94, 1731, - -2, 1553, + 94, 1733, + -2, 1555, -1, 990, - 94, 1732, - 237, 1736, - -2, 1554, + 94, 1734, + 237, 1738, + -2, 1556, -1, 991, - 237, 1735, + 237, 1737, -2, 103, -1, 1077, - 64, 967, - -2, 980, + 64, 969, + -2, 982, -1, 1082, - 264, 1714, - -2, 1623, - -1, 1164, - 275, 1180, - 280, 1180, - -2, 489, - -1, 1252, - 1, 650, - 787, 650, - -2, 233, - -1, 1577, - 237, 1736, - -2, 1554, - -1, 1790, - 64, 968, - -2, 984, + 264, 1716, + -2, 1625, + -1, 1165, + 275, 1182, + 280, 1182, + -2, 491, + -1, 1253, + 1, 652, + 787, 652, + -2, 235, + -1, 1578, + 237, 1738, + -2, 1556, -1, 1791, - 64, 969, - -2, 985, - -1, 1868, - 148, 233, - 192, 233, - 376, 233, - -2, 528, - -1, 1945, - 149, 478, - 270, 478, - -2, 582, - -1, 1954, - 275, 1181, - 280, 1181, - -2, 490, - -1, 2402, - 237, 1740, + 64, 970, + -2, 986, + -1, 1792, + 64, 971, + -2, 987, + -1, 1871, + 148, 235, + 192, 235, + 376, 235, + -2, 530, + -1, 1948, + 149, 480, + 270, 480, + -2, 584, + -1, 1957, + 275, 1183, + 280, 1183, + -2, 492, + -1, 2405, + 237, 1742, + -2, 1736, + -1, 2406, + 237, 1738, -2, 1734, - -1, 2403, - 237, 1736, - -2, 1732, - -1, 2521, - 148, 233, - 192, 233, - 376, 233, - -2, 529, - -1, 2528, - 27, 254, - -2, 256, - -1, 3004, - 85, 160, - 95, 160, - -2, 1047, - -1, 3069, - 762, 772, - -2, 746, - -1, 3303, - 54, 1673, - -2, 1667, - -1, 3622, - 96, 1614, - -2, 1619, - -1, 4147, - 762, 772, - -2, 760, - -1, 4187, + -1, 2527, + 148, 235, + 192, 235, + 376, 235, + -2, 531, + -1, 2534, + 27, 256, + -2, 258, + -1, 3011, + 85, 162, + 95, 162, + -2, 1049, + -1, 3076, + 762, 774, + -2, 748, + -1, 3310, + 54, 1675, + -2, 1669, + -1, 3630, + 96, 1616, + -2, 1621, + -1, 4155, + 762, 774, + -2, 762, + -1, 4195, 15, 110, 16, 110, 164, 91, - -2, 881, - -1, 4244, + -2, 883, + -1, 4252, 164, 92, -2, 110, - -1, 4264, - 97, 704, - 103, 704, - 113, 704, - 194, 704, - 195, 704, - 196, 704, - 197, 704, - 198, 704, - 199, 704, - 200, 704, - 201, 704, - 202, 704, - 203, 704, - 204, 704, - 205, 704, - 206, 704, - 207, 704, - 208, 704, - 209, 704, - 210, 704, - 211, 704, - 212, 704, - 213, 704, - 214, 704, - 215, 704, - 216, 704, - 217, 704, - 218, 704, - 219, 704, - 220, 704, - 221, 704, - 222, 704, - 223, 704, - 224, 704, - 225, 704, - 226, 704, - 227, 704, - 228, 704, - 229, 704, - 230, 704, - 231, 704, - 232, 704, - 233, 704, - 234, 704, - 235, 704, - -2, 2137, - -1, 4337, + -1, 4272, + 97, 706, + 103, 706, + 113, 706, + 194, 706, + 195, 706, + 196, 706, + 197, 706, + 198, 706, + 199, 706, + 200, 706, + 201, 706, + 202, 706, + 203, 706, + 204, 706, + 205, 706, + 206, 706, + 207, 706, + 208, 706, + 209, 706, + 210, 706, + 211, 706, + 212, 706, + 213, 706, + 214, 706, + 215, 706, + 216, 706, + 217, 706, + 218, 706, + 219, 706, + 220, 706, + 221, 706, + 222, 706, + 223, 706, + 224, 706, + 225, 706, + 226, 706, + 227, 706, + 228, 706, + 229, 706, + 230, 706, + 231, 706, + 232, 706, + 233, 706, + 234, 706, + 235, 706, + -2, 2139, + -1, 4345, 162, 97, 164, 97, -2, 110, - -1, 4421, + -1, 4429, 164, 96, -2, 110, - -1, 4427, + -1, 4435, 15, 110, 16, 110, -2, 101, @@ -1795,1344 +1795,1297 @@ var yyExca = [...]int{ const yyPrivate = 57344 -const yyLast = 62444 +const yyLast = 63763 var yyAct = [...]int{ - 1005, 3786, 3787, 3785, 2196, 92, 4379, 1000, 4368, 992, - 4245, 4244, 4246, 4397, 953, 4129, 954, 812, 4385, 4384, - 4226, 3430, 4315, 4314, 2518, 4262, 4342, 2208, 3580, 1322, - 2075, 3735, 4179, 4386, 3444, 3355, 4391, 1871, 3362, 4108, - 4031, 3399, 90, 2431, 1320, 9, 2433, 2578, 3154, 3239, - 3428, 3370, 2588, 3408, 3413, 3410, 3409, 3723, 3407, 3412, - 3411, 3427, 958, 784, 3320, 1196, 3317, 46, 3828, 3316, - 3634, 3620, 2977, 3839, 3128, 3153, 129, 993, 2492, 2472, - 4106, 3656, 2489, 3304, 3314, 2964, 778, 2557, 779, 1928, - 3039, 1075, 3610, 92, 3110, 3451, 3066, 2949, 2562, 3040, - 2619, 3041, 2506, 1134, 1102, 171, 2989, 47, 2493, 2970, - 1072, 2494, 2922, 2388, 1075, 2451, 2938, 45, 2230, 2356, - 2192, 1109, 2948, 3101, 2142, 2355, 2597, 1952, 2481, 1144, - 157, 2564, 1172, 1970, 3032, 1081, 1154, 1860, 1159, 3006, - 781, 1840, 3645, 1101, 1007, 1808, 2496, 955, 1825, 3319, - 2460, 111, 1771, 1074, 2236, 1078, 1590, 112, 2167, 2156, - 107, 1515, 1498, 2070, 1959, 1141, 782, 1162, 1138, 1142, - 1165, 1160, 2553, 794, 1161, 1859, 1104, 2554, 789, 2473, - 1119, 3823, 1121, 2920, 1845, 1097, 1085, 1245, 1793, 3815, - 2244, 2231, 106, 2263, 1573, 1549, 1310, 1098, 2083, 14, - 1080, 135, 2133, 13, 12, 133, 1070, 114, 175, 134, - 1079, 3581, 140, 1944, 141, 1114, 1083, 89, 771, 1296, - 4242, 113, 1256, 1250, 1318, 1198, 99, 1594, 6, 4369, - 2590, 2591, 2592, 2590, 3724, 3396, 3057, 1599, 1215, 1216, - 1217, 1113, 1220, 1221, 1222, 1223, 714, 4163, 1226, 1227, - 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, - 1238, 1239, 1240, 1241, 1242, 1135, 136, 1089, 1201, 2634, - 3716, 774, 142, 4164, 3089, 3088, 1069, 1176, 4286, 2036, - 1827, 3118, 3119, 1244, 3790, 4158, 4159, 2428, 2429, 2149, - 3790, 1267, 2148, 2147, 3681, 2146, 772, 1087, 4, 1209, - 1090, 2145, 1128, 1129, 4, 2144, 2114, 1266, 1073, 2918, - 4137, 1071, 1175, 2687, 3054, 1823, 1151, 3300, 711, 3059, - 712, 2623, 3243, 756, 4318, 4416, 1830, 4313, 3418, 4359, - 1146, 1202, 1205, 1206, 1150, 750, 2966, 1828, 1149, 4373, - 1103, 136, 1148, 3584, 4290, 4288, 118, 119, 120, 1512, - 123, 3418, 1509, 1804, 2469, 1218, 1831, 199, 3583, 2468, - 706, 3079, 3082, 4109, 3415, 4372, 1006, 1829, 2883, 2622, - 4289, 4287, 769, 770, 2154, 3470, 4241, 4027, 4026, 1152, - 3789, 1200, 1063, 1064, 1065, 1066, 3789, 3729, 3416, 1077, - 3730, 91, 1199, 1082, 1057, 756, 101, 4159, 4328, 995, - 1058, 1009, 1010, 1011, 996, 4037, 4284, 997, 998, 136, - 999, 3416, 1068, 3747, 2980, 1500, 3736, 3422, 4223, 1116, - 1117, 2579, 2616, 4036, 1529, 3830, 1530, 1531, 1012, 1013, - 2201, 4272, 1127, 1131, 957, 1127, 1131, 957, 4267, 2621, - 3422, 3496, 2981, 2462, 750, 3352, 3353, 2513, 2514, 1528, - 1532, 4270, 2126, 2127, 1861, 4227, 1862, 1511, 2919, 3746, - 3015, 4277, 4278, 3014, 3351, 3117, 3016, 2691, 2512, 1516, - 3100, 3372, 3373, 2694, 101, 1274, 1286, 1061, 4271, 1315, - 1275, 750, 3060, 1060, 750, 91, 4130, 91, 1273, 745, - 1272, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, - 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, - 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, - 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, - 1053, 1054, 1055, 4231, 1516, 2573, 103, 730, 3853, 1287, - 1291, 1292, 1274, 2692, 3419, 91, 1280, 1275, 93, 3027, - 3448, 2079, 1249, 750, 1257, 1258, 2531, 2530, 3478, 2567, - 728, 3446, 750, 751, 1510, 2973, 2974, 3419, 101, 3175, - 101, 4344, 4345, 4346, 4347, 4348, 4349, 4350, 4351, 4352, - 4353, 4354, 4355, 2430, 3476, 3439, 1493, 1261, 1526, 2685, - 1499, 4319, 3371, 1314, 1260, 2125, 103, 1219, 3102, 1313, - 3452, 725, 764, 2129, 3374, 768, 762, 2026, 3067, 1775, - 740, 1262, 4320, 4079, 2958, 4080, 2959, 2598, 2944, 3286, - 2660, 2450, 2661, 2452, 2662, 735, 3703, 3287, 101, 1819, - 1289, 1290, 1307, 1492, 2452, 1312, 1295, 738, 1288, 2641, - 748, 1253, 3105, 3718, 3717, 1281, 2663, 3449, 749, 1293, - 2639, 1225, 2027, 1526, 2028, 1224, 1550, 2637, 3447, 1294, - 4011, 2688, 3714, 2689, 1155, 2601, 3440, 3441, 1156, 3794, - 2490, 1156, 751, 1194, 1193, 1192, 3631, 1120, 1191, 3467, - 1190, 1778, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1559, - 1558, 1560, 1561, 2638, 2080, 2642, 1189, 1188, 1187, 1182, - 1937, 1522, 1195, 3374, 1514, 4417, 2640, 3394, 715, 751, - 717, 731, 751, 753, 1139, 752, 721, 1139, 719, 723, - 732, 724, 1168, 718, 2566, 729, 1167, 4426, 720, 733, - 734, 737, 741, 742, 743, 739, 736, 2461, 727, 754, - 3055, 750, 1139, 1115, 1204, 1319, 1137, 1319, 1319, 3176, - 1167, 3242, 2071, 3623, 1203, 1857, 1248, 2648, 2644, 2646, - 2647, 2645, 2649, 2650, 2651, 2652, 1522, 3106, 2627, 2626, - 4302, 2067, 1501, 1212, 1130, 1124, 1122, 1130, 1124, 1122, - 3290, 751, 3091, 3077, 2943, 2459, 2476, 2458, 2457, 3713, - 751, 2453, 2068, 1265, 705, 4301, 4414, 1075, 1574, 1579, - 1580, 3061, 1583, 1585, 1586, 1587, 1588, 1589, 4282, 1592, - 1593, 1595, 1595, 101, 1595, 1595, 1600, 1600, 1600, 1603, - 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, - 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, - 1624, 1625, 1626, 1627, 1628, 1629, 1630, 1631, 1632, 1633, - 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, 1642, 1643, - 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, - 1654, 1655, 1656, 1657, 1658, 1659, 1660, 1661, 1662, 1663, - 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, 1672, 1673, - 1674, 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, - 1684, 1685, 1686, 1687, 1688, 1689, 1690, 1691, 1692, 1693, - 1694, 1695, 1696, 1697, 1698, 1699, 1700, 1701, 1702, 1703, - 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, - 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721, 1722, 1723, - 1724, 1725, 1726, 1584, 2620, 1575, 4136, 1727, 1153, 1729, - 1730, 1731, 1732, 1733, 1308, 3058, 1827, 1567, 1568, 1569, - 1570, 1600, 1600, 1600, 1600, 1600, 1600, 1581, 1489, 751, - 1571, 1490, 1491, 3832, 3831, 4182, 1740, 1741, 1742, 1743, - 1744, 1745, 1746, 1747, 1748, 1749, 1750, 1751, 1752, 1753, - 1259, 3568, 4276, 2474, 2475, 2956, 3788, 3745, 3081, 3632, - 1858, 100, 3788, 1185, 1174, 4125, 1174, 1270, 1183, 1276, - 1277, 1278, 1279, 4229, 2038, 2037, 2039, 2040, 2041, 4142, - 1521, 1518, 1519, 1520, 1525, 1527, 1524, 1174, 1523, 3679, - 3680, 3682, 4401, 1316, 1317, 4274, 1564, 755, 1517, 1596, - 4275, 1597, 1598, 3420, 3421, 94, 3080, 1174, 1081, 1958, - 1564, 4228, 1508, 1271, 1601, 1602, 3424, 1768, 746, 1303, - 750, 1305, 3099, 1774, 4390, 3098, 3420, 3421, 1764, 2693, - 3670, 2570, 1075, 747, 1123, 1251, 1075, 1123, 3652, 3424, - 2692, 3251, 1075, 1284, 3011, 1521, 1518, 1519, 1520, 1525, - 1527, 1524, 2976, 1523, 2895, 100, 2204, 100, 1849, 2618, - 1302, 1304, 2056, 1517, 3109, 2476, 1728, 2923, 2925, 1264, - 1565, 1566, 2571, 132, 3358, 3250, 2971, 713, 1081, 1173, - 2569, 1173, 2272, 1765, 3468, 2519, 1564, 1167, 1170, 1171, - 1561, 1139, 3350, 3122, 1782, 1164, 1168, 1804, 1786, 2720, - 1532, 1211, 1173, 1297, 1074, 1544, 92, 2709, 1556, 1557, - 1559, 1558, 1560, 1561, 2572, 100, 1093, 1163, 4393, 2245, - 2084, 3270, 1173, 1822, 1311, 3359, 1186, 4150, 2568, 1531, - 1957, 1184, 2055, 1197, 4420, 1269, 2246, 3709, 1529, 1784, - 1530, 1531, 3644, 111, 3268, 1785, 126, 4422, 1081, 112, - 3361, 1931, 1532, 1765, 2463, 2138, 2064, 1766, 1734, 1735, - 1736, 1737, 1738, 1739, 1532, 1530, 1531, 1772, 46, 1863, - 3356, 1300, 4297, 3149, 1780, 1301, 4380, 1934, 1935, 1936, - 4257, 4408, 3029, 2720, 2237, 1306, 2729, 2237, 2954, 1532, - 3372, 3373, 1826, 2264, 2482, 2483, 3848, 3357, 2266, 114, - 4329, 3687, 2271, 2267, 3686, 2605, 2268, 2269, 2270, 1249, - 1243, 2265, 2273, 2274, 2275, 2276, 2277, 2278, 2279, 2280, - 2281, 3129, 1299, 3112, 1174, 127, 1950, 1967, 3111, 1966, - 1956, 4321, 1806, 3363, 2615, 2021, 4399, 2613, 1769, 4400, - 1783, 4398, 2228, 1251, 2011, 2012, 1185, 3112, 751, 1943, - 2017, 2018, 3111, 2924, 2077, 1071, 1183, 1174, 1781, 1073, - 1962, 1821, 1298, 1960, 1960, 1809, 1811, 1319, 2617, 2610, - 2003, 1283, 2474, 2475, 1252, 1247, 1972, 2243, 1973, 2085, - 1975, 1977, 1285, 1964, 1981, 1983, 1985, 1987, 1989, 2052, - 1268, 2053, 1854, 1855, 2054, 2060, 1961, 2058, 2059, 2057, - 2061, 2062, 2063, 1815, 2610, 3671, 1818, 4418, 101, 1923, - 1999, 3371, 2614, 2002, 1088, 2004, 3131, 1529, 1174, 1530, - 1531, 1804, 1529, 3374, 1530, 1531, 1816, 4193, 2170, 2242, - 1941, 1940, 1939, 3742, 1787, 3743, 1953, 4403, 4323, 1173, - 4117, 1210, 4019, 1532, 4018, 1207, 1804, 2612, 1532, 2046, - 4009, 2051, 2007, 2220, 2209, 2210, 2211, 2212, 2222, 2213, - 2214, 2215, 2227, 2223, 2216, 2217, 2224, 2225, 2226, 2218, - 2219, 2221, 1173, 1174, 3759, 3758, 4194, 1177, 1167, 1009, - 1010, 1011, 1179, 2072, 2073, 1246, 1180, 1178, 3694, 4118, - 3141, 3140, 3139, 3693, 2172, 3133, 3683, 3137, 1838, 3132, - 2044, 3130, 1529, 4419, 1530, 1531, 3135, 3397, 1181, 2173, - 1562, 1563, 2171, 1248, 1150, 3134, 3390, 1249, 1149, 1812, - 2045, 136, 1148, 198, 3037, 3036, 1814, 1813, 1532, 2160, - 2161, 2699, 2700, 1173, 3136, 3138, 2033, 3035, 1177, 1167, - 2576, 2090, 2047, 1179, 2031, 3360, 137, 1180, 1178, 1319, - 1319, 1550, 2086, 2087, 1554, 1555, 1556, 1557, 1559, 1558, - 1560, 1561, 180, 2030, 2112, 92, 2091, 198, 92, 1837, - 1819, 2043, 2029, 2098, 2099, 2100, 1262, 1551, 1552, 1553, - 1554, 1555, 1556, 1557, 1559, 1558, 1560, 1561, 1173, 2019, - 137, 2111, 2013, 2010, 1167, 1170, 1171, 2009, 1139, 4334, - 1804, 2008, 1164, 1168, 4332, 1804, 180, 2032, 3020, 1979, - 2134, 1779, 1529, 2134, 1530, 1531, 1100, 1099, 1100, 3298, - 1495, 4299, 177, 756, 1857, 178, 1529, 46, 1530, 1531, - 46, 2200, 2088, 2199, 2199, 2197, 2197, 1833, 1532, 2092, - 1804, 2094, 2095, 2096, 2097, 3676, 4138, 756, 2101, 1100, - 4357, 197, 1532, 2390, 3643, 3018, 1529, 756, 1530, 1531, - 2113, 1529, 2392, 1530, 1531, 4322, 177, 1760, 4145, 178, - 1550, 2725, 1758, 1546, 2586, 1547, 2585, 1756, 1004, 4144, - 1757, 1755, 1532, 1759, 2162, 2756, 1834, 1532, 1081, 2716, - 1548, 1562, 1563, 1545, 4121, 197, 1551, 1552, 1553, 1554, - 1555, 1556, 1557, 1559, 1558, 1560, 1561, 1550, 1764, 3121, - 2283, 1552, 1553, 1554, 1555, 1556, 1557, 1559, 1558, 1560, - 1561, 1248, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1559, - 1558, 1560, 1561, 1551, 1552, 1553, 1554, 1555, 1556, 1557, - 1559, 1558, 1560, 1561, 2766, 2584, 4120, 2583, 2175, 2724, - 2177, 2178, 2179, 2180, 2181, 2182, 2184, 2186, 2187, 2188, - 2189, 2190, 2191, 1765, 2137, 4119, 2232, 2137, 2135, 2136, - 2139, 2135, 2136, 2119, 2120, 2176, 1933, 4370, 181, 2169, - 4309, 1804, 1575, 4324, 4046, 117, 2582, 187, 2581, 4237, - 1804, 3485, 4045, 4235, 1804, 4003, 116, 2389, 115, 3364, - 2238, 4014, 2174, 3368, 4233, 1804, 1529, 3999, 1530, 1531, - 1529, 3367, 1530, 1531, 1529, 3998, 1530, 1531, 2402, 2401, - 108, 2307, 181, 1804, 2160, 2161, 2158, 2159, 1592, 2203, - 109, 187, 1532, 2400, 3847, 2299, 1532, 1766, 3845, 1529, - 1532, 1530, 1531, 1933, 1804, 3369, 1529, 3755, 1530, 1531, - 1529, 2157, 1530, 1531, 3365, 2247, 2248, 2249, 2250, 3366, - 1763, 1529, 1804, 1530, 1531, 1532, 1550, 2391, 4134, 2261, - 1762, 1804, 1532, 1528, 1804, 2282, 1532, 4092, 1804, 1529, - 1761, 1530, 1531, 3691, 2297, 3675, 4041, 1532, 2467, 2770, - 1803, 1804, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1559, - 1558, 1560, 1561, 2768, 3453, 1532, 2399, 1933, 4222, 2405, - 2406, 3450, 117, 1528, 1804, 2498, 3393, 172, 1529, 3392, - 1530, 1531, 3103, 116, 1529, 115, 1530, 1531, 3046, 111, - 1933, 4203, 4002, 110, 1529, 112, 1530, 1531, 3033, 2402, - 2487, 2941, 108, 1529, 1532, 1530, 1531, 1760, 110, 1754, - 1532, 111, 109, 2435, 2400, 110, 2528, 112, 1933, 4199, - 1532, 172, 1094, 2682, 2380, 2381, 2382, 2383, 2384, 1532, - 1095, 2447, 2168, 1550, 2674, 2708, 2673, 2500, 4090, 1804, - 3629, 2404, 2632, 1098, 2407, 2408, 2631, 2441, 1144, 2442, - 4099, 1804, 4087, 1804, 3727, 4135, 4069, 1804, 1804, 1551, - 1552, 1553, 1554, 1555, 1556, 1557, 1559, 1558, 1560, 1561, - 2471, 4022, 1804, 1804, 1099, 1100, 1144, 2455, 2423, 2939, - 2425, 1933, 4010, 2538, 2539, 2540, 2532, 1089, 2533, 2534, - 2535, 2536, 2537, 2523, 2522, 1529, 2541, 1530, 1531, 2436, - 2504, 2448, 2543, 3609, 1804, 2545, 2546, 2547, 2548, 1529, - 4006, 1530, 1531, 1529, 2115, 1530, 1531, 2081, 2454, 3602, - 1804, 1532, 2599, 3599, 1804, 3727, 1804, 2464, 2526, 110, - 2559, 1933, 3725, 2610, 1804, 1532, 3597, 1804, 3068, 1532, - 3560, 1804, 2477, 2042, 2565, 3650, 1804, 2850, 1804, 3383, - 3382, 2485, 3380, 3381, 2510, 1128, 1129, 2509, 2034, 2508, - 1529, 2525, 1530, 1531, 2524, 2024, 1529, 2020, 1530, 1531, - 3378, 3379, 2978, 2596, 3558, 1804, 1529, 2575, 1530, 1531, - 1529, 2016, 1530, 1531, 3378, 3377, 1532, 2986, 1804, 2692, - 3090, 116, 1532, 1529, 1804, 1530, 1531, 1529, 3007, 1530, - 1531, 1176, 1532, 3007, 2604, 2015, 1532, 2607, 2014, 2608, - 1835, 1960, 2560, 2556, 2549, 2551, 2552, 2574, 1309, 1532, - 1927, 3071, 3051, 1532, 3064, 3065, 2624, 2527, 173, 1528, - 2718, 1529, 3710, 1530, 1531, 185, 1175, 3038, 2202, 1804, - 2717, 2603, 2560, 2606, 2602, 1933, 1932, 2985, 2628, 2986, - 2625, 2978, 2629, 2630, 1927, 1926, 2611, 1532, 3554, 1804, - 1869, 1868, 3315, 4177, 3345, 1528, 3008, 3551, 1804, 4149, - 1933, 3008, 173, 3643, 2692, 2697, 3010, 193, 4113, 185, - 2986, 2692, 3588, 3647, 1075, 1075, 1075, 2636, 1529, 3380, - 1530, 1531, 3273, 1529, 2635, 1530, 1531, 1529, 2511, 1530, - 1531, 2850, 3549, 1804, 1585, 2753, 1585, 2752, 2986, 2610, - 2593, 3547, 1804, 2480, 1532, 1529, 2466, 1530, 1531, 1532, - 2610, 193, 2712, 1532, 1529, 1820, 1530, 1531, 3643, 3665, - 174, 179, 176, 182, 183, 184, 186, 188, 189, 190, - 191, 1532, 3545, 1804, 2426, 1076, 192, 194, 195, 196, - 1532, 3646, 2666, 2202, 2402, 2401, 3543, 1804, 2140, 1529, - 2124, 1530, 1531, 2066, 3541, 1804, 1856, 1836, 1529, 2715, - 1530, 1531, 3539, 1804, 174, 179, 176, 182, 183, 184, - 186, 188, 189, 190, 191, 1532, 1529, 1158, 1530, 1531, - 192, 194, 195, 196, 1532, 3695, 103, 1157, 101, 1529, - 4280, 1530, 1531, 3445, 3537, 1804, 4205, 2684, 3400, 3535, - 1804, 4033, 1532, 1529, 1995, 1530, 1531, 3533, 1804, 4000, - 3860, 1529, 2690, 1530, 1531, 1532, 3531, 1804, 101, 1529, - 130, 1530, 1531, 2705, 3604, 2707, 3708, 2698, 3705, 1532, - 3689, 3501, 3500, 1929, 2710, 2558, 2711, 1532, 3529, 1804, - 2704, 3402, 3696, 3697, 3698, 1532, 3043, 2701, 2702, 2703, - 2706, 1529, 3398, 1530, 1531, 2169, 1529, 1251, 1530, 1531, - 2713, 1996, 1997, 1998, 1529, 3042, 1530, 1531, 3527, 1804, - 3296, 3072, 2555, 1529, 2550, 1530, 1531, 1532, 3525, 1804, - 2544, 1529, 1532, 1530, 1531, 2542, 2049, 1955, 2676, 2677, - 1532, 1951, 1925, 2679, 128, 1529, 4034, 1530, 1531, 1532, - 2728, 2573, 2680, 3657, 3658, 3523, 1804, 1532, 2439, 3521, - 1804, 2894, 4365, 3507, 1804, 1529, 2117, 1530, 1531, 3043, - 4363, 1532, 3483, 1804, 3151, 1529, 4316, 1530, 1531, 4157, - 4074, 3660, 3628, 3627, 3626, 1529, 710, 1530, 1531, 3315, - 3291, 1532, 2667, 2926, 3337, 2882, 2735, 2915, 1804, 3338, - 3663, 1532, 2929, 3335, 3662, 2199, 3334, 2197, 3336, 2764, - 3333, 1532, 1529, 2750, 1530, 1531, 1529, 3699, 1530, 1531, - 1529, 4153, 1530, 1531, 1991, 3339, 1075, 2995, 2996, 1529, - 4035, 1530, 1531, 2118, 2913, 1804, 2470, 1832, 1532, 1091, - 4307, 2927, 1532, 2888, 1804, 2445, 1532, 2865, 1804, 3651, - 2983, 2984, 3305, 3307, 1529, 1532, 1530, 1531, 3814, 2498, - 3813, 3308, 1075, 3003, 3278, 773, 3277, 4116, 2857, 1804, - 3700, 3701, 3702, 3636, 3838, 2848, 1804, 1992, 1993, 1994, - 1532, 3635, 3840, 3600, 2930, 3639, 2932, 2846, 1804, 3302, - 1092, 1529, 1081, 1530, 1531, 2982, 2833, 1804, 2168, 2065, - 1529, 1081, 1530, 1531, 1529, 1059, 1530, 1531, 3376, 3025, - 4339, 2963, 46, 3812, 3047, 2659, 2658, 1532, 2657, 2245, - 2656, 3000, 2655, 2654, 3002, 1529, 1532, 1530, 1531, 1214, - 1532, 2947, 1529, 1772, 1530, 1531, 2246, 3001, 1108, 2917, - 1529, 2653, 1530, 1531, 1529, 2972, 1530, 1531, 2165, 2163, - 2164, 1532, 1107, 1529, 1213, 1530, 1531, 3461, 1532, 3042, - 2946, 2942, 3115, 4305, 2945, 1494, 1532, 2937, 2831, 1804, - 1532, 1826, 3076, 3028, 3030, 2961, 1765, 3031, 3078, 1532, - 137, 108, 2975, 3641, 2829, 1804, 110, 3021, 3005, 2827, - 1804, 109, 3045, 2825, 1804, 4395, 108, 3048, 3049, 2960, - 2823, 1804, 110, 2482, 2483, 3009, 109, 3295, 2670, 3012, - 115, 4240, 4029, 3087, 2821, 1804, 3375, 3019, 2999, 2425, - 2465, 2565, 3022, 1145, 4341, 1529, 4340, 1530, 1531, 2819, - 1804, 1538, 1539, 1540, 1541, 1542, 1543, 1537, 1534, 3034, - 3611, 1529, 2696, 1530, 1531, 2123, 1529, 2122, 1530, 1531, - 1529, 1532, 1530, 1531, 4098, 3044, 3566, 1529, 4097, 1530, - 1531, 2817, 1804, 4077, 117, 3562, 3052, 1532, 3846, 3844, - 3498, 1529, 1532, 1530, 1531, 116, 1532, 115, 2815, 1804, - 3843, 3825, 3084, 1532, 1943, 110, 1529, 3276, 1530, 1531, - 2813, 1804, 116, 3073, 3074, 3275, 3706, 1532, 3125, 3126, - 3640, 3638, 3403, 2811, 1804, 2594, 117, 2809, 1804, 1938, - 1106, 3083, 1532, 1529, 3824, 1530, 1531, 116, 1529, 115, - 1530, 1531, 1529, 3621, 1530, 1531, 2978, 1529, 3798, 1530, - 1531, 117, 2807, 1804, 3085, 1529, 2941, 1530, 1531, 1532, - 4366, 3104, 116, 3179, 1532, 4367, 4366, 1529, 1532, 1530, - 1531, 3107, 3142, 1532, 2754, 4367, 2437, 3123, 1850, 1842, - 1529, 1532, 1530, 1531, 1529, 4122, 1530, 1531, 2805, 1804, - 121, 122, 3674, 1532, 1550, 5, 3160, 3161, 3162, 3163, - 3164, 3165, 3166, 3167, 3168, 3169, 1532, 1, 3, 1529, - 1532, 1530, 1531, 2803, 1804, 105, 3177, 2801, 1804, 3143, - 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1559, 1558, 1560, - 1561, 4186, 1067, 3127, 1497, 1532, 8, 1496, 2799, 1804, - 3678, 3144, 2794, 1804, 4269, 1529, 726, 1530, 1531, 2790, - 1804, 2427, 1770, 2788, 1804, 4317, 3124, 4265, 4266, 2781, - 1804, 2035, 2025, 3737, 3237, 2354, 4030, 3826, 3827, 3181, - 1529, 1532, 1530, 1531, 1529, 3113, 1530, 1531, 3114, 3829, - 3406, 2600, 3704, 2389, 2563, 2389, 1166, 162, 2520, 2521, - 1805, 1807, 4217, 3145, 125, 1529, 1532, 1530, 1531, 1529, - 1532, 1530, 1531, 1132, 124, 3063, 1529, 1169, 1530, 1531, - 1529, 1282, 1530, 1531, 3244, 2595, 1529, 3246, 1530, 1531, - 3255, 1532, 2498, 3728, 3026, 1532, 2779, 1804, 2529, 1875, - 1873, 1874, 1532, 1872, 1877, 3497, 1532, 3170, 1876, 3489, - 4181, 3469, 1532, 2755, 3567, 2128, 763, 4310, 2998, 757, - 3217, 200, 1864, 2391, 1843, 2391, 1893, 2121, 1208, 716, - 3384, 2633, 3322, 722, 92, 1582, 2116, 2498, 2498, 2498, - 2498, 2498, 3227, 3228, 3229, 3230, 3231, 3274, 3013, 1126, - 3245, 1118, 3247, 1529, 2500, 1530, 1531, 2498, 1096, 2438, - 2498, 3280, 1529, 3254, 1530, 1531, 1529, 2931, 1530, 1531, - 3282, 3255, 1125, 4007, 3487, 3323, 1081, 3633, 3301, 1532, - 3303, 2965, 3306, 2228, 3266, 3299, 4115, 3837, 1532, 4338, - 4204, 2077, 1532, 3023, 1839, 3219, 1078, 3221, 3344, 2500, - 2500, 2500, 2500, 2500, 3279, 3327, 3267, 3269, 3271, 3587, - 3272, 3281, 3289, 3232, 3233, 3234, 3235, 2727, 2235, 2500, - 3423, 1572, 2500, 3292, 3293, 3294, 788, 3309, 3310, 2497, - 3431, 1529, 959, 1530, 1531, 3346, 1824, 3793, 3347, 2155, - 786, 1080, 785, 783, 3436, 3328, 3435, 3432, 3331, 3329, - 3330, 1079, 3332, 2933, 3340, 111, 2911, 1532, 3388, 3389, - 2979, 112, 1536, 3348, 2910, 1535, 994, 2921, 3326, 1851, - 2990, 3312, 2906, 2988, 2987, 2668, 3354, 2505, 3318, 3659, - 3655, 2905, 4261, 3318, 2499, 1880, 2495, 2940, 945, 3385, - 944, 3387, 3386, 795, 2220, 2209, 2210, 2211, 2212, 2222, - 2213, 2214, 2215, 2227, 2223, 2216, 2217, 2224, 2225, 2226, - 2218, 2219, 2221, 1529, 787, 1530, 1531, 777, 3404, 2565, - 3425, 1529, 1008, 1530, 1531, 943, 942, 3433, 3434, 1529, - 3442, 1530, 1531, 2904, 2955, 1817, 4306, 2903, 1529, 1532, - 1530, 1531, 3297, 2957, 3024, 2902, 3285, 1532, 1513, 3457, - 3454, 1789, 3456, 2901, 1792, 1532, 2446, 1810, 2892, 3466, - 3464, 4140, 2695, 3495, 1532, 3405, 1788, 4147, 3414, 3471, - 3472, 3474, 3473, 3722, 3395, 3475, 3069, 3477, 2587, 3479, - 1894, 3490, 3491, 3492, 3493, 3494, 74, 50, 4107, 4178, - 1529, 937, 1530, 1531, 1529, 934, 1530, 1531, 3795, 1585, - 3796, 3797, 1529, 1585, 1530, 1531, 3240, 3241, 4160, 4161, - 1529, 933, 1530, 1531, 4162, 1529, 1532, 1530, 1531, 3612, - 1532, 3614, 2292, 1507, 1504, 3053, 2130, 104, 1532, 40, - 39, 38, 37, 36, 3622, 30, 1532, 29, 3582, 3465, - 28, 1532, 27, 26, 2891, 3586, 1907, 1910, 1911, 1912, - 1913, 1914, 1915, 33, 1916, 1917, 1919, 1920, 1918, 1921, - 1922, 1895, 1896, 1897, 1898, 1878, 1879, 1908, 23, 1881, - 25, 1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, - 24, 22, 1891, 1899, 1900, 1901, 1902, 4377, 1903, 1904, - 1905, 1906, 4378, 4407, 1892, 4243, 2498, 4183, 3321, 3417, - 2890, 1529, 3619, 1530, 1531, 2889, 4312, 4394, 131, 3672, - 3617, 4343, 3613, 4304, 3615, 2991, 2994, 2995, 2996, 2992, - 4303, 2993, 2997, 3436, 4254, 3435, 3432, 1532, 4383, 4249, - 3673, 60, 2886, 57, 55, 3630, 139, 3637, 2881, 3589, - 138, 3591, 3592, 3593, 2874, 58, 56, 54, 53, 1254, - 3654, 3642, 51, 3426, 102, 3459, 3460, 1529, 2500, 1530, - 1531, 35, 1529, 3661, 1530, 1531, 2873, 34, 3664, 3668, - 3669, 2872, 21, 20, 3667, 19, 2240, 3666, 18, 17, - 16, 2241, 15, 1532, 3684, 3685, 2871, 11, 1532, 1529, - 10, 1530, 1531, 2870, 43, 1529, 42, 1530, 1531, 2869, - 41, 1529, 32, 1530, 1531, 31, 44, 3690, 7, 3692, - 2, 3056, 2589, 0, 2868, 1532, 0, 0, 2867, 2303, - 0, 1532, 0, 1529, 2866, 1530, 1531, 1532, 1529, 2860, - 1530, 1531, 3715, 2859, 0, 0, 3719, 3720, 3721, 0, - 0, 0, 0, 1529, 0, 1530, 1531, 0, 0, 1532, - 1529, 0, 1530, 1531, 1532, 0, 1529, 0, 1530, 1531, - 2858, 0, 0, 0, 1766, 3732, 3733, 2855, 0, 1532, - 3734, 1529, 0, 1530, 1531, 1529, 1532, 1530, 1531, 2854, - 0, 1529, 1532, 1530, 1531, 2853, 1529, 0, 1530, 1531, - 1529, 0, 1530, 1531, 2851, 0, 0, 1532, 2844, 2386, - 0, 1532, 3749, 0, 0, 0, 0, 1532, 0, 0, - 0, 1909, 1532, 0, 0, 2841, 1532, 1529, 0, 1530, - 1531, 0, 0, 2839, 1529, 0, 1530, 1531, 3760, 2417, - 0, 2837, 0, 0, 0, 2796, 1529, 0, 1530, 1531, - 0, 0, 1529, 1532, 1530, 1531, 1805, 2424, 2776, 0, - 1532, 1529, 2775, 1530, 1531, 1529, 2771, 1530, 1531, 0, - 0, 3811, 1532, 0, 3818, 0, 3820, 3801, 1532, 3802, - 3803, 3804, 1529, 0, 1530, 1531, 0, 1532, 0, 0, - 1529, 1532, 1530, 1531, 0, 0, 0, 2449, 1529, 3754, - 1530, 1531, 1529, 3791, 1530, 1531, 0, 3322, 1532, 0, - 92, 0, 3322, 0, 0, 1529, 1532, 1530, 1531, 1529, - 3821, 1530, 1531, 1529, 1532, 1530, 1531, 2769, 1532, 0, - 3862, 0, 2761, 2199, 0, 2197, 1794, 0, 0, 0, - 0, 1532, 0, 0, 0, 1532, 2732, 0, 0, 1532, - 1802, 3822, 1081, 1795, 3852, 3854, 0, 0, 0, 0, - 0, 0, 0, 2726, 3842, 0, 3841, 0, 0, 0, - 3849, 3851, 46, 2721, 0, 4013, 0, 0, 2443, 2444, - 1801, 1799, 1800, 1796, 1529, 1797, 1530, 1531, 0, 1529, - 0, 1530, 1531, 3711, 3712, 0, 0, 0, 3866, 3863, - 3864, 0, 0, 1529, 0, 1530, 1531, 0, 1798, 0, - 1532, 0, 0, 0, 3782, 1532, 0, 0, 0, 4005, - 1529, 2577, 1530, 1531, 0, 0, 0, 4004, 4020, 1532, - 1529, 0, 1530, 1531, 0, 1794, 0, 4024, 4025, 0, - 0, 4032, 4015, 4016, 4017, 0, 1532, 4071, 4072, 1802, - 0, 3318, 1795, 0, 0, 4075, 1532, 0, 2199, 0, - 2197, 3856, 0, 0, 3819, 2991, 2994, 2995, 2996, 2992, - 0, 2993, 2997, 0, 0, 3657, 3658, 1790, 1791, 1801, - 1799, 1800, 1796, 0, 1797, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 4078, 0, 1798, 0, 4081, - 0, 0, 0, 4123, 3322, 0, 0, 0, 0, 0, - 0, 3858, 0, 0, 0, 0, 0, 0, 1603, 1604, + 1005, 3794, 3795, 3793, 1000, 92, 4387, 992, 2199, 4376, + 4253, 4252, 4392, 4254, 953, 4405, 4137, 954, 812, 4393, + 3438, 4322, 4234, 2524, 4323, 4350, 4270, 3588, 4187, 1323, + 2211, 2078, 3743, 4394, 3452, 3363, 4399, 1874, 3370, 4116, + 1321, 3407, 3731, 2434, 4039, 90, 2584, 9, 3416, 3246, + 2436, 2594, 3378, 3421, 3418, 3417, 3415, 3420, 3419, 3324, + 3435, 3436, 1197, 784, 3328, 3325, 3642, 3628, 3847, 3135, + 3160, 129, 3836, 2476, 958, 993, 2495, 3664, 3322, 46, + 2498, 3311, 2970, 778, 3618, 2563, 2983, 779, 3046, 3459, + 3117, 1075, 3073, 92, 2955, 2568, 1135, 3047, 2625, 3048, + 171, 4114, 2512, 1102, 2996, 2499, 1072, 47, 2976, 2455, + 2944, 2391, 2500, 1110, 1075, 2928, 2954, 2359, 2195, 1173, + 2233, 2145, 3108, 1973, 2603, 45, 1955, 157, 2485, 1145, + 2570, 3039, 1155, 1863, 2358, 3013, 1841, 1931, 1081, 1160, + 781, 1101, 3653, 1809, 1007, 1826, 955, 3161, 2464, 3327, + 111, 1591, 2239, 112, 1772, 107, 2170, 2502, 2159, 1516, + 1499, 2073, 1962, 1142, 1166, 1074, 782, 1078, 1139, 1143, + 2559, 1163, 794, 1161, 1162, 789, 2560, 1847, 1862, 1085, + 1097, 1120, 3831, 1246, 2926, 1122, 106, 1794, 1104, 2247, + 2266, 1574, 3823, 1550, 1098, 1311, 2086, 2136, 14, 13, + 1080, 2477, 114, 3589, 12, 140, 135, 1070, 133, 175, + 134, 1947, 141, 1115, 1083, 1257, 113, 771, 1079, 1297, + 1251, 1595, 1199, 89, 1319, 1087, 4, 4250, 6, 4377, + 3732, 3404, 4, 1114, 2596, 1216, 1217, 1218, 1245, 1221, + 1222, 1223, 1224, 1600, 3064, 1227, 1228, 1229, 1230, 1231, + 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241, + 1242, 1243, 1089, 1202, 1177, 99, 1136, 136, 714, 2640, + 142, 3724, 4171, 2234, 118, 119, 120, 1069, 123, 2596, + 2597, 2598, 3096, 3095, 2039, 199, 1210, 4294, 706, 3689, + 1828, 3125, 3126, 4166, 1090, 772, 4167, 1268, 4172, 1129, + 769, 770, 2152, 756, 2151, 1824, 1071, 2431, 2432, 2150, + 1063, 1064, 1065, 1066, 1073, 2149, 1176, 1077, 3798, 4145, + 3066, 1082, 3426, 2148, 2147, 1130, 2117, 3426, 1267, 3798, + 711, 1147, 712, 3061, 2924, 1203, 1206, 1207, 1152, 1151, + 3423, 1150, 136, 1149, 3307, 2629, 2693, 1117, 1118, 756, + 2972, 1057, 4326, 774, 1831, 1006, 995, 1058, 1009, 1010, + 1011, 996, 750, 3086, 997, 998, 3250, 999, 1128, 1132, + 957, 4381, 101, 4424, 4298, 4321, 4296, 1219, 1829, 1103, + 4367, 1805, 3424, 3592, 1832, 1012, 1013, 3424, 3591, 1128, + 1132, 957, 2473, 2628, 2472, 3089, 1513, 4380, 750, 1510, + 4297, 1530, 4295, 1531, 1532, 4167, 1153, 4117, 1830, 2889, + 136, 3430, 4235, 1068, 3797, 2157, 3430, 750, 3478, 4249, + 4035, 4034, 1201, 3737, 1200, 3797, 3738, 1533, 4336, 4045, + 4292, 3755, 1501, 2700, 3744, 4231, 2585, 2622, 750, 4044, + 2204, 4275, 3504, 745, 3838, 2466, 2925, 1529, 1014, 1015, + 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, + 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, + 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, + 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, + 4239, 730, 2579, 2627, 3754, 91, 2518, 91, 93, 91, + 3360, 3361, 91, 2698, 1512, 3022, 3359, 3124, 3021, 750, + 2697, 3023, 2519, 2520, 728, 3107, 2573, 2129, 2130, 1864, + 2987, 1865, 1275, 1287, 1061, 1060, 4138, 1276, 1316, 1275, + 1292, 1293, 1517, 2082, 1276, 1274, 3034, 1273, 3427, 1551, + 750, 1517, 3447, 3427, 1288, 1281, 103, 3182, 2988, 3456, + 103, 2537, 2536, 3861, 2480, 725, 3486, 4280, 3484, 3454, + 2979, 2980, 3475, 1494, 740, 1552, 1553, 1554, 1555, 1556, + 1557, 1558, 1560, 1559, 1561, 1562, 2691, 4278, 101, 735, + 101, 2128, 101, 764, 1220, 101, 2132, 4285, 4286, 3074, + 751, 738, 768, 2964, 748, 2965, 3109, 3380, 3381, 762, + 3460, 1776, 749, 2433, 4279, 2029, 4087, 1500, 4088, 2604, + 3293, 1511, 2950, 1121, 1820, 2456, 3711, 1308, 3294, 4327, + 1290, 1291, 1493, 3448, 3449, 1313, 751, 4352, 4353, 4354, + 4355, 4356, 4357, 4358, 4359, 4360, 4361, 4362, 4363, 1294, + 4328, 1296, 1315, 1289, 1282, 751, 3457, 1254, 1314, 1295, + 2030, 1527, 2031, 2666, 2275, 2667, 3455, 2668, 2647, 3112, + 1527, 4019, 715, 2645, 717, 731, 751, 753, 1779, 752, + 721, 3639, 719, 723, 732, 724, 2083, 718, 3067, 729, + 3726, 2572, 720, 733, 734, 737, 741, 742, 743, 739, + 736, 3725, 727, 754, 2694, 2454, 2695, 2654, 2650, 2652, + 2653, 2651, 2655, 2656, 2657, 2658, 2644, 2669, 2456, 1226, + 1131, 1125, 1123, 1225, 2648, 2607, 2643, 1156, 3379, 2646, + 3802, 1157, 2496, 1157, 1195, 1194, 1193, 3183, 1192, 1191, + 3382, 1131, 1125, 1123, 1190, 1189, 1188, 751, 1183, 1940, + 1196, 3382, 1140, 4425, 1140, 1320, 1138, 1320, 1320, 1169, + 1205, 1860, 3402, 1140, 1168, 1116, 1168, 3113, 4434, 3062, + 1204, 2478, 2479, 2465, 1523, 2267, 2074, 1515, 751, 2633, + 2269, 2632, 2070, 1523, 2274, 2270, 750, 1502, 2271, 2272, + 2273, 1213, 3631, 2268, 2276, 2277, 2278, 2279, 2280, 2281, + 2282, 2283, 2284, 3297, 3098, 3249, 2949, 1075, 1575, 1580, + 1581, 2463, 1584, 1586, 1587, 1588, 1589, 1590, 101, 1593, + 1594, 1596, 1596, 2462, 1596, 1596, 1601, 1601, 1601, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, - 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1623, 1624, 1625, - 1626, 1627, 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, - 1636, 1637, 1638, 1639, 1640, 1641, 1642, 1643, 1644, 1645, - 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, - 1656, 1657, 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, - 1666, 1667, 1668, 1669, 1670, 1671, 1672, 1673, 1674, 1675, - 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, - 1686, 1687, 1688, 1689, 1690, 1691, 1692, 1693, 1694, 1695, - 1696, 1697, 1698, 1699, 1700, 1702, 1703, 1704, 1705, 1706, - 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1714, 1715, 1716, - 1717, 1723, 1724, 1725, 1726, 1740, 1741, 1742, 1743, 1744, - 1745, 1746, 1747, 1748, 1749, 1750, 1751, 1752, 1753, 4126, - 4076, 4095, 4127, 4124, 4105, 4104, 0, 0, 4101, 0, - 4103, 0, 4141, 3321, 0, 0, 0, 4111, 3321, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 92, 0, 0, 0, 2714, 0, 0, 0, 2719, 4008, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2722, 4143, 2723, 0, 0, 0, 0, 0, 2731, - 4131, 0, 1081, 2733, 2734, 4148, 0, 0, 0, 0, - 4146, 4012, 2740, 2741, 2742, 2743, 2744, 2745, 2746, 2747, - 2748, 2749, 46, 2751, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 92, 0, 0, 2757, 2758, 2759, 2760, - 0, 2762, 2763, 4185, 2765, 4184, 0, 4166, 2767, 0, - 4167, 4201, 2772, 2773, 0, 2774, 0, 0, 2777, 2778, - 2780, 2782, 2783, 2784, 2785, 2786, 2787, 2789, 2791, 2792, - 2793, 2795, 4192, 2797, 2798, 2800, 2802, 2804, 2806, 2808, - 2810, 2812, 2814, 2816, 2818, 2820, 2822, 2824, 2826, 2828, - 2830, 2832, 2834, 2835, 2836, 46, 2838, 4230, 2840, 4206, - 2842, 2843, 4191, 2845, 2847, 2849, 4176, 0, 92, 2852, - 4216, 4128, 4195, 2856, 4032, 4219, 4215, 2861, 2862, 2863, - 2864, 4209, 4214, 4211, 4210, 1766, 4208, 4213, 4212, 0, - 2875, 2876, 2877, 2878, 2879, 2880, 0, 4238, 2884, 2885, - 3321, 0, 0, 0, 4256, 2887, 0, 4255, 0, 0, - 2893, 0, 0, 0, 0, 2896, 2897, 2898, 2899, 2900, - 4268, 4296, 4230, 4273, 4260, 92, 2907, 2908, 4285, 2909, - 46, 0, 2912, 2914, 2449, 4298, 2916, 4283, 0, 0, - 0, 4155, 0, 0, 0, 0, 2928, 4197, 0, 4165, - 3318, 0, 4295, 0, 0, 4202, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4300, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2962, 0, - 92, 4311, 0, 0, 0, 0, 0, 46, 0, 0, - 0, 4337, 2077, 4326, 0, 4327, 0, 4361, 0, 4330, - 2199, 0, 2197, 0, 0, 4336, 0, 0, 0, 0, - 0, 4133, 4356, 1766, 0, 4358, 4360, 4362, 92, 4364, - 4381, 0, 0, 0, 4230, 0, 0, 0, 4298, 0, - 4371, 0, 0, 0, 3436, 0, 3435, 3432, 0, 0, - 4392, 4382, 46, 0, 4151, 0, 0, 0, 0, 0, - 0, 0, 4291, 0, 0, 0, 0, 4396, 4139, 4404, - 0, 4402, 0, 0, 92, 4409, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4412, 0, 0, 0, - 46, 0, 0, 0, 0, 0, 0, 0, 4415, 92, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 4421, 4425, 92, 92, 2199, 0, 2197, 4429, 92, 4428, - 4430, 4072, 4298, 4424, 4427, 0, 0, 0, 4298, 0, - 0, 0, 0, 0, 0, 0, 46, 0, 0, 0, - 0, 0, 0, 0, 4196, 0, 0, 198, 0, 0, + 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, + 1625, 1626, 1627, 1628, 1629, 1630, 1631, 1632, 1633, 1634, + 1635, 1636, 1637, 1638, 1639, 1640, 1641, 1642, 1643, 1644, + 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, + 1655, 1656, 1657, 1658, 1659, 1660, 1661, 1662, 1663, 1664, + 1665, 1666, 1667, 1668, 1669, 1670, 1671, 1672, 1673, 1674, + 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1684, + 1685, 1686, 1687, 1688, 1689, 1690, 1691, 1692, 1693, 1694, + 1695, 1696, 1697, 1698, 1699, 1700, 1701, 1702, 1703, 1704, + 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1714, + 1715, 1716, 1717, 1718, 1719, 1720, 1721, 1722, 1723, 1724, + 1725, 1726, 1727, 1585, 1576, 1260, 1828, 1728, 1490, 1730, + 1731, 1732, 1733, 1734, 1309, 4144, 3065, 1568, 1569, 1570, + 1571, 1601, 1601, 1601, 1601, 1601, 1601, 1582, 3576, 1572, + 4237, 1491, 1492, 4190, 2962, 1154, 1741, 1742, 1743, 1744, + 1745, 1746, 1747, 1748, 1749, 1750, 1751, 1752, 1753, 1754, + 3036, 755, 3840, 3839, 3640, 94, 1861, 3068, 2626, 1252, + 3088, 750, 1175, 4409, 751, 3722, 1186, 3476, 4236, 1184, + 1124, 1175, 746, 1271, 4150, 1277, 1278, 1279, 1280, 2041, + 2040, 2042, 2043, 2044, 3687, 3688, 3690, 747, 2576, 2699, + 3796, 1124, 3753, 1597, 1212, 1598, 1599, 3428, 3429, 1317, + 1318, 3796, 3428, 3429, 2461, 2698, 2480, 1565, 3087, 1961, + 3432, 1081, 1565, 3084, 2457, 3432, 2071, 1769, 3116, 1266, + 1602, 1603, 705, 1775, 4310, 2929, 2931, 1272, 1175, 2577, + 4398, 1250, 1075, 1258, 1259, 4309, 1075, 2575, 4422, 4290, + 1765, 4133, 1075, 1522, 1519, 1520, 1521, 1526, 1528, 1525, + 3258, 1524, 1522, 1519, 1520, 1521, 1526, 1528, 1525, 1509, + 1524, 1518, 1285, 1566, 1567, 100, 1262, 100, 2058, 100, + 1518, 2578, 100, 1261, 3678, 2624, 3106, 1174, 4284, 3105, + 3660, 1081, 3018, 2982, 2901, 2574, 1174, 2207, 1851, 1729, + 1263, 1766, 3721, 1265, 1175, 3257, 2977, 713, 132, 2525, + 1565, 1562, 3358, 2248, 3129, 1805, 1783, 92, 1533, 2715, + 1787, 1298, 91, 48, 49, 93, 1074, 1175, 1823, 3277, + 2249, 4282, 1252, 2726, 1545, 2059, 4283, 2087, 3275, 1187, + 1960, 98, 1185, 1250, 1244, 52, 81, 82, 1785, 79, + 83, 1786, 111, 1174, 1530, 112, 1531, 1532, 1532, 1531, + 1532, 80, 1081, 4430, 1934, 1093, 1304, 3366, 1306, 1270, + 1312, 1766, 4401, 103, 1735, 1736, 1737, 1738, 1739, 1740, + 1533, 1533, 1781, 1533, 4428, 1937, 1938, 1939, 1773, 4158, + 1198, 46, 1816, 67, 3717, 1819, 4265, 2175, 3119, 751, + 4305, 2726, 1827, 3118, 114, 101, 4421, 1303, 1305, 1248, + 3652, 3119, 2176, 1563, 1564, 2174, 3118, 4407, 3367, 1174, + 4408, 2930, 4406, 2478, 2479, 1168, 1171, 1172, 2467, 1140, + 1953, 126, 2141, 1165, 1169, 2055, 1807, 2056, 4342, 1805, + 2057, 2067, 1174, 3369, 1211, 1249, 1866, 1770, 1208, 1767, + 2024, 1784, 2014, 2015, 2762, 88, 3156, 1946, 2020, 2021, + 1071, 1963, 1963, 3364, 4388, 2080, 2240, 4416, 1810, 1822, + 1965, 2246, 1788, 1812, 2006, 1073, 4337, 1975, 1320, 1976, + 1299, 1978, 1980, 3380, 3381, 1984, 1986, 1988, 1990, 1992, + 3365, 1817, 1175, 1967, 2623, 1530, 2088, 1531, 1532, 2616, + 1284, 1857, 1858, 2960, 3856, 1964, 1250, 1782, 1813, 1253, + 127, 1286, 1926, 3695, 3694, 1815, 1814, 2621, 1301, 1247, + 2002, 1533, 1302, 2005, 1269, 2007, 3371, 2240, 2611, 2735, + 1970, 1969, 1307, 1959, 1944, 2619, 1186, 1184, 4329, 1956, + 1943, 1942, 2620, 2163, 2164, 2705, 2706, 1249, 4426, 3679, + 4201, 2616, 95, 59, 62, 61, 64, 4125, 78, 1820, + 2054, 87, 84, 101, 4197, 1263, 4340, 1805, 2063, 1300, + 2061, 2062, 2060, 2064, 2065, 2066, 1175, 2049, 1175, 1530, + 4196, 1531, 1532, 2173, 1088, 2010, 1557, 1558, 1560, 1559, + 1561, 1562, 2075, 2076, 2618, 4198, 66, 97, 96, 4202, + 1805, 76, 77, 63, 3379, 1533, 4126, 1174, 2245, 85, + 86, 4245, 1805, 1168, 1171, 1172, 3382, 1140, 1009, 1010, + 1011, 1165, 1169, 1530, 2047, 1531, 1532, 3750, 4411, 3751, + 1151, 4331, 1150, 136, 1149, 1555, 1556, 1557, 1558, 1560, + 1559, 1561, 1562, 1164, 4427, 4027, 4026, 4017, 2048, 1533, + 2093, 3767, 3766, 4195, 69, 3702, 70, 71, 72, 73, + 1320, 1320, 3701, 2089, 2090, 4243, 1805, 3691, 1530, 3405, + 1531, 1532, 3398, 3044, 2115, 3043, 92, 2094, 3042, 92, + 4241, 1805, 2582, 2036, 2101, 2102, 2103, 2050, 198, 1100, + 2731, 1174, 2034, 1174, 1533, 2046, 1178, 1168, 1178, 1168, + 2033, 1180, 2114, 1180, 2032, 1181, 1179, 1181, 1179, 2022, + 1249, 137, 4100, 1805, 2016, 2013, 2163, 2164, 2161, 2162, + 65, 2231, 1530, 2137, 1531, 1532, 2137, 180, 3136, 1182, + 2012, 2011, 4098, 1805, 1982, 1780, 3305, 1530, 3368, 1531, + 1532, 2202, 2202, 2160, 2200, 2200, 2203, 1496, 1533, 2091, + 46, 1100, 756, 46, 2035, 2393, 2095, 1860, 2097, 2098, + 2099, 2100, 4365, 1533, 2395, 2104, 1094, 4330, 2730, 1530, + 1805, 1531, 1532, 3027, 1095, 1099, 1100, 2116, 1551, 4153, + 1004, 1547, 3684, 1548, 756, 4152, 3025, 177, 756, 1530, + 178, 1531, 1532, 4129, 2165, 1533, 1936, 4378, 1549, 1563, + 1564, 1546, 1081, 4128, 1552, 1553, 1554, 1555, 1556, 1557, + 1558, 1560, 1559, 1561, 1562, 1533, 197, 4127, 1099, 1100, + 4317, 1805, 94, 3138, 2286, 1530, 4022, 1531, 1532, 1936, + 1805, 1765, 2223, 2212, 2213, 2214, 2215, 2225, 2216, 2217, + 2218, 2230, 2226, 2219, 2220, 2227, 2228, 2229, 2221, 2222, + 2224, 1533, 2592, 4007, 2591, 4095, 1805, 3651, 2590, 2178, + 2589, 2180, 2181, 2182, 2183, 2184, 2185, 2187, 2189, 2190, + 2191, 2192, 2193, 2194, 2140, 2138, 2142, 2140, 2138, 2235, + 2139, 4006, 1766, 2139, 2122, 2123, 2179, 1529, 1805, 2172, + 4077, 1805, 1576, 1530, 3855, 1531, 1532, 3148, 3147, 3146, + 3853, 2588, 3140, 2587, 3144, 3763, 3139, 1764, 3137, 2392, + 2241, 2177, 1530, 3142, 1531, 1532, 2774, 3617, 1805, 1533, + 1763, 1834, 3141, 1936, 4230, 110, 1529, 1805, 1551, 2405, + 3128, 2404, 100, 1762, 2310, 1805, 4146, 2206, 1533, 1593, + 2403, 3143, 3145, 181, 1936, 4211, 2302, 1530, 2722, 1531, + 1532, 3699, 187, 3683, 1552, 1553, 1554, 1555, 1556, 1557, + 1558, 1560, 1559, 1561, 1562, 2250, 2251, 2252, 2253, 1530, + 1835, 1531, 1532, 1533, 1530, 2394, 1531, 1532, 4307, 2264, + 1551, 1936, 4207, 2285, 3610, 1805, 4107, 1805, 3735, 4143, + 1805, 1530, 3372, 1531, 1532, 1533, 3376, 4030, 1805, 2471, + 1533, 1936, 4018, 2776, 3375, 1804, 1552, 1553, 1554, 1555, + 1556, 1557, 1558, 1560, 1559, 1561, 1562, 1533, 4054, 2402, + 3461, 3458, 2408, 2409, 3735, 1805, 108, 3401, 2504, 3400, + 1767, 3110, 110, 3607, 1805, 4053, 109, 3053, 3377, 111, + 3040, 1530, 112, 1531, 1532, 1936, 3733, 3373, 2616, 1805, + 75, 2405, 3374, 2492, 1761, 2724, 3658, 1805, 3605, 1805, + 4011, 111, 2403, 1755, 112, 2723, 2438, 1533, 2534, 108, + 117, 2688, 2171, 1530, 2451, 1531, 1532, 2300, 1551, 109, + 2714, 116, 172, 115, 2856, 1805, 3568, 1805, 3391, 3390, + 1530, 1098, 1531, 1532, 3388, 3389, 2444, 1805, 2445, 1533, + 2680, 1145, 2506, 2679, 1552, 1553, 1554, 1555, 1556, 1557, + 1558, 1560, 1559, 1561, 1562, 1530, 1533, 1531, 1532, 2638, + 2486, 2487, 1530, 2426, 1531, 1532, 2459, 3386, 3387, 1145, + 2544, 2545, 2546, 1089, 3386, 3385, 2993, 1805, 4010, 2529, + 1805, 1533, 2528, 1530, 2637, 1531, 1532, 2475, 1533, 2439, + 2510, 2452, 2698, 3097, 1930, 3078, 1805, 2383, 2384, 2385, + 2386, 2387, 3071, 3072, 3637, 2458, 2205, 1805, 3075, 1533, + 2118, 2468, 3014, 2084, 2407, 3566, 1805, 2410, 2411, 3562, + 1805, 2565, 2532, 2045, 2037, 3014, 2605, 2538, 2481, 2539, + 2540, 2541, 2542, 2543, 2571, 2027, 2490, 2547, 2023, 2019, + 2018, 2017, 1836, 2549, 1310, 1129, 2551, 2552, 2553, 2554, + 2516, 2515, 3058, 2428, 2533, 2514, 2531, 2530, 1529, 2602, + 1553, 1554, 1555, 1556, 1557, 1558, 1560, 1559, 1561, 1562, + 2581, 1130, 1530, 3323, 1531, 1532, 1530, 4185, 1531, 1532, + 3015, 1177, 3353, 1530, 3651, 1531, 1532, 1551, 3559, 1805, + 3017, 1963, 2698, 3015, 1936, 1935, 2610, 2947, 1533, 2613, + 4157, 2614, 1533, 2698, 2562, 2566, 2555, 2557, 2558, 1533, + 2580, 110, 2630, 1552, 1553, 1554, 1555, 1556, 1557, 1558, + 1560, 1559, 1561, 1562, 1551, 117, 1930, 1929, 1872, 1871, + 3655, 2608, 2609, 1176, 2612, 2566, 116, 2617, 115, 2634, + 2984, 2631, 2984, 2635, 2636, 1530, 110, 1531, 1532, 4332, + 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1560, 1559, 1561, + 1562, 3557, 1805, 116, 2992, 1076, 1936, 4121, 2703, 3555, + 1805, 1533, 2993, 173, 2642, 2945, 3596, 1075, 1075, 1075, + 185, 3553, 1805, 3388, 2641, 1552, 1553, 1554, 1555, 1556, + 1557, 1558, 1560, 1559, 1561, 1562, 3703, 1586, 3654, 1586, + 3280, 2616, 2517, 3551, 1805, 1530, 2856, 1531, 1532, 2759, + 1998, 1805, 198, 3549, 1805, 2718, 103, 2993, 1530, 3651, + 1531, 1532, 193, 2758, 1839, 2993, 1530, 2616, 1531, 1532, + 1530, 1533, 1531, 1532, 2599, 137, 2484, 1529, 1530, 3158, + 1531, 1532, 2470, 2672, 1533, 1821, 2429, 2405, 101, 2404, + 2205, 180, 1533, 3704, 3705, 3706, 1533, 2143, 2721, 2127, + 1530, 2069, 1531, 1532, 1533, 3547, 1805, 1999, 2000, 2001, + 1530, 1859, 1531, 1532, 1837, 174, 179, 176, 182, 183, + 184, 186, 188, 189, 190, 191, 1533, 3545, 1805, 1159, + 1158, 192, 194, 195, 196, 1838, 1533, 101, 2690, 3543, + 1805, 4288, 4213, 3408, 3541, 1805, 2231, 3453, 3539, 1805, + 4041, 177, 4008, 2696, 178, 3050, 3537, 1805, 3868, 1252, + 3535, 1805, 1530, 130, 1531, 1532, 2711, 3716, 2713, 2704, + 3713, 3697, 4042, 3533, 1805, 3493, 3509, 2716, 3508, 2717, + 197, 2710, 1932, 2564, 1530, 3410, 1531, 1532, 1533, 2707, + 2708, 2709, 1530, 2712, 1531, 1532, 1530, 2172, 1531, 1532, + 3406, 1530, 2719, 1531, 1532, 1530, 3303, 1531, 1532, 3079, + 1533, 2561, 2556, 1530, 2550, 1531, 1532, 1530, 1533, 1531, + 1532, 2548, 1533, 3531, 1805, 2052, 1958, 1533, 3529, 1805, + 1530, 1533, 1531, 1532, 3515, 1805, 1954, 2682, 2683, 1533, + 1928, 2734, 2685, 1533, 2579, 128, 1805, 3049, 3665, 3666, + 2442, 2686, 4373, 4371, 2900, 4324, 1533, 2223, 2212, 2213, + 2214, 2215, 2225, 2216, 2217, 2218, 2230, 2226, 2219, 2220, + 2227, 2228, 2229, 2221, 2222, 2224, 3707, 3491, 1805, 4165, + 1530, 4082, 1531, 1532, 4049, 1530, 2932, 1531, 1532, 2120, + 3668, 1530, 3636, 1531, 1532, 2202, 1994, 2770, 2200, 2935, + 3635, 3050, 1530, 3634, 1531, 1532, 1533, 181, 3323, 2921, + 1805, 1533, 3298, 2919, 1805, 710, 187, 1533, 2894, 1805, + 1075, 2673, 2871, 1805, 3671, 3670, 2863, 1805, 1533, 3708, + 3709, 3710, 1833, 3342, 1530, 3345, 1531, 1532, 2933, 3341, + 3346, 1530, 4161, 1531, 1532, 4315, 2990, 2991, 4142, 1995, + 1996, 1997, 3343, 2854, 1805, 2504, 2121, 3344, 1075, 3010, + 1533, 4043, 2474, 2448, 2852, 1805, 1530, 1533, 1531, 1532, + 1530, 2741, 1531, 1532, 2936, 1530, 2938, 1531, 1532, 1530, + 2171, 1531, 1532, 1530, 3659, 1531, 1532, 2888, 2756, 1091, + 2772, 1081, 1533, 2989, 773, 3347, 1533, 3002, 3003, 2969, + 1081, 1533, 3312, 3314, 1530, 1533, 1531, 1532, 3285, 1533, + 1530, 3315, 1531, 1532, 3284, 2839, 1805, 3644, 4124, 2953, + 46, 1530, 3846, 1531, 1532, 3643, 3848, 2837, 1805, 3007, + 1533, 2985, 3009, 3647, 2923, 3008, 1533, 1773, 2978, 3822, + 1092, 3821, 3309, 2835, 1805, 2068, 172, 1533, 1059, 3384, + 3032, 3054, 2952, 2948, 2665, 2943, 2951, 2664, 2833, 1805, + 1215, 2663, 2248, 3035, 3037, 1827, 2967, 3038, 3083, 1805, + 2662, 2981, 1530, 2661, 1531, 1532, 2831, 1805, 3028, 2249, + 1766, 3012, 2660, 2659, 1530, 3052, 1531, 1532, 2829, 1805, + 3055, 3056, 2966, 1108, 3820, 2827, 1805, 3016, 1533, 1214, + 1530, 3019, 1531, 1532, 2825, 1805, 108, 1107, 3094, 3026, + 1533, 108, 110, 3673, 2571, 1530, 109, 1531, 1532, 3029, + 3469, 109, 3049, 2823, 1805, 1530, 1533, 1531, 1532, 2168, + 2166, 2167, 3041, 1530, 3612, 1531, 1532, 3122, 4313, 1495, + 4347, 1533, 2821, 1805, 3085, 1530, 137, 1531, 1532, 3649, + 3051, 1533, 1530, 110, 1531, 1532, 2819, 1805, 4403, 1533, + 3302, 1530, 3059, 1531, 1532, 2486, 2487, 2817, 1805, 2676, + 1530, 1533, 1531, 1532, 3091, 2815, 1805, 1946, 1533, 117, + 1530, 4248, 1531, 1532, 4037, 4349, 3383, 1533, 3080, 3081, + 116, 1530, 115, 1531, 1532, 2428, 1533, 3132, 3133, 1530, + 110, 1531, 1532, 2813, 1805, 3090, 1533, 3006, 2469, 1146, + 4348, 3283, 3619, 1530, 2702, 1531, 1532, 1533, 115, 3282, + 2811, 1805, 2126, 4106, 1530, 1533, 1531, 1532, 4105, 3092, + 2125, 4085, 1530, 3854, 1531, 1532, 3111, 3852, 3851, 1533, + 3833, 2809, 1805, 3149, 3114, 3714, 3648, 3646, 2807, 1805, + 1533, 3411, 3130, 2805, 1805, 2600, 1941, 1106, 1533, 3608, + 1530, 116, 1531, 1532, 3832, 3629, 3574, 3167, 3168, 3169, + 3170, 3171, 3172, 3173, 3174, 3175, 3176, 1530, 2984, 1531, + 1532, 117, 3806, 4375, 4374, 4374, 1533, 3184, 2800, 1805, + 2947, 3186, 116, 3150, 4014, 2760, 2440, 173, 1530, 3718, + 1531, 1532, 1853, 1533, 185, 1530, 1852, 1531, 1532, 3134, + 1530, 1844, 1531, 1532, 1843, 4375, 1530, 3151, 1531, 1532, + 121, 122, 117, 1530, 1533, 1531, 1532, 2796, 1805, 4130, + 3682, 1533, 3131, 116, 3, 115, 1533, 2794, 1805, 4194, + 3244, 105, 1533, 3188, 8, 1530, 193, 1531, 1532, 1533, + 1530, 3120, 1531, 1532, 3121, 1530, 5, 1531, 1532, 1, + 2392, 1067, 2392, 1498, 1761, 1806, 1808, 1497, 3686, 1759, + 4277, 1533, 2787, 1805, 1757, 726, 1533, 1758, 1756, 2430, + 1760, 1533, 3070, 3570, 1530, 1771, 1531, 1532, 4325, 4273, + 4274, 2038, 3262, 3253, 1530, 2028, 1531, 1532, 2504, 174, + 179, 176, 182, 183, 184, 186, 188, 189, 190, 191, + 1533, 3745, 2357, 4038, 3177, 192, 194, 195, 196, 3834, + 1533, 3045, 3835, 3837, 3224, 3506, 2394, 1896, 2394, 1530, + 3414, 1531, 1532, 2606, 3712, 2569, 1167, 162, 2526, 3330, + 1530, 92, 1531, 1532, 2504, 2504, 2504, 2504, 2504, 2527, + 4225, 3152, 125, 1133, 3252, 1533, 3254, 3234, 3235, 3236, + 3237, 3238, 124, 1170, 2504, 1283, 1533, 2504, 2601, 3736, + 3033, 3261, 2506, 3262, 2535, 1878, 1876, 1530, 3289, 1531, + 1532, 3287, 1530, 1877, 1531, 1532, 1081, 1875, 1936, 3251, + 1880, 1879, 4189, 3273, 3477, 2761, 3575, 2131, 2080, 3274, + 3276, 3278, 3335, 1533, 3286, 3352, 3279, 763, 1533, 3288, + 3005, 757, 3296, 200, 1867, 1078, 1845, 2124, 2506, 2506, + 2506, 2506, 2506, 3299, 3300, 3301, 1209, 3431, 716, 3392, + 2639, 3505, 3316, 3317, 722, 1583, 2119, 3439, 2506, 3281, + 3020, 2506, 1127, 1119, 3354, 1096, 2441, 3355, 1080, 3336, + 2937, 3444, 3339, 1126, 3443, 3440, 4015, 3337, 3338, 3348, + 3340, 111, 3396, 3397, 112, 3334, 1079, 3331, 3641, 3497, + 3356, 3308, 3310, 2971, 3313, 3319, 3306, 3321, 3362, 2785, + 1805, 4123, 3845, 3226, 3326, 3228, 1883, 3495, 1530, 3326, + 1531, 1532, 4346, 4212, 3393, 3030, 3395, 3394, 1840, 2917, + 3595, 3239, 3240, 3241, 3242, 2733, 2238, 1573, 2916, 788, + 2503, 959, 1825, 3801, 1533, 2912, 2158, 786, 3412, 785, + 2911, 783, 2939, 2571, 3433, 2986, 1530, 1537, 1531, 1532, + 1536, 994, 2927, 3450, 1854, 2910, 1530, 2997, 1531, 1532, + 2909, 2995, 2994, 2674, 1530, 2511, 1531, 1532, 2908, 3667, + 3663, 3462, 1533, 4269, 3465, 3464, 1530, 2907, 1531, 1532, + 2505, 2501, 1533, 2946, 945, 1530, 3472, 1531, 1532, 944, + 1533, 3413, 1530, 795, 1531, 1532, 3482, 1530, 787, 1531, + 1532, 1897, 1533, 3498, 3499, 3500, 3501, 3502, 777, 1008, + 943, 1533, 1530, 942, 1531, 1532, 3441, 1530, 1533, 1531, + 1532, 3442, 2961, 1533, 1818, 1530, 1586, 1531, 1532, 4314, + 1586, 3304, 2963, 3031, 1530, 3292, 1531, 1532, 1533, 1514, + 1790, 1793, 2449, 1533, 3479, 3480, 3620, 3481, 3622, 1811, + 3483, 1533, 3485, 3474, 3487, 4148, 2701, 3503, 1789, 2898, + 1533, 3630, 4155, 2897, 3422, 3730, 3473, 1910, 1913, 1914, + 1915, 1916, 1917, 1918, 3403, 1919, 1920, 1922, 1923, 1921, + 1924, 1925, 1898, 1899, 1900, 1901, 1881, 1882, 1911, 3076, + 1884, 2593, 1885, 1886, 1887, 1888, 1889, 1890, 1891, 1892, + 1893, 2896, 74, 1894, 1902, 1903, 1904, 1905, 50, 1906, + 1907, 1908, 1909, 4115, 3329, 1895, 1530, 2895, 1531, 1532, + 1530, 4186, 1531, 1532, 2504, 937, 934, 3803, 3804, 3805, + 3247, 3621, 3248, 3623, 3625, 4168, 2892, 3680, 4169, 933, + 4170, 2295, 1533, 3627, 1508, 1505, 1533, 3060, 2133, 104, + 40, 3444, 39, 38, 3443, 3440, 2887, 3681, 1530, 3638, + 1531, 1532, 3645, 2880, 3590, 37, 3597, 2879, 3599, 3600, + 3601, 3594, 36, 3650, 1530, 2878, 1531, 1532, 30, 29, + 28, 3434, 27, 2877, 1533, 26, 33, 3669, 3467, 3468, + 23, 3672, 3662, 1530, 2876, 1531, 1532, 25, 2506, 3674, + 1533, 24, 2243, 22, 3675, 4385, 4386, 2244, 4415, 3692, + 3693, 3676, 3677, 1530, 2875, 1531, 1532, 4251, 4191, 1533, + 1530, 2874, 1531, 1532, 1530, 2873, 1531, 1532, 3425, 3698, + 2872, 3700, 1530, 4320, 1531, 1532, 4402, 131, 4351, 1533, + 1530, 4312, 1531, 1532, 4311, 2306, 1533, 4262, 4391, 4257, + 1533, 1530, 2866, 1531, 1532, 60, 57, 3723, 1533, 2865, + 55, 3727, 3728, 3729, 139, 138, 1533, 58, 56, 2864, + 54, 1530, 53, 1531, 1532, 1255, 51, 1533, 1530, 2861, + 1531, 1532, 1530, 102, 1531, 1532, 2860, 1530, 35, 1531, + 1532, 3740, 3741, 3742, 34, 21, 20, 1533, 19, 2859, + 18, 17, 16, 15, 1533, 11, 10, 2857, 1533, 1530, + 43, 1531, 1532, 1533, 42, 41, 1530, 32, 1531, 1532, + 2850, 31, 44, 7, 3757, 2389, 1530, 2847, 1531, 1532, + 2, 3063, 1912, 2595, 0, 1533, 1530, 0, 1531, 1532, + 0, 0, 1533, 1530, 0, 1531, 1532, 0, 2845, 0, + 0, 3768, 1533, 0, 0, 2420, 1530, 0, 1531, 1532, + 2843, 0, 1533, 0, 1530, 0, 1531, 1532, 0, 1533, + 0, 0, 1806, 2427, 1767, 2802, 0, 1530, 0, 1531, + 1532, 0, 1533, 0, 1530, 2782, 1531, 1532, 0, 3819, + 1533, 0, 3826, 0, 3828, 0, 0, 2781, 3809, 0, + 3810, 3811, 3812, 1533, 0, 1530, 0, 1531, 1532, 0, + 1533, 0, 2777, 2453, 0, 3762, 3799, 1530, 0, 1531, + 1532, 0, 0, 0, 2775, 3330, 0, 0, 92, 0, + 3330, 1533, 1530, 0, 1531, 1532, 0, 2767, 3829, 0, + 0, 2738, 1530, 1533, 1531, 1532, 2732, 0, 2202, 0, + 0, 2200, 3870, 0, 1530, 0, 1531, 1532, 1533, 0, + 0, 0, 2727, 0, 0, 3830, 0, 0, 1533, 1530, + 0, 1531, 1532, 1081, 0, 3862, 3860, 0, 3850, 3849, + 1533, 1530, 0, 1531, 1532, 0, 0, 3857, 0, 3859, + 0, 0, 0, 4021, 1530, 1533, 1531, 1532, 1530, 0, + 1531, 1532, 46, 1530, 0, 1531, 1532, 1533, 0, 0, + 0, 0, 3719, 3720, 0, 0, 3874, 0, 0, 1530, + 1533, 1531, 1532, 0, 1533, 0, 0, 0, 0, 1533, + 0, 3871, 3872, 0, 0, 0, 4013, 0, 0, 2583, + 0, 0, 0, 0, 4012, 1533, 0, 0, 0, 0, + 4028, 0, 0, 0, 0, 4040, 4032, 4023, 4024, 4025, + 0, 1795, 0, 0, 0, 4079, 4080, 4033, 3326, 0, + 0, 0, 0, 2202, 0, 1803, 2200, 4083, 1796, 3864, + 0, 0, 0, 0, 0, 3827, 1539, 1540, 1541, 1542, + 1543, 1544, 1538, 1535, 2998, 3001, 3002, 3003, 2999, 0, + 3000, 3004, 0, 2446, 2447, 1802, 1800, 1801, 1797, 0, + 1798, 0, 0, 0, 3790, 2998, 3001, 3002, 3003, 2999, + 0, 3000, 3004, 4086, 0, 3665, 3666, 4089, 0, 0, + 0, 4131, 3330, 1799, 0, 0, 0, 0, 0, 0, + 3866, 0, 0, 0, 0, 0, 1604, 1605, 1606, 1607, + 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, + 1618, 1619, 1620, 1621, 1622, 1624, 1625, 1626, 1627, 1628, + 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, + 1639, 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1648, + 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1658, + 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, + 1669, 1670, 1671, 1672, 1673, 1674, 1675, 1676, 1677, 1678, + 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686, 1687, 1688, + 1689, 1690, 1691, 1692, 1693, 1694, 1695, 1696, 1697, 1698, + 1699, 1700, 1701, 1703, 1704, 1705, 1706, 1707, 1708, 1709, + 1710, 1711, 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1724, + 1725, 1726, 1727, 1741, 1742, 1743, 1744, 1745, 1746, 1747, + 1748, 1749, 1750, 1751, 1752, 1753, 1754, 4134, 4135, 4084, + 3329, 4132, 4103, 4113, 4112, 3329, 1795, 0, 0, 4109, + 4149, 4111, 0, 0, 0, 0, 0, 0, 0, 0, + 1803, 0, 0, 1796, 0, 0, 0, 0, 92, 0, + 0, 0, 2720, 0, 0, 0, 2725, 0, 4016, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1791, 1792, + 1802, 1800, 1801, 1797, 0, 1798, 0, 0, 0, 2728, + 0, 2729, 0, 4154, 4151, 0, 0, 2737, 4020, 4139, + 0, 2739, 2740, 1081, 0, 4156, 0, 0, 1799, 0, + 2746, 2747, 2748, 2749, 2750, 2751, 2752, 2753, 2754, 2755, + 0, 2757, 0, 0, 0, 0, 0, 4119, 0, 0, + 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, + 0, 92, 0, 0, 2763, 2764, 2765, 2766, 0, 2768, + 2769, 4193, 2771, 0, 4192, 0, 2773, 0, 0, 4209, + 2778, 2779, 0, 2780, 0, 0, 2783, 2784, 2786, 2788, + 2789, 2790, 2791, 2792, 2793, 2795, 2797, 2798, 2799, 2801, + 4200, 2803, 2804, 2806, 2808, 2810, 2812, 2814, 2816, 2818, + 2820, 2822, 2824, 2826, 2828, 2830, 2832, 2834, 2836, 2838, + 2840, 2841, 2842, 775, 2844, 4238, 2846, 4214, 2848, 2849, + 4203, 2851, 2853, 2855, 4199, 46, 92, 2858, 4040, 4227, + 4136, 2862, 4224, 4223, 4217, 2867, 2868, 2869, 2870, 4222, + 4219, 4218, 4216, 4221, 4220, 4184, 0, 3329, 2881, 2882, + 2883, 2884, 2885, 2886, 0, 4246, 2890, 2891, 0, 0, + 0, 0, 4264, 2893, 4174, 4263, 0, 4175, 2899, 0, + 0, 0, 0, 2902, 2903, 2904, 2905, 2906, 4276, 4304, + 4238, 4281, 4268, 92, 2913, 2914, 0, 2915, 4293, 0, + 2918, 2920, 2453, 4306, 2922, 4291, 0, 0, 0, 0, + 46, 0, 0, 0, 2934, 4205, 4303, 3326, 0, 0, + 0, 4210, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4308, 1767, 0, 0, 0, 1105, + 0, 0, 1111, 1111, 0, 0, 0, 2968, 92, 4319, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4345, + 2080, 0, 4334, 0, 4335, 2202, 0, 46, 2200, 4369, + 4338, 0, 4344, 0, 0, 0, 0, 0, 0, 4364, + 4141, 0, 0, 4368, 4366, 4372, 92, 4370, 4389, 0, + 0, 4163, 4238, 0, 0, 0, 4306, 0, 0, 4173, + 4379, 0, 3444, 0, 0, 3443, 3440, 0, 4390, 4400, + 0, 0, 0, 4159, 0, 4147, 0, 0, 0, 0, + 4299, 0, 46, 0, 0, 0, 4404, 0, 4412, 0, + 0, 4410, 92, 4417, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4420, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4423, 92, 0, 0, + 46, 0, 0, 1767, 0, 0, 0, 0, 4429, 2202, + 92, 92, 2200, 4433, 4432, 4437, 92, 4436, 4438, 4080, + 4306, 0, 4435, 0, 0, 0, 4306, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4204, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 46, 0, 0, 0, 0, 0, 0, 0, 0, - 137, 0, 159, 0, 46, 46, 0, 0, 0, 0, - 46, 0, 0, 0, 0, 0, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 46, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 46, 46, 0, 0, 0, 198, + 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4256, + 0, 0, 137, 0, 159, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 180, 1057, + 0, 0, 4318, 0, 995, 1058, 1009, 1010, 1011, 996, + 0, 1896, 997, 998, 0, 999, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3162, 3163, 3164, + 3165, 3166, 170, 1012, 1013, 0, 0, 0, 158, 0, + 0, 0, 0, 0, 0, 0, 0, 3181, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 177, 0, + 0, 178, 0, 0, 0, 0, 0, 0, 0, 0, + 4333, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 146, 147, 169, 168, 197, 0, 0, + 0, 0, 0, 0, 0, 0, 1014, 1015, 1016, 1017, + 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, + 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, + 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, + 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 4239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 4248, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 170, 0, 0, 0, 0, 1893, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 177, 0, 0, 178, - 0, 0, 0, 0, 0, 0, 3155, 3156, 3157, 3158, - 3159, 0, 0, 0, 0, 0, 0, 0, 0, 1773, - 0, 146, 147, 169, 168, 197, 3174, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1933, 0, 0, 775, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4325, 0, 0, 0, 0, 0, 0, 0, 0, + 1883, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 198, 0, + 3447, 163, 144, 166, 151, 143, 0, 164, 165, 3069, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 137, 0, 159, 181, 0, 0, 0, 0, 0, + 0, 0, 0, 187, 152, 0, 0, 180, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, + 153, 148, 149, 150, 154, 0, 0, 0, 0, 0, + 0, 145, 0, 0, 0, 0, 0, 0, 0, 0, + 156, 170, 0, 0, 0, 1897, 0, 158, 0, 0, + 0, 3448, 3449, 0, 0, 0, 3332, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 177, 0, 0, + 178, 0, 0, 0, 3350, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 708, 0, 0, 0, 0, 0, 0, + 0, 0, 1949, 1950, 169, 168, 197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1062, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 198, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3062, 0, 0, 163, - 144, 166, 151, 143, 1880, 164, 165, 0, 137, 0, - 159, 0, 0, 0, 0, 0, 0, 1140, 0, 0, - 0, 0, 181, 0, 180, 1105, 0, 0, 1111, 1111, - 0, 187, 152, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 155, 153, 148, - 149, 150, 154, 0, 0, 0, 0, 0, 170, 145, - 0, 0, 0, 0, 158, 0, 0, 0, 156, 0, + 0, 1910, 1913, 1914, 1915, 1916, 1917, 1918, 0, 1919, + 1920, 1922, 1923, 1921, 1924, 1925, 1898, 1899, 1900, 1901, + 1881, 1882, 1911, 172, 1884, 0, 1885, 1886, 1887, 1888, + 1889, 1890, 1891, 1892, 1893, 0, 0, 1894, 1902, 1903, + 1904, 1905, 0, 1906, 1907, 1908, 1909, 0, 0, 1895, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 177, 0, 0, 178, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1894, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1946, - 1947, 169, 168, 197, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3342, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 172, 0, 0, 0, 1907, 1910, 1911, 1912, 1913, - 1914, 1915, 0, 1916, 1917, 1919, 1920, 1918, 1921, 1922, - 1895, 1896, 1897, 1898, 1878, 1879, 1908, 0, 1881, 0, - 1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 0, - 0, 1891, 1899, 1900, 1901, 1902, 0, 1903, 1904, 1905, - 1906, 0, 0, 1892, 0, 0, 0, 163, 1948, 166, - 0, 1945, 0, 164, 165, 0, 0, 0, 0, 0, + 1534, 0, 0, 3471, 0, 0, 0, 0, 0, 0, + 163, 1951, 166, 0, 1948, 0, 164, 165, 0, 0, + 0, 0, 0, 0, 0, 3488, 3489, 0, 3490, 3492, + 3494, 1592, 0, 181, 0, 0, 0, 0, 0, 0, + 0, 0, 187, 0, 0, 0, 0, 0, 0, 0, + 0, 167, 0, 0, 0, 0, 3507, 0, 0, 0, + 0, 3510, 0, 3512, 3513, 3514, 3516, 3517, 3518, 3519, + 3520, 3521, 3522, 3523, 3524, 3525, 3526, 3527, 3528, 3530, + 3532, 3534, 3536, 3538, 3540, 3542, 3544, 3546, 3548, 3550, + 3552, 3554, 3556, 3558, 3560, 3561, 3563, 3564, 3565, 3567, + 0, 0, 3569, 0, 3571, 3572, 3573, 0, 0, 3577, + 3578, 3579, 3580, 3581, 3582, 3583, 3584, 3585, 3586, 3587, + 0, 0, 0, 0, 0, 0, 0, 0, 3593, 0, + 0, 0, 3598, 0, 0, 0, 3602, 3603, 0, 3604, + 3606, 0, 3609, 3611, 0, 3613, 3614, 3615, 3616, 0, + 0, 0, 0, 0, 0, 3624, 0, 0, 0, 0, + 160, 0, 0, 161, 0, 0, 0, 0, 0, 0, + 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1912, 0, 0, 0, + 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, + 0, 185, 0, 0, 0, 0, 3656, 3657, 4237, 0, + 3661, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 181, 0, 0, 0, 0, 0, 0, 0, 0, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3463, 0, 0, 0, 0, 0, 0, 0, 167, + 0, 0, 0, 193, 0, 0, 4236, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 3480, 3481, 0, 3482, 3484, 3486, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3499, 0, 0, 0, 0, 3502, - 0, 3504, 3505, 3506, 3508, 3509, 3510, 3511, 3512, 3513, - 3514, 3515, 3516, 3517, 3518, 3519, 3520, 3522, 3524, 3526, - 3528, 3530, 3532, 3534, 3536, 3538, 3540, 3542, 3544, 3546, - 3548, 3550, 3552, 3553, 3555, 3556, 3557, 3559, 0, 0, - 3561, 0, 3563, 3564, 3565, 0, 0, 3569, 3570, 3571, - 3572, 3573, 3574, 3575, 3576, 3577, 3578, 3579, 160, 172, - 0, 161, 0, 0, 0, 0, 3585, 0, 0, 0, - 3590, 0, 0, 0, 3594, 3595, 0, 3596, 3598, 0, - 3601, 3603, 0, 3605, 3606, 3607, 3608, 0, 0, 0, - 0, 0, 173, 3616, 0, 0, 0, 0, 0, 185, + 167, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1774, 0, 174, 179, 176, 182, + 183, 184, 186, 188, 189, 190, 191, 0, 0, 0, + 0, 3734, 192, 194, 195, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1909, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1842, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 91, 48, 49, 93, 0, 0, 0, + 3752, 0, 0, 3756, 0, 0, 0, 0, 708, 0, + 0, 0, 98, 0, 0, 0, 52, 81, 82, 1933, + 79, 83, 0, 0, 0, 0, 0, 0, 1062, 0, + 0, 0, 80, 0, 0, 0, 0, 3769, 0, 160, + 0, 0, 161, 0, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, + 0, 0, 1141, 173, 0, 0, 101, 0, 0, 0, + 185, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 193, 0, 3648, 3649, 0, 0, 3653, 0, 0, + 0, 3792, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3800, 0, 0, 0, 0, 0, + 0, 3807, 193, 0, 0, 0, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 167, 0, 0, + 0, 0, 0, 0, 2085, 4388, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 174, 179, 176, 182, 183, 184, - 186, 188, 189, 190, 191, 0, 0, 0, 0, 0, - 192, 194, 195, 196, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 174, 179, 176, 182, 183, + 184, 186, 188, 189, 190, 191, 0, 0, 0, 0, + 0, 192, 194, 195, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3726, 198, + 0, 0, 0, 95, 59, 62, 61, 64, 0, 78, + 0, 0, 87, 84, 0, 4197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1942, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 137, 0, 159, 1255, 160, 1263, 0, 161, - 0, 0, 0, 0, 0, 0, 0, 3744, 180, 0, - 3748, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4196, 0, 0, 0, 0, 4029, 0, 0, 0, + 0, 0, 0, 0, 0, 4036, 4198, 66, 97, 96, + 0, 0, 76, 77, 63, 0, 0, 0, 0, 0, + 85, 86, 0, 0, 4046, 4047, 4048, 0, 4050, 0, + 4051, 4052, 0, 0, 0, 0, 4055, 4056, 4057, 4058, + 4059, 4060, 4061, 4062, 4063, 4064, 4065, 4066, 4067, 4068, + 4069, 4070, 4071, 4072, 4073, 4074, 4075, 4076, 0, 4078, + 4081, 0, 0, 0, 4195, 69, 0, 70, 71, 72, + 73, 0, 0, 0, 0, 4090, 4091, 4092, 4093, 4094, + 4096, 4097, 4099, 4101, 4102, 4104, 0, 0, 0, 4108, + 0, 0, 0, 4110, 0, 0, 0, 0, 0, 0, + 4120, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 65, 0, 0, 0, 0, 0, 0, 0, 4140, + 0, 0, 0, 2153, 2154, 2155, 2156, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2169, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2208, 2209, 0, 0, 0, 0, + 2232, 0, 0, 2236, 2237, 0, 0, 0, 2242, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2254, 2255, 2256, 2257, 2258, 2259, 2260, + 2261, 2262, 2263, 94, 2265, 0, 0, 0, 2287, 2288, + 2289, 2290, 2291, 2292, 2293, 2294, 2296, 0, 2301, 0, + 2303, 2304, 2305, 0, 2307, 2308, 2309, 0, 2311, 2312, + 2313, 2314, 2315, 2316, 2317, 2318, 2319, 2320, 2321, 2322, + 2323, 2324, 2325, 2326, 2327, 2328, 2329, 2330, 2331, 2332, + 2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340, 2341, 2342, + 2343, 2344, 2345, 2346, 2347, 2348, 2349, 2350, 2351, 2352, + 2353, 2354, 2355, 2356, 2360, 2361, 2362, 2363, 2364, 2365, + 2366, 2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, + 2376, 2377, 2378, 2379, 2380, 2381, 2382, 0, 0, 0, + 0, 0, 2388, 0, 2390, 0, 2396, 2397, 2398, 2399, + 2400, 2401, 0, 100, 0, 4164, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2412, 2413, 2414, 2415, 2416, + 2417, 2418, 2419, 0, 2421, 2422, 2423, 2424, 2425, 4179, + 0, 0, 0, 0, 0, 4182, 0, 4183, 0, 0, + 0, 0, 0, 198, 0, 0, 0, 0, 0, 0, + 1256, 0, 1264, 0, 1945, 0, 0, 0, 0, 0, + 0, 0, 0, 4208, 1111, 0, 137, 0, 159, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 180, 0, 0, 0, 0, 0, 4232, 4233, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4240, 4242, 4244, 0, 0, 0, 91, 48, + 49, 93, 2482, 2483, 1504, 0, 170, 0, 0, 0, + 0, 75, 158, 0, 0, 0, 0, 98, 0, 0, + 4267, 52, 81, 82, 0, 79, 83, 0, 0, 0, + 2523, 4289, 177, 0, 0, 178, 0, 80, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, + 0, 0, 0, 0, 0, 0, 0, 1949, 1950, 169, + 168, 197, 0, 0, 0, 0, 0, 0, 0, 67, + 0, 0, 0, 990, 0, 0, 0, 0, 0, 0, + 0, 101, 0, 0, 0, 4316, 0, 0, 0, 0, + 0, 0, 2567, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4339, 4341, 4343, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 88, 0, 0, 203, 0, 0, 203, 0, 0, + 0, 761, 0, 0, 0, 0, 767, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 203, 0, 0, + 4384, 0, 0, 0, 0, 163, 1951, 166, 0, 1948, + 0, 164, 165, 0, 203, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 181, 0, + 0, 0, 0, 0, 0, 0, 0, 187, 4413, 4414, + 767, 203, 767, 0, 767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 173, 0, 0, 0, 0, 0, 0, 185, 0, 0, - 0, 0, 170, 0, 3761, 0, 0, 0, 158, 0, - 0, 0, 0, 0, 0, 0, 0, 1057, 0, 1503, - 1100, 0, 0, 1058, 0, 0, 0, 0, 177, 0, - 0, 178, 0, 2198, 0, 0, 0, 0, 0, 193, - 0, 0, 0, 0, 0, 0, 1533, 0, 0, 0, - 0, 0, 0, 1946, 1947, 169, 168, 197, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3784, 0, - 0, 0, 0, 0, 0, 0, 0, 1591, 0, 0, - 0, 3792, 0, 0, 0, 0, 0, 1893, 3799, 0, - 0, 0, 174, 179, 176, 182, 183, 184, 186, 188, - 189, 190, 191, 0, 0, 0, 0, 0, 192, 194, - 195, 196, 0, 0, 1014, 1015, 1016, 1017, 1018, 1019, - 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, - 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, - 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, - 1050, 1051, 1052, 1053, 1054, 1055, 0, 0, 0, 0, - 0, 163, 1948, 166, 0, 1945, 0, 164, 165, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 95, 59, + 62, 61, 64, 0, 78, 4431, 0, 87, 84, 0, + 4197, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 181, 0, 0, 0, 0, 0, - 0, 0, 0, 187, 0, 0, 0, 0, 0, 0, + 0, 4198, 66, 97, 96, 0, 0, 76, 77, 63, + 91, 48, 49, 93, 0, 85, 86, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, + 0, 0, 0, 52, 81, 82, 0, 79, 83, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, + 0, 0, 0, 0, 0, 0, 0, 172, 0, 4195, + 69, 103, 70, 71, 72, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1856, 67, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 101, 0, 0, 0, 0, 0, 1873, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 4021, 0, 0, 0, 0, 0, 0, - 0, 0, 4028, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1880, 0, 0, 0, - 0, 4038, 4039, 4040, 0, 4042, 0, 4043, 4044, 0, - 0, 0, 0, 4047, 4048, 4049, 4050, 4051, 4052, 4053, - 4054, 4055, 4056, 4057, 4058, 4059, 4060, 4061, 4062, 4063, - 4064, 4065, 4066, 4067, 4068, 0, 4070, 4073, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 4082, 4083, 4084, 4085, 4086, 4088, 4089, 4091, - 4093, 4094, 4096, 0, 0, 0, 4100, 0, 0, 0, - 4102, 0, 0, 172, 0, 0, 0, 4112, 0, 0, + 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, + 0, 0, 0, 0, 2736, 0, 0, 0, 0, 0, + 0, 0, 0, 88, 2742, 2743, 2744, 2745, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1894, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 167, 0, 0, 0, 0, + 0, 0, 0, 0, 2008, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1592, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1853, 0, 4132, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1841, 0, 0, 0, - 0, 0, 0, 1870, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2053, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1907, 1910, 1911, - 1912, 1913, 1914, 1915, 1930, 1916, 1917, 1919, 1920, 1918, - 1921, 1922, 1895, 1896, 1897, 1898, 1878, 1879, 1908, 0, - 1881, 167, 1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, - 1890, 0, 0, 1891, 1899, 1900, 1901, 1902, 0, 1903, - 1904, 1905, 1906, 0, 0, 1892, 0, 0, 2005, 0, - 0, 0, 990, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 94, 0, + 0, 2081, 0, 0, 0, 0, 0, 0, 0, 0, + 95, 59, 62, 61, 64, 0, 78, 2092, 0, 87, + 84, 0, 0, 0, 2096, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2107, 2108, 2109, 2110, 2111, + 2112, 2113, 0, 0, 160, 0, 0, 161, 0, 0, + 0, 0, 0, 0, 66, 97, 96, 0, 0, 76, + 77, 63, 0, 0, 0, 0, 0, 85, 86, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 173, 0, + 0, 0, 0, 0, 0, 185, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, + 0, 68, 69, 0, 70, 71, 72, 73, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2050, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1842, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2078, 0, 0, 0, 0, - 0, 0, 0, 203, 0, 0, 203, 0, 0, 0, - 761, 2089, 0, 0, 0, 767, 0, 0, 2093, 2082, - 160, 0, 0, 161, 0, 0, 203, 0, 0, 2104, - 2105, 2106, 2107, 2108, 2109, 2110, 0, 0, 0, 0, - 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, - 0, 0, 4156, 0, 173, 0, 0, 0, 0, 0, - 0, 185, 0, 0, 0, 0, 0, 0, 0, 767, - 203, 767, 0, 767, 0, 0, 4171, 0, 0, 0, - 0, 0, 4174, 0, 4175, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1057, - 0, 0, 0, 193, 995, 1058, 1009, 1010, 1011, 996, - 4200, 0, 997, 998, 0, 999, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1012, 1013, 4224, 4225, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 4232, - 4234, 4236, 1909, 0, 0, 0, 174, 179, 176, 182, - 183, 184, 186, 188, 189, 190, 191, 0, 0, 0, - 0, 0, 192, 194, 195, 196, 0, 4259, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 4281, 0, - 0, 0, 0, 0, 0, 0, 1014, 1015, 1016, 1017, - 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, - 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, - 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, - 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 4231, 0, - 0, 0, 4308, 0, 2143, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 4331, 4333, 4335, 0, 0, 2150, 2151, - 2152, 2153, 0, 0, 0, 0, 0, 0, 0, 0, - 3439, 0, 0, 0, 2166, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4376, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 2205, - 2206, 0, 0, 0, 0, 2229, 0, 0, 2233, 2234, - 0, 0, 0, 2239, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 4405, 4406, 0, 2251, 2252, - 2253, 2254, 2255, 2256, 2257, 2258, 2259, 2260, 0, 2262, - 0, 3440, 3441, 2284, 2285, 2286, 2287, 2288, 2289, 2290, - 2291, 2293, 0, 2298, 0, 2300, 2301, 2302, 0, 2304, - 2305, 2306, 4423, 2308, 2309, 2310, 2311, 2312, 2313, 2314, - 2315, 2316, 2317, 2318, 2319, 2320, 2321, 2322, 2323, 2324, - 2325, 2326, 2327, 2328, 2329, 2330, 2331, 2332, 2333, 2334, - 2335, 2336, 2337, 2338, 2339, 2340, 2341, 2342, 2343, 2344, - 2345, 2346, 2347, 2348, 2349, 2350, 2351, 2352, 2353, 2357, - 2358, 2359, 2360, 2361, 2362, 2363, 2364, 2365, 2366, 2367, - 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376, 2377, - 2378, 2379, 0, 0, 0, 0, 0, 2385, 0, 2387, - 0, 2393, 2394, 2395, 2396, 2397, 2398, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2409, 2410, 2411, 2412, 2413, 2414, 2415, 2416, 0, 2418, - 2419, 2420, 2421, 2422, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, + 174, 179, 176, 182, 183, 184, 186, 188, 189, 190, + 191, 0, 0, 0, 0, 0, 192, 194, 195, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1111, + 0, 0, 0, 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 91, 48, 49, 93, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, - 0, 0, 2484, 52, 81, 82, 0, 79, 83, 0, - 2488, 0, 2491, 0, 0, 2143, 0, 2478, 2479, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 103, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2517, 0, 0, 0, 0, 0, 0, - 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 101, 4413, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 203, 0, - 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2561, 0, 0, 0, 0, - 0, 0, 0, 88, 0, 0, 0, 767, 0, 767, - 767, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, + 94, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 767, 203, 0, 0, 0, 0, 0, 4229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 767, 0, + 767, 767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1577, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4228, 0, 0, 0, + 0, 0, 767, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 2143, - 95, 59, 62, 61, 64, 2643, 78, 0, 0, 87, - 84, 0, 4189, 1057, 0, 0, 2664, 2665, 0, 1058, - 2669, 0, 0, 2672, 0, 0, 0, 0, 4188, 2198, - 0, 0, 0, 2675, 0, 0, 0, 0, 0, 0, - 2678, 0, 0, 4190, 66, 97, 96, 0, 0, 76, - 77, 63, 0, 0, 0, 0, 0, 85, 86, 0, - 0, 0, 0, 0, 0, 0, 2681, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3127, 0, 0, + 0, 1578, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 100, 0, 0, 0, 3153, 3154, 3155, 0, 0, 3157, + 0, 0, 3159, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3178, 3179, 3180, 0, 0, 0, 0, 0, + 0, 3185, 0, 0, 0, 0, 3187, 0, 0, 3189, + 3190, 3191, 0, 0, 0, 3192, 3193, 0, 0, 3194, + 0, 3195, 0, 0, 0, 0, 0, 0, 3196, 0, + 3197, 0, 0, 0, 3198, 0, 3199, 0, 0, 3200, + 0, 3201, 0, 3202, 0, 3203, 0, 3204, 0, 3205, + 0, 3206, 0, 3207, 0, 3208, 0, 3209, 0, 3210, + 0, 3211, 0, 3212, 0, 3213, 0, 3214, 0, 3215, + 0, 3216, 0, 3217, 0, 0, 0, 3218, 75, 3219, + 0, 3220, 0, 0, 3221, 0, 3222, 0, 3223, 0, + 2360, 3225, 0, 0, 3227, 0, 0, 3229, 3230, 3231, + 3232, 0, 0, 0, 0, 3233, 2360, 2360, 2360, 2360, + 2360, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3243, 0, 0, 0, 0, 0, 0, 0, 3256, + 0, 0, 3260, 1896, 0, 0, 0, 0, 0, 0, + 0, 3263, 3264, 3265, 3266, 3267, 3268, 0, 2488, 2489, + 3269, 3270, 0, 3271, 0, 3272, 0, 2493, 2494, 0, + 2497, 0, 0, 2146, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4187, 69, 0, 70, 71, 72, 73, 0, 0, - 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, - 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, - 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, - 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, - 1054, 1055, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, + 0, 0, 0, 0, 203, 0, 0, 0, 767, 767, + 0, 0, 0, 0, 0, 0, 0, 0, 3320, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3351, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 767, 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 767, 0, 0, 0, 0, 0, 0, 203, 0, + 0, 0, 767, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1883, 0, 0, 0, 0, 0, 0, 0, + 0, 3409, 0, 0, 0, 0, 0, 767, 0, 767, + 0, 0, 0, 0, 0, 0, 0, 767, 0, 0, + 1578, 767, 0, 0, 767, 767, 767, 767, 0, 767, + 0, 767, 767, 0, 767, 767, 767, 767, 767, 767, + 0, 0, 0, 0, 0, 0, 0, 1578, 767, 767, + 1578, 767, 1578, 203, 767, 0, 0, 2146, 0, 0, + 0, 0, 0, 2649, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 203, 2670, 2671, 0, 0, 2675, 0, + 0, 2678, 0, 0, 0, 0, 767, 1897, 203, 0, + 0, 2681, 3496, 0, 0, 0, 0, 0, 2684, 0, + 0, 0, 767, 0, 0, 1057, 767, 0, 1100, 203, + 203, 1058, 0, 0, 0, 0, 0, 0, 0, 0, + 3511, 2201, 0, 0, 2687, 0, 203, 0, 0, 0, + 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, + 0, 0, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 767, 0, 1910, 1913, 1914, 1915, 1916, 1917, 1918, + 0, 1919, 1920, 1922, 1923, 1921, 1924, 1925, 1898, 1899, + 1900, 1901, 1881, 1882, 1911, 0, 1884, 0, 1885, 1886, + 1887, 1888, 1889, 1890, 1891, 1892, 1893, 0, 0, 1894, + 1902, 1903, 1904, 1905, 0, 1906, 1907, 1908, 1909, 0, + 0, 1895, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, + 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, + 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, + 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, + 1052, 1053, 1054, 1055, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2730, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2736, 2737, 2738, - 2739, 0, 0, 203, 0, 0, 0, 767, 767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 203, 91, 48, - 49, 93, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1591, 0, 0, 0, 0, 98, 0, 0, - 94, 52, 81, 82, 767, 79, 83, 203, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 80, 0, 767, - 0, 0, 0, 0, 0, 0, 203, 0, 0, 103, - 767, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, - 0, 0, 0, 0, 0, 767, 0, 767, 0, 0, - 0, 101, 0, 0, 0, 767, 0, 0, 1577, 767, - 0, 0, 767, 767, 767, 767, 0, 767, 0, 767, - 767, 0, 767, 767, 767, 767, 767, 767, 0, 0, - 0, 0, 0, 0, 0, 1577, 767, 767, 1577, 767, - 1577, 203, 767, 0, 0, 0, 0, 0, 0, 0, - 100, 88, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 203, 0, 0, 0, 0, 0, 0, 0, 0, - 4380, 0, 0, 0, 767, 0, 203, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 767, 0, 0, 0, 767, 0, 0, 203, 203, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 203, 0, 0, 0, 0, 0, - 1841, 203, 0, 3004, 0, 0, 0, 0, 0, 0, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 767, - 0, 0, 0, 0, 0, 0, 0, 0, 95, 59, - 62, 61, 64, 0, 78, 0, 0, 87, 84, 0, - 4189, 0, 0, 0, 0, 0, 0, 0, 75, 0, - 0, 0, 0, 0, 0, 0, 4188, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4190, 66, 97, 96, 0, 0, 76, 77, 63, - 0, 0, 0, 0, 0, 85, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 4187, - 69, 0, 70, 71, 72, 73, 0, 3092, 3093, 3094, - 3095, 3096, 3097, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 989, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 2143, 3108, 0, 0, + 0, 0, 0, 767, 767, 0, 0, 0, 0, 0, + 3715, 0, 0, 0, 0, 0, 0, 0, 767, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3739, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 744, 0, 0, 0, + 0, 0, 766, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 767, + 0, 0, 0, 0, 0, 0, 0, 0, 1912, 1578, + 0, 0, 0, 0, 0, 3758, 0, 3759, 0, 3760, + 0, 3761, 0, 0, 0, 0, 0, 1578, 0, 3764, + 3765, 0, 0, 0, 0, 0, 766, 0, 766, 3770, + 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3771, 0, 3772, 0, 3773, 0, 3774, + 0, 3775, 0, 3776, 0, 3777, 0, 3778, 0, 3779, + 0, 3780, 0, 3781, 0, 3782, 0, 3783, 0, 3784, + 0, 3785, 0, 3786, 0, 0, 3787, 0, 0, 0, + 3788, 0, 3789, 0, 0, 0, 0, 0, 3791, 0, + 0, 0, 0, 0, 3011, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3808, 0, 0, 0, 0, 0, 0, 0, 0, 3813, + 0, 3814, 3815, 0, 3816, 0, 3817, 0, 0, 0, + 0, 3818, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2406, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3858, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3867, + 0, 0, 3869, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3873, 0, 0, 0, 203, 0, + 0, 0, 0, 767, 101, 0, 0, 1057, 0, 0, + 0, 4009, 995, 1058, 1009, 1010, 1011, 996, 0, 0, + 997, 998, 0, 999, 0, 0, 0, 0, 3099, 3100, + 3101, 3102, 3103, 3104, 0, 0, 0, 767, 0, 1004, + 0, 1012, 1013, 0, 0, 203, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2146, 3115, 0, + 0, 0, 0, 0, 0, 0, 0, 203, 203, 0, + 0, 0, 767, 0, 0, 2406, 203, 203, 0, 203, + 0, 203, 203, 3123, 0, 0, 0, 0, 0, 0, + 0, 0, 3445, 3446, 0, 0, 767, 0, 0, 0, + 0, 0, 0, 0, 1014, 1015, 1016, 1017, 1018, 1019, + 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, + 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, + 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, + 1050, 1051, 1052, 1053, 1054, 1055, 4118, 0, 0, 0, + 0, 0, 0, 0, 767, 0, 0, 0, 0, 0, + 767, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 767, 0, 0, 0, + 0, 0, 767, 767, 0, 0, 767, 0, 767, 0, + 0, 0, 0, 0, 767, 0, 0, 0, 3447, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3116, 0, 0, 0, 65, 0, 0, 0, - 0, 767, 767, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 767, 3120, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3146, 3147, 3148, 0, 0, 3150, - 0, 0, 3152, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3171, 3172, 3173, 0, 0, 767, 0, 0, - 0, 3178, 0, 0, 0, 0, 3180, 1577, 0, 3182, - 3183, 3184, 0, 0, 0, 3185, 3186, 0, 94, 3187, - 0, 3188, 0, 0, 0, 1577, 0, 0, 3189, 0, - 3190, 0, 0, 0, 3191, 0, 3192, 0, 0, 3193, - 0, 3194, 0, 3195, 0, 3196, 0, 3197, 0, 3198, - 0, 3199, 0, 3200, 0, 3201, 0, 3202, 0, 3203, - 0, 3204, 0, 3205, 0, 3206, 0, 3207, 0, 3208, - 0, 3209, 0, 3210, 0, 0, 0, 3211, 0, 3212, - 0, 3213, 0, 0, 3214, 0, 3215, 0, 3216, 0, - 2357, 3218, 0, 0, 3220, 0, 0, 3222, 3223, 3224, - 3225, 0, 0, 0, 0, 3226, 2357, 2357, 2357, 2357, - 2357, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3236, 0, 0, 0, 0, 0, 0, 100, 3249, - 0, 0, 3253, 0, 0, 0, 0, 0, 0, 0, - 0, 3256, 3257, 3258, 3259, 3260, 3261, 0, 0, 0, - 3262, 3263, 0, 3264, 0, 3265, 0, 0, 0, 0, - 0, 2403, 3283, 3284, 0, 3288, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1111, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 767, + 0, 0, 0, 0, 767, 0, 0, 0, 767, 767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 203, 0, 0, 0, - 0, 767, 0, 0, 0, 0, 0, 0, 3313, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 203, 0, 0, 3448, + 3449, 0, 203, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 203, 203, 0, 0, 203, 0, 203, + 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 203, 0, 0, 0, 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 3343, 0, 767, 75, 0, 0, 0, + 0, 0, 0, 3290, 3291, 0, 3295, 0, 0, 0, 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, + 203, 0, 0, 0, 0, 767, 0, 0, 0, 0, + 0, 0, 0, 4162, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 960, 0, 0, 0, + 0, 0, 964, 0, 0, 0, 961, 962, 0, 0, + 0, 963, 965, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4176, + 0, 0, 4177, 0, 4178, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1578, + 0, 2406, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 766, 1489, 766, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 203, 0, 0, 0, 767, - 0, 0, 2403, 203, 0, 203, 0, 203, 203, 0, - 0, 0, 0, 0, 0, 0, 0, 3429, 0, 0, - 3401, 0, 767, 0, 0, 0, 0, 0, 0, 0, - 0, 3443, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3455, 0, 0, 3458, + 0, 0, 0, 0, 0, 0, 0, 0, 766, 3437, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3451, 0, 0, 1057, 0, 0, 0, + 0, 995, 1058, 1009, 1010, 1011, 996, 1577, 3463, 997, + 998, 3466, 999, 0, 0, 0, 0, 0, 0, 0, + 4255, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1012, 1013, 0, 0, 0, 0, 0, 4287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 767, 0, 0, 0, 0, 0, 767, 0, 0, 0, + 0, 0, 0, 0, 0, 4300, 0, 4301, 0, 4302, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 767, 0, 0, 0, 0, 0, 767, 767, - 0, 3488, 767, 0, 767, 0, 0, 0, 0, 0, - 767, 0, 989, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 3503, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 946, + 0, 0, 0, 1014, 1015, 1016, 1017, 1018, 1019, 1020, + 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, + 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, + 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, + 1051, 1052, 1053, 1054, 1055, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 767, 0, 0, 0, 0, - 767, 0, 0, 0, 767, 767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 744, - 0, 0, 0, 0, 0, 766, 0, 0, 0, 0, - 0, 0, 203, 0, 0, 0, 0, 0, 203, 0, - 0, 0, 0, 0, 3618, 0, 0, 0, 0, 203, - 203, 0, 0, 203, 0, 203, 203, 0, 0, 0, - 3624, 3625, 0, 0, 0, 0, 203, 0, 0, 0, - 0, 0, 0, 203, 0, 0, 0, 0, 0, 766, - 0, 766, 0, 766, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, - 0, 0, 0, 0, 0, 0, 203, 0, 0, 0, - 0, 767, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 765, 203, 4382, 0, 4383, 0, 0, 0, + 0, 203, 0, 0, 0, 0, 3626, 0, 0, 0, + 0, 0, 767, 0, 0, 0, 0, 3447, 0, 0, + 0, 0, 3632, 3633, 0, 767, 767, 767, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 767, 4418, 4419, 0, 0, 1137, 0, 1144, 0, + 1148, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 203, 0, + 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3688, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3448, 3449, + 0, 0, 0, 0, 766, 766, 0, 3696, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1577, 0, 2403, 3707, 0, + 0, 0, 0, 767, 0, 0, 0, 0, 0, 0, + 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 767, 0, 0, 766, 0, 0, + 0, 767, 0, 0, 0, 767, 767, 0, 766, 0, + 767, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1578, 767, 0, 0, + 0, 0, 0, 766, 0, 766, 0, 203, 203, 203, + 203, 203, 203, 766, 0, 0, 1577, 766, 0, 0, + 766, 766, 766, 766, 0, 766, 0, 766, 766, 0, + 766, 766, 766, 766, 766, 766, 203, 203, 0, 0, + 0, 0, 0, 1577, 766, 766, 1577, 766, 1577, 0, + 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 203, 0, 0, 1057, 0, 0, 0, 0, + 0, 1058, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2201, 766, 0, 0, 0, 0, 0, 767, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 766, 0, + 0, 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 767, 0, + 0, 0, 0, 0, 0, 0, 0, 766, 0, 0, + 0, 0, 0, 0, 0, 0, 3841, 0, 0, 3842, + 3843, 3844, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, + 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, + 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, + 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, + 1052, 1053, 1054, 1055, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3731, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 91, 48, 49, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 98, 0, 0, 0, 52, 81, 82, 0, - 79, 83, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 80, 3750, 0, 3751, 0, 3752, 0, 3753, - 0, 0, 0, 0, 103, 0, 0, 3756, 3757, 0, - 0, 0, 0, 0, 0, 0, 946, 3762, 0, 0, - 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, - 0, 3763, 0, 3764, 0, 3765, 101, 3766, 0, 3767, - 0, 3768, 0, 3769, 0, 3770, 0, 3771, 0, 3772, - 0, 3773, 0, 3774, 0, 3775, 0, 3776, 0, 3777, - 0, 3778, 0, 0, 3779, 0, 0, 0, 3780, 0, - 3781, 0, 0, 0, 0, 0, 3783, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 88, 0, 0, 765, - 0, 0, 0, 0, 0, 0, 0, 0, 3800, 0, - 0, 0, 0, 0, 0, 0, 0, 3805, 0, 3806, - 3807, 0, 3808, 3833, 3809, 0, 3834, 3835, 3836, 3810, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, - 0, 0, 0, 0, 0, 0, 0, 203, 0, 0, - 0, 0, 0, 1136, 0, 1143, 0, 1147, 767, 0, - 0, 0, 0, 0, 3850, 0, 0, 0, 0, 0, - 767, 767, 767, 203, 0, 0, 0, 3859, 0, 0, - 3861, 0, 0, 0, 0, 0, 767, 0, 0, 0, - 0, 0, 3865, 95, 59, 62, 61, 64, 0, 78, - 0, 0, 87, 84, 0, 4189, 0, 0, 0, 4001, - 0, 203, 0, 0, 0, 0, 203, 0, 0, 0, - 0, 4188, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4190, 66, 97, 96, - 0, 0, 76, 77, 63, 0, 0, 0, 0, 0, - 85, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 767, 0, 0, 0, - 0, 0, 0, 0, 4187, 69, 0, 70, 71, 72, - 73, 0, 0, 0, 0, 0, 0, 767, 0, 0, - 0, 0, 0, 0, 767, 0, 0, 0, 767, 767, 0, 0, 0, 767, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1577, - 767, 0, 0, 0, 4110, 0, 0, 0, 0, 0, - 203, 203, 203, 203, 203, 203, 0, 0, 0, 0, - 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, - 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 91, 48, 49, 93, 0, - 0, 0, 0, 0, 0, 203, 0, 0, 0, 0, - 0, 0, 0, 0, 98, 0, 0, 0, 52, 81, - 82, 0, 79, 83, 0, 0, 0, 766, 1488, 766, - 766, 767, 0, 0, 80, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, - 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 94, 0, 0, 67, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 101, 0, - 1576, 767, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 88, 0, - 0, 0, 0, 0, 4152, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4154, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 767, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4168, 767, 0, - 4169, 0, 4170, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 95, 59, 62, 61, 64, - 0, 78, 0, 0, 87, 84, 0, 0, 0, 767, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 203, 203, 203, 0, 203, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, - 97, 96, 0, 0, 76, 77, 63, 0, 0, 0, - 0, 0, 85, 86, 0, 0, 0, 0, 0, 767, - 0, 75, 0, 1577, 0, 0, 767, 767, 1577, 203, - 203, 203, 203, 203, 0, 0, 0, 0, 4247, 0, - 0, 203, 0, 0, 0, 0, 0, 203, 0, 203, - 0, 0, 203, 203, 203, 4279, 68, 69, 0, 70, - 71, 72, 73, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 766, 766, 0, - 0, 0, 0, 4292, 0, 4293, 0, 4294, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1321, 0, 1321, 1321, 0, 0, 767, 0, 0, - 1577, 0, 0, 0, 0, 767, 0, 0, 0, 0, - 203, 0, 0, 65, 766, 1502, 0, 0, 0, 0, - 0, 0, 0, 0, 203, 0, 0, 0, 0, 766, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, - 766, 0, 203, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 766, 0, 766, 0, 0, - 0, 0, 4374, 0, 4375, 766, 0, 0, 1576, 766, - 0, 0, 766, 766, 766, 766, 0, 766, 0, 766, - 766, 0, 766, 766, 766, 766, 766, 766, 0, 0, - 0, 0, 0, 0, 0, 1576, 766, 766, 1576, 766, - 1576, 0, 766, 0, 0, 94, 0, 0, 0, 0, - 4410, 4411, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1057, 0, 0, 0, 0, 995, 1058, 1009, - 1010, 1011, 996, 0, 766, 997, 998, 0, 999, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 766, 0, 0, 0, 766, 0, 1012, 1013, 0, 0, - 767, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 203, 203, 203, 0, 203, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 766, + 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 766, 0, 767, 0, 0, 0, + 0, 1578, 0, 0, 767, 767, 1578, 203, 203, 203, + 203, 203, 0, 0, 0, 0, 0, 0, 0, 203, + 0, 0, 0, 0, 0, 203, 0, 203, 0, 0, + 203, 203, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 766, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1577, 0, 0, 0, 0, + 0, 0, 0, 0, 2210, 0, 0, 0, 0, 0, + 0, 0, 0, 1577, 0, 767, 0, 0, 1578, 0, + 0, 0, 0, 767, 0, 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 203, 0, 766, + 0, 0, 203, 0, 1322, 0, 1322, 1322, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 203, 0, 0, + 203, 0, 0, 0, 0, 0, 0, 0, 1503, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 203, 203, 100, 0, 0, 0, 1014, - 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, - 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, - 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, - 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, - 1055, 0, 0, 0, 0, 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 203, 0, 0, - 0, 1776, 1777, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 3439, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 767, 767, 0, 0, 0, - 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1847, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1865, 0, 0, 0, 0, 767, 767, - 767, 767, 0, 0, 1924, 0, 0, 0, 0, 0, - 0, 766, 766, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3440, 3441, 766, 0, 0, 1136, - 0, 1954, 0, 0, 0, 0, 0, 0, 0, 1963, - 0, 0, 0, 1965, 0, 0, 1968, 1969, 1971, 1971, - 0, 1971, 0, 1971, 1971, 0, 1980, 1971, 1971, 1971, - 1971, 1971, 0, 0, 0, 0, 0, 0, 0, 0, - 2000, 2001, 0, 1136, 0, 0, 2006, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 766, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1576, 0, 0, - 0, 0, 0, 0, 0, 0, 2207, 0, 2048, 0, - 0, 0, 0, 0, 0, 1576, 0, 0, 0, 0, - 0, 0, 0, 0, 2069, 0, 0, 0, 2074, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 767, 0, 767, 0, 203, - 0, 0, 0, 1321, 0, 0, 203, 0, 0, 203, - 203, 203, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1577, 0, 0, 0, - 203, 0, 0, 767, 0, 767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4160, 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 767, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 203, 0, 0, 767, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 767, + 0, 0, 0, 0, 0, 0, 0, 0, 767, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 203, 0, 0, 0, 0, + 0, 0, 0, 766, 0, 0, 0, 0, 0, 0, + 0, 203, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 766, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 766, 0, + 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1321, 1321, 0, 0, 0, - 0, 0, 0, 0, 767, 0, 0, 0, 0, 766, - 2131, 767, 766, 767, 0, 0, 0, 0, 0, 0, - 0, 0, 767, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 766, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 766, 0, 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2193, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 766, 0, 0, 0, 0, 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 766, 0, 0, 0, 767, 767, 766, 0, 0, 0, + 0, 0, 0, 0, 1777, 1778, 0, 0, 0, 0, 0, 0, 766, 0, 0, 0, 0, 0, 766, 766, 0, 0, 766, 0, 766, 0, 0, 0, 0, 0, - 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 101, 0, 0, 1057, 0, 0, 0, - 0, 995, 1058, 1009, 1010, 1011, 996, 0, 0, 997, - 998, 0, 999, 0, 0, 766, 0, 0, 0, 0, - 766, 0, 0, 0, 766, 766, 0, 0, 1004, 0, - 1012, 1013, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 767, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 203, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 767, 203, 0, 0, - 0, 3437, 3438, 0, 0, 1321, 0, 0, 0, 0, - 0, 0, 0, 1014, 1015, 1016, 1017, 1018, 1019, 1020, - 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, - 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, - 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, - 1051, 1052, 1053, 1054, 1055, 2440, 0, 0, 0, 0, - 0, 766, 767, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 767, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1577, 767, 0, 767, 2456, - 0, 0, 0, 0, 0, 947, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 3439, 0, 0, - 0, 0, 767, 2403, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1847, 0, 0, 1321, 0, 0, 0, - 0, 0, 0, 0, 0, 1576, 0, 766, 0, 0, - 0, 0, 0, 0, 0, 0, 1136, 0, 0, 0, - 0, 0, 767, 767, 0, 0, 201, 0, 0, 709, - 0, 0, 0, 203, 767, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 709, - 0, 0, 0, 0, 0, 0, 0, 0, 3440, 3441, - 0, 0, 0, 0, 0, 0, 1086, 0, 0, 0, - 0, 0, 767, 0, 1143, 0, 0, 0, 0, 0, - 2580, 0, 0, 0, 1112, 1112, 0, 0, 0, 0, - 0, 0, 0, 709, 0, 0, 1136, 0, 0, 0, - 0, 0, 1143, 1963, 0, 0, 1963, 0, 1963, 0, - 0, 0, 0, 767, 2609, 203, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 767, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 767, 0, 0, 0, 0, 0, 0, 1136, - 0, 0, 0, 0, 2193, 960, 0, 0, 2193, 2193, - 0, 964, 0, 0, 0, 961, 962, 0, 0, 0, - 963, 965, 0, 767, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 766, 0, 0, 0, 0, 0, 0, 767, 767, 767, + 767, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1849, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 766, 0, 1868, 0, 0, + 766, 0, 0, 0, 766, 766, 0, 0, 1927, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1137, 0, 1957, 0, 0, 0, 0, + 0, 0, 0, 1966, 0, 0, 0, 1968, 0, 0, + 1971, 1972, 1974, 1974, 0, 1974, 0, 1974, 1974, 0, + 1983, 1974, 1974, 1974, 1974, 1974, 0, 0, 0, 0, + 0, 0, 0, 0, 2003, 2004, 0, 1137, 0, 0, + 2009, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 947, 0, 0, 0, + 0, 0, 2051, 0, 0, 0, 0, 0, 0, 0, + 0, 766, 0, 0, 0, 0, 0, 0, 2072, 0, + 0, 0, 2077, 0, 767, 0, 767, 0, 203, 0, + 0, 0, 0, 0, 0, 203, 0, 0, 203, 203, + 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1578, 0, 201, 0, 203, + 709, 0, 767, 0, 767, 0, 0, 1322, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 709, 0, 0, 0, 0, 1577, 0, 766, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1086, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1112, 1112, 0, 0, 0, + 767, 0, 0, 0, 709, 0, 0, 0, 0, 0, + 0, 0, 0, 203, 0, 0, 767, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 767, 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 766, 766, 766, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2686, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 767, 0, 0, 0, 0, 0, 0, + 767, 0, 767, 0, 0, 0, 0, 0, 0, 0, + 0, 767, 0, 0, 0, 0, 0, 0, 0, 1322, + 1322, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2134, 0, 0, 0, 0, 0, + 0, 0, 767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3017, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1321, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 766, 0, 0, 0, + 0, 0, 0, 0, 0, 2196, 0, 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 766, 766, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 766, 0, 0, - 0, 0, 0, 0, 766, 0, 0, 0, 766, 766, - 0, 0, 0, 766, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1576, - 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3024, 0, 0, 0, 0, + 0, 0, 767, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 767, 203, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 766, 0, 0, 0, 0, 0, 0, 766, 0, 1322, + 0, 766, 766, 0, 0, 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 767, 1577, 766, 0, 0, 0, 0, 0, 0, + 0, 767, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1578, 767, 0, 767, 0, 2443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2934, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2950, 2951, 2952, 0, 0, 0, + 0, 767, 2406, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2460, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2967, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 767, 767, 0, 766, 0, 0, 0, 1849, 0, + 0, 1322, 203, 767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1137, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 767, 0, 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 709, 0, 709, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 766, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 3050, 0, 0, 0, 0, 0, 0, 0, 0, 766, - 0, 0, 0, 0, 0, 709, 0, 0, 0, 0, - 0, 1147, 0, 0, 0, 0, 0, 0, 3070, 0, - 0, 0, 1963, 1963, 0, 0, 0, 3075, 0, 0, - 0, 0, 0, 1578, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3086, 0, 0, 0, 0, 766, - 0, 0, 0, 1576, 0, 0, 766, 766, 1576, 0, + 1144, 0, 767, 0, 203, 0, 2586, 0, 0, 0, + 0, 0, 709, 0, 709, 0, 0, 0, 767, 0, + 0, 0, 1137, 0, 0, 0, 0, 0, 1144, 1966, + 0, 767, 1966, 0, 1966, 0, 0, 0, 0, 0, + 2615, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 767, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1137, 709, 0, 0, 766, + 2196, 0, 0, 0, 2196, 2196, 0, 0, 0, 0, + 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1579, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 766, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 766, 0, 0, 0, 0, 1577, 0, 0, + 766, 766, 1577, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 3391, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2193, 0, 766, 0, 0, - 1576, 0, 0, 0, 0, 766, 0, 0, 0, 0, + 0, 2692, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2193, 0, 0, 0, 0, - 0, 0, 3462, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3399, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 766, 0, 0, 1577, 0, 0, 0, 0, 766, + 0, 0, 0, 0, 0, 0, 0, 1322, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3470, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 709, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 709, 0, 0, 0, - 3238, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 766, 0, 1321, 0, 0, 0, 0, 0, 0, 0, - 1086, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1971, 0, 0, 0, 0, 0, 0, - 709, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 709, + 0, 1086, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1321, 0, 0, 0, 0, 0, 0, - 3325, 1971, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1578, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 709, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 766, 0, 0, 0, 0, 0, + 0, 709, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3677, 0, 1578, 0, - 0, 1578, 0, 1578, 709, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2022, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 766, 766, 0, 0, 709, - 0, 1136, 0, 0, 0, 0, 0, 0, 0, 1147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2076, 709, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 709, 766, 766, - 766, 766, 0, 0, 709, 0, 0, 0, 0, 0, - 0, 0, 0, 2102, 2103, 709, 709, 709, 709, 709, - 709, 709, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1579, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1579, 0, 0, 1579, 0, 1579, 709, 0, 2940, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2956, 2957, 2958, 0, 0, 2025, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2973, 0, 0, + 0, 709, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3685, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2079, 709, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 709, + 0, 0, 0, 0, 0, 0, 709, 0, 0, 0, + 766, 766, 0, 0, 0, 2105, 2106, 709, 709, 709, + 709, 709, 709, 709, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 766, 766, 766, 766, 0, 0, 3057, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1148, 0, 0, 0, 0, 0, 0, 3077, 0, 0, + 0, 1966, 1966, 0, 0, 0, 3082, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3093, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1924, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 766, 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1576, 0, 0, 0, - 0, 0, 0, 766, 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 709, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 766, 0, 766, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 709, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 766, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 766, - 1578, 0, 0, 0, 0, 0, 0, 0, 0, 1147, - 1147, 0, 0, 0, 0, 0, 0, 0, 1578, 0, + 0, 1577, 0, 0, 2196, 0, 0, 0, 766, 0, + 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1579, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3738, 3739, 3740, 3741, 0, 0, 0, 0, + 1579, 0, 0, 0, 0, 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 766, 0, 0, 0, 0, 0, - 0, 766, 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 766, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 766, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2076, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 2022, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1112, 0, 0, 0, 3816, - 0, 3816, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1322, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1086, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 3855, 0, 3857, - 0, 0, 0, 766, 0, 0, 0, 0, 709, 0, - 0, 0, 0, 0, 0, 2076, 709, 0, 709, 0, - 709, 2507, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1147, 0, 0, 0, 0, + 0, 0, 1974, 0, 0, 0, 0, 0, 0, 766, + 0, 0, 0, 0, 0, 0, 766, 0, 766, 0, + 0, 0, 0, 0, 0, 0, 0, 766, 0, 0, + 0, 0, 0, 0, 0, 0, 2079, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4023, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1321, 0, 0, 0, 0, 0, 0, + 0, 0, 1322, 0, 0, 0, 0, 0, 766, 0, + 3333, 1974, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 766, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 766, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1576, 766, 0, 766, 0, + 0, 2025, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 766, 766, 0, 0, 0, 0, 3816, 0, - 0, 0, 0, 0, 0, 3816, 0, 3816, 0, 0, - 0, 0, 0, 0, 0, 0, 4114, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1086, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 766, 766, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 766, 0, 0, 1147, 0, 0, - 0, 0, 0, 0, 0, 709, 0, 0, 0, 0, - 0, 709, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 709, 709, 0, 0, 709, 0, 2671, 709, - 0, 0, 766, 0, 0, 0, 0, 0, 0, 709, - 0, 0, 0, 0, 0, 0, 709, 0, 0, 0, + 0, 1137, 0, 0, 0, 0, 0, 0, 0, 1148, + 709, 709, 0, 0, 0, 0, 0, 0, 2079, 709, + 709, 0, 709, 0, 709, 2513, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 709, 766, 0, 0, 0, 0, 0, 2683, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 766, + 0, 0, 0, 0, 0, 0, 0, 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 766, 0, 0, 0, 1147, 0, 0, + 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1578, 0, - 2076, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4172, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4180, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 766, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 766, 0, 0, + 0, 0, 0, 0, 1927, 0, 0, 0, 0, 0, + 1577, 766, 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1147, 0, 4198, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 766, 766, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 709, + 0, 0, 0, 0, 0, 709, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 709, 709, 0, 0, + 709, 0, 2677, 709, 0, 0, 0, 766, 766, 0, + 0, 0, 0, 709, 0, 0, 0, 0, 0, 766, + 709, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1321, 1321, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 3887, 3889, 3888, - 3954, 3955, 3956, 3957, 3958, 3959, 3960, 3890, 3891, 837, + 0, 0, 0, 0, 0, 0, 709, 0, 0, 0, + 0, 0, 0, 2689, 0, 0, 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4250, 4258, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 4263, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 766, 0, + 1148, 1148, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 766, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 766, 0, 0, + 0, 0, 1579, 0, 2079, 0, 0, 0, 0, 0, + 0, 0, 0, 3746, 3747, 3748, 3749, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4180, 0, 0, 0, - 0, 0, 709, 0, 0, 0, 0, 0, 0, 0, - 2022, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 2953, 1147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1924, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4263, 0, 0, 0, - 0, 0, 0, 0, 709, 0, 0, 0, 0, 709, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4258, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 4258, 0, 0, 0, 3895, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 3903, - 3904, 0, 0, 3979, 3978, 3977, 0, 0, 3975, 3976, - 3974, 0, 1578, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 709, 709, 709, 709, 709, 709, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 709, 709, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3980, 960, 709, 813, - 814, 3981, 3982, 964, 3983, 816, 817, 961, 962, 0, - 811, 815, 963, 965, 0, 0, 0, 0, 0, 0, + 3824, 0, 3824, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 3884, - 3885, 3886, 3892, 3893, 3894, 3905, 3952, 3953, 3961, 3963, - 916, 3962, 3964, 3965, 3966, 3969, 3970, 3971, 3972, 3967, - 3968, 3973, 3867, 3871, 3868, 3869, 3870, 3882, 3872, 3873, - 3874, 3875, 3876, 3877, 3878, 3879, 3880, 3881, 3883, 3984, - 3985, 3986, 3987, 3988, 3989, 3898, 3902, 3901, 3899, 3900, - 3896, 3897, 3924, 3923, 3925, 3926, 3927, 3928, 3929, 3930, - 3932, 3931, 3933, 3934, 3935, 3936, 3937, 3938, 3906, 3907, - 3910, 3911, 3909, 3908, 3912, 3921, 3922, 3913, 3914, 3915, - 3916, 3917, 3918, 3920, 3919, 3939, 3940, 3941, 3942, 3943, - 3945, 3944, 3948, 3949, 3947, 3946, 3951, 3950, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3863, 0, + 3865, 0, 0, 0, 0, 0, 709, 0, 0, 0, + 0, 0, 0, 0, 2025, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 966, 0, 967, 0, 0, 971, 0, 0, 0, - 973, 972, 0, 974, 936, 935, 0, 0, 968, 969, - 0, 970, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2959, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4031, 0, 0, 0, 0, 0, 0, 0, + 0, 709, 0, 0, 1322, 0, 709, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1112, 0, 709, 709, 709, - 0, 709, 0, 0, 0, 0, 0, 3990, 3991, 3992, - 3993, 3994, 3995, 3996, 3997, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1578, 0, 0, 0, - 0, 1578, 709, 709, 709, 709, 709, 0, 0, 0, - 0, 0, 0, 0, 3341, 0, 0, 0, 0, 0, - 2022, 0, 709, 0, 0, 709, 3349, 2076, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3824, + 0, 0, 0, 0, 0, 0, 3824, 0, 3824, 0, + 0, 0, 0, 0, 0, 0, 0, 4122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1148, 1579, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1578, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 709, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 709, 0, 0, + 709, 709, 709, 709, 709, 709, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 709, 0, 0, 709, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 709, + 709, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 709, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4180, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4188, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 709, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 709, 709, 0, 0, + 0, 1148, 0, 4206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1322, 1322, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1112, 0, 709, 709, 709, 0, 709, 0, + 0, 0, 0, 0, 0, 0, 0, 4258, 4266, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4271, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1579, 0, 0, 0, 0, 1579, + 709, 709, 709, 709, 709, 0, 0, 0, 0, 0, + 0, 0, 3349, 0, 0, 0, 0, 4188, 2025, 0, + 709, 0, 0, 709, 3357, 2079, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3895, 3897, + 3896, 3962, 3963, 3964, 3965, 3966, 3967, 3968, 3898, 3899, + 837, 0, 0, 0, 0, 0, 0, 0, 1148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1927, 0, 0, 0, 0, 0, + 0, 1579, 0, 0, 0, 0, 0, 4271, 0, 0, 0, 709, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 709, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4266, 0, + 709, 0, 0, 709, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 709, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4266, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -3141,30 +3094,52 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 709, 0, + 0, 0, 0, 0, 0, 3903, 0, 0, 0, 0, + 0, 0, 0, 0, 709, 709, 0, 0, 0, 0, + 3911, 3912, 0, 0, 3987, 3986, 3985, 0, 0, 3983, + 3984, 3982, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 709, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3988, 960, 709, + 813, 814, 3989, 3990, 964, 3991, 816, 817, 961, 962, + 0, 811, 815, 963, 965, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3892, 3893, 3894, 3900, 3901, 3902, 3913, 3960, 3961, 3969, + 3971, 916, 3970, 3972, 3973, 3974, 3977, 3978, 3979, 3980, + 3975, 3976, 3981, 3875, 3879, 3876, 3877, 3878, 3890, 3880, + 3881, 3882, 3883, 3884, 3885, 3886, 3887, 3888, 3889, 3891, + 3992, 3993, 3994, 3995, 3996, 3997, 3906, 3910, 3909, 3907, + 3908, 3904, 3905, 3932, 3931, 3933, 3934, 3935, 3936, 3937, + 3938, 3940, 3939, 3941, 3942, 3943, 3944, 3945, 3946, 3914, + 3915, 3918, 3919, 3917, 3916, 3920, 3929, 3930, 3921, 3922, + 3923, 3924, 3925, 3926, 3928, 3927, 3947, 3948, 3949, 3950, + 3951, 3953, 3952, 3956, 3957, 3955, 3954, 3959, 3958, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 966, 0, 967, 0, 0, 971, 0, 0, + 0, 973, 972, 0, 974, 936, 935, 0, 0, 968, + 969, 0, 970, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2022, 0, 0, 0, 0, 0, 0, 709, - 0, 0, 709, 709, 709, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1578, - 0, 0, 0, 2022, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2025, 0, 0, 0, 0, 0, 0, 709, 0, + 0, 709, 709, 709, 0, 0, 0, 0, 3998, 3999, + 4000, 4001, 4002, 4003, 4004, 4005, 0, 0, 1579, 0, + 0, 0, 2025, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2022, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2025, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -3183,114 +3158,349 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1471, 1450, 557, - 0, 1391, 1474, 1356, 1377, 1484, 1380, 1383, 1428, 1331, - 1406, 438, 1374, 1360, 1326, 1368, 1327, 1358, 1393, 286, - 1355, 1452, 1410, 1473, 385, 283, 1333, 1324, 212, 530, - 1361, 453, 1379, 211, 1431, 511, 268, 396, 393, 615, - 298, 289, 285, 264, 336, 405, 450, 547, 444, 1480, - 389, 1416, 0, 522, 422, 0, 0, 0, 1457, 1456, - 1384, 1395, 1462, 1404, 1443, 1389, 1430, 1343, 1415, 1475, - 1375, 1425, 1476, 342, 262, 344, 210, 435, 523, 302, - 0, 2022, 0, 0, 4220, 536, 991, 0, 0, 0, - 0, 4221, 0, 0, 0, 0, 249, 0, 0, 256, - 709, 0, 0, 370, 379, 378, 358, 359, 361, 363, - 369, 376, 382, 355, 364, 1371, 1422, 641, 1469, 1372, - 1424, 281, 340, 288, 280, 612, 1481, 1461, 1330, 1403, - 1468, 1398, 628, 0, 0, 238, 1472, 1397, 0, 1427, - 0, 1487, 1325, 1418, 0, 1328, 1332, 1483, 1466, 1364, - 1365, 291, 0, 0, 0, 0, 0, 0, 0, 1394, - 1405, 1440, 1444, 1387, 0, 416, 0, 0, 0, 0, - 0, 0, 0, 1362, 0, 1414, 0, 0, 0, 1337, - 1329, 0, 0, 0, 0, 0, 0, 0, 1578, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4218, 0, 0, 0, - 0, 0, 0, 1392, 0, 0, 0, 0, 1342, 0, - 1363, 1441, 0, 1323, 313, 1334, 423, 273, 0, 477, - 1354, 319, 334, 1340, 1369, 1470, 1458, 1459, 1460, 1339, - 1448, 1465, 1388, 661, 1467, 1386, 1385, 1435, 1338, 1455, - 1378, 384, 1336, 349, 205, 233, 2022, 1376, 434, 485, - 497, 1454, 1453, 1359, 1370, 269, 1367, 495, 448, 636, - 243, 300, 482, 455, 493, 463, 303, 1413, 1433, 494, - 391, 617, 473, 633, 662, 663, 279, 428, 647, 551, - 655, 680, 234, 276, 442, 535, 639, 519, 417, 613, - 614, 348, 518, 311, 209, 388, 668, 232, 503, 390, - 253, 241, 619, 644, 315, 267, 305, 480, 675, 221, - 546, 630, 250, 507, 0, 0, 683, 258, 529, 642, - 631, 223, 626, 528, 413, 345, 346, 222, 2076, 481, - 284, 309, 0, 0, 274, 437, 621, 622, 272, 684, - 237, 654, 228, 1335, 653, 430, 616, 627, 414, 402, - 227, 625, 412, 401, 353, 374, 375, 296, 324, 470, - 394, 471, 323, 325, 425, 424, 426, 215, 640, 658, - 0, 216, 0, 524, 643, 685, 475, 220, 244, 245, - 248, 1353, 295, 299, 307, 310, 320, 321, 331, 386, - 441, 469, 465, 474, 1449, 610, 634, 648, 660, 666, - 667, 669, 670, 671, 672, 673, 676, 674, 429, 329, - 520, 352, 392, 1438, 1486, 447, 496, 251, 638, 521, - 240, 604, 418, 427, 259, 261, 260, 235, 512, 609, - 246, 266, 207, 1347, 1352, 1345, 0, 270, 271, 1419, - 605, 1348, 1346, 1408, 1409, 1349, 1477, 1478, 1479, 1463, - 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, - 696, 697, 698, 699, 700, 701, 702, 703, 681, 537, - 543, 538, 539, 540, 541, 542, 0, 544, 1442, 1341, - 0, 1350, 1351, 419, 1451, 623, 624, 704, 403, 510, - 635, 354, 368, 371, 360, 380, 0, 381, 356, 357, - 362, 365, 366, 367, 372, 373, 377, 383, 263, 218, - 410, 420, 608, 330, 224, 225, 226, 553, 554, 555, - 556, 651, 652, 656, 213, 486, 487, 488, 489, 308, - 646, 326, 492, 491, 350, 351, 398, 472, 569, 571, - 582, 586, 588, 590, 596, 599, 570, 572, 583, 587, - 589, 591, 597, 600, 559, 561, 563, 565, 578, 577, - 574, 602, 603, 580, 585, 564, 576, 581, 594, 601, - 598, 558, 562, 566, 575, 593, 592, 573, 584, 595, - 579, 567, 560, 568, 1412, 204, 229, 387, 1482, 478, - 304, 682, 650, 508, 645, 214, 231, 1344, 278, 1357, - 1366, 0, 1373, 1381, 1382, 1396, 1399, 1400, 1401, 1402, - 1420, 1421, 1423, 1432, 1434, 1437, 1439, 1446, 1464, 1485, - 206, 208, 217, 230, 242, 247, 254, 277, 292, 294, - 301, 314, 327, 328, 337, 338, 341, 347, 399, 406, - 407, 408, 409, 431, 432, 433, 436, 439, 440, 443, - 445, 446, 449, 454, 458, 459, 460, 462, 464, 466, - 479, 484, 498, 499, 500, 501, 502, 505, 506, 513, - 514, 515, 516, 517, 525, 526, 531, 532, 533, 534, - 545, 618, 620, 637, 657, 664, 504, 404, 452, 476, - 611, 1429, 1390, 317, 318, 467, 468, 332, 333, 678, - 679, 316, 632, 665, 629, 677, 659, 461, 397, 1411, - 1417, 400, 297, 322, 339, 1426, 649, 527, 236, 490, - 306, 265, 1445, 1447, 219, 257, 239, 275, 290, 293, - 343, 411, 421, 451, 457, 312, 287, 255, 483, 252, - 509, 548, 549, 550, 552, 415, 282, 456, 1407, 1436, - 395, 606, 607, 335, 1471, 1450, 557, 0, 1391, 1474, - 1356, 1377, 1484, 1380, 1383, 1428, 1331, 1406, 438, 1374, - 1360, 1326, 1368, 1327, 1358, 1393, 286, 1355, 1452, 1410, - 1473, 385, 283, 1333, 1324, 212, 530, 1361, 453, 1379, - 211, 1431, 511, 268, 396, 393, 615, 298, 289, 285, - 264, 336, 405, 450, 547, 444, 1480, 389, 1416, 0, - 522, 422, 0, 0, 0, 1457, 1456, 1384, 1395, 1462, - 1404, 1443, 1389, 1430, 1343, 1415, 1475, 1375, 1425, 1476, - 342, 262, 344, 210, 435, 523, 302, 0, 0, 0, - 0, 0, 536, 202, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1472, 1451, 557, 0, + 1392, 1475, 1357, 1378, 1485, 1381, 1384, 1429, 1332, 1407, + 438, 1375, 1361, 1327, 1369, 1328, 1359, 1394, 286, 1356, + 1453, 1411, 1474, 385, 283, 1334, 1325, 212, 530, 1362, + 453, 1380, 211, 1432, 511, 268, 396, 393, 615, 298, + 289, 285, 264, 336, 405, 450, 547, 444, 1481, 389, + 1417, 0, 522, 422, 0, 0, 0, 1458, 1457, 1385, + 1396, 1463, 1405, 1444, 1390, 1431, 1344, 1416, 1476, 1376, + 1426, 1477, 342, 262, 344, 210, 435, 523, 302, 0, + 2025, 0, 0, 4228, 536, 991, 0, 0, 0, 0, + 4229, 0, 0, 0, 0, 249, 0, 0, 256, 709, + 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, + 376, 382, 355, 364, 1372, 1423, 641, 1470, 1373, 1425, + 281, 340, 288, 280, 612, 1482, 1462, 1331, 1404, 1469, + 1399, 628, 0, 0, 238, 1473, 1398, 0, 1428, 0, + 1488, 1326, 1419, 0, 1329, 1333, 1484, 1467, 1365, 1366, + 291, 0, 0, 0, 0, 0, 0, 0, 1395, 1406, + 1441, 1445, 1388, 0, 416, 0, 0, 0, 0, 0, + 0, 0, 1363, 0, 1415, 0, 0, 0, 1338, 1330, + 0, 0, 0, 0, 0, 0, 0, 1579, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4226, 0, 0, 0, 0, + 0, 0, 1393, 0, 0, 0, 0, 1343, 0, 1364, + 1442, 0, 1324, 313, 1335, 423, 273, 0, 477, 1355, + 319, 334, 1341, 1370, 1471, 1459, 1460, 1461, 1340, 1449, + 1466, 1389, 661, 1468, 1387, 1386, 1436, 1339, 1456, 1379, + 384, 1337, 349, 205, 233, 2025, 1377, 434, 485, 497, + 1455, 1454, 1360, 1371, 269, 1368, 495, 448, 636, 243, + 300, 482, 455, 493, 463, 303, 1414, 1434, 494, 391, + 617, 473, 633, 662, 663, 279, 428, 647, 551, 655, + 680, 234, 276, 442, 535, 639, 519, 417, 613, 614, + 348, 518, 311, 209, 388, 668, 232, 503, 390, 253, + 241, 619, 644, 315, 267, 305, 480, 675, 221, 546, + 630, 250, 507, 0, 0, 683, 258, 529, 642, 631, + 223, 626, 528, 413, 345, 346, 222, 2079, 481, 284, + 309, 0, 0, 274, 437, 621, 622, 272, 684, 237, + 654, 228, 1336, 653, 430, 616, 627, 414, 402, 227, + 625, 412, 401, 353, 374, 375, 296, 324, 470, 394, + 471, 323, 325, 425, 424, 426, 215, 640, 658, 0, + 216, 0, 524, 643, 685, 475, 220, 244, 245, 248, + 1354, 295, 299, 307, 310, 320, 321, 331, 386, 441, + 469, 465, 474, 1450, 610, 634, 648, 660, 666, 667, + 669, 670, 671, 672, 673, 676, 674, 429, 329, 520, + 352, 392, 1439, 1487, 447, 496, 251, 638, 521, 240, + 604, 418, 427, 259, 261, 260, 235, 512, 609, 246, + 266, 207, 1348, 1353, 1346, 0, 270, 271, 1420, 605, + 1349, 1347, 1409, 1410, 1350, 1478, 1479, 1480, 1464, 686, + 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, + 697, 698, 699, 700, 701, 702, 703, 681, 537, 543, + 538, 539, 540, 541, 542, 0, 544, 1443, 1342, 0, + 1351, 1352, 419, 1452, 623, 624, 704, 403, 510, 635, + 354, 368, 371, 360, 380, 0, 381, 356, 357, 362, + 365, 366, 367, 372, 373, 377, 383, 263, 218, 410, + 420, 608, 330, 224, 225, 226, 553, 554, 555, 556, + 651, 652, 656, 213, 486, 487, 488, 489, 308, 646, + 326, 492, 491, 350, 351, 398, 472, 569, 571, 582, + 586, 588, 590, 596, 599, 570, 572, 583, 587, 589, + 591, 597, 600, 559, 561, 563, 565, 578, 577, 574, + 602, 603, 580, 585, 564, 576, 581, 594, 601, 598, + 558, 562, 566, 575, 593, 592, 573, 584, 595, 579, + 567, 560, 568, 1413, 204, 229, 387, 1483, 478, 304, + 682, 650, 508, 645, 214, 231, 1345, 278, 1358, 1367, + 0, 1374, 1382, 1383, 1397, 1400, 1401, 1402, 1403, 1421, + 1422, 1424, 1433, 1435, 1438, 1440, 1447, 1465, 1486, 206, + 208, 217, 230, 242, 247, 254, 277, 292, 294, 301, + 314, 327, 328, 337, 338, 341, 347, 399, 406, 407, + 408, 409, 431, 432, 433, 436, 439, 440, 443, 445, + 446, 449, 454, 458, 459, 460, 462, 464, 466, 479, + 484, 498, 499, 500, 501, 502, 505, 506, 513, 514, + 515, 516, 517, 525, 526, 531, 532, 533, 534, 545, + 618, 620, 637, 657, 664, 504, 404, 452, 476, 611, + 1430, 1391, 317, 318, 467, 468, 332, 333, 678, 679, + 316, 632, 665, 629, 677, 659, 461, 397, 1412, 1418, + 400, 297, 322, 339, 1427, 649, 527, 236, 490, 306, + 265, 1446, 1448, 219, 257, 239, 275, 290, 293, 343, + 411, 421, 451, 457, 312, 287, 255, 483, 252, 509, + 548, 549, 550, 552, 415, 282, 456, 1408, 1437, 395, + 606, 607, 335, 1472, 1451, 557, 0, 1392, 1475, 1357, + 1378, 1485, 1381, 1384, 1429, 1332, 1407, 438, 1375, 1361, + 1327, 1369, 1328, 1359, 1394, 286, 1356, 1453, 1411, 1474, + 385, 283, 1334, 1325, 212, 530, 1362, 453, 1380, 211, + 1432, 511, 268, 396, 393, 615, 298, 289, 285, 264, + 336, 405, 450, 547, 444, 1481, 389, 1417, 0, 522, + 422, 0, 0, 0, 1458, 1457, 1385, 1396, 1463, 1405, + 1444, 1390, 1431, 1344, 1416, 1476, 1376, 1426, 1477, 342, + 262, 344, 210, 435, 523, 302, 0, 0, 0, 0, + 0, 536, 202, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, + 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, + 364, 1372, 1423, 641, 1470, 1373, 1425, 281, 340, 288, + 280, 612, 1482, 1462, 1331, 1404, 1469, 1399, 628, 0, + 0, 238, 1473, 1398, 0, 1428, 0, 1488, 1326, 1419, + 0, 1329, 1333, 1484, 1467, 1365, 1366, 291, 0, 0, + 0, 0, 0, 0, 0, 1395, 1406, 1441, 1445, 1388, + 0, 416, 0, 0, 0, 0, 0, 3358, 0, 1363, + 0, 1415, 0, 0, 0, 1338, 1330, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1393, + 0, 0, 0, 0, 1343, 0, 1364, 1442, 0, 1324, + 313, 1335, 423, 273, 0, 477, 1355, 319, 334, 1341, + 1370, 1471, 1459, 1460, 1461, 1340, 1449, 1466, 1389, 661, + 1468, 1387, 1386, 1436, 1339, 1456, 1379, 384, 1337, 349, + 205, 233, 0, 1377, 434, 485, 497, 1455, 1454, 1360, + 1371, 269, 1368, 495, 448, 636, 243, 300, 482, 455, + 493, 463, 303, 1414, 1434, 494, 391, 617, 473, 633, + 662, 663, 279, 428, 647, 551, 655, 680, 234, 276, + 442, 535, 639, 519, 417, 613, 614, 348, 518, 311, + 209, 388, 668, 232, 503, 390, 253, 241, 619, 644, + 315, 267, 305, 480, 675, 221, 546, 630, 250, 507, + 0, 0, 683, 258, 529, 642, 631, 223, 626, 528, + 413, 345, 346, 222, 0, 481, 284, 309, 0, 0, + 274, 437, 621, 622, 272, 684, 237, 654, 228, 1336, + 653, 430, 616, 627, 414, 402, 227, 625, 412, 401, + 353, 374, 375, 296, 324, 470, 394, 471, 323, 325, + 425, 424, 426, 215, 640, 658, 0, 216, 0, 524, + 643, 685, 475, 220, 244, 245, 248, 1354, 295, 299, + 307, 310, 320, 321, 331, 386, 441, 469, 465, 474, + 1450, 610, 634, 648, 660, 666, 667, 669, 670, 671, + 672, 673, 676, 674, 429, 329, 520, 352, 392, 1439, + 1487, 447, 496, 251, 638, 521, 240, 604, 418, 427, + 259, 261, 260, 235, 512, 609, 246, 266, 207, 1348, + 1353, 1346, 0, 270, 271, 1420, 605, 1349, 1347, 1409, + 1410, 1350, 1478, 1479, 1480, 1464, 686, 687, 688, 689, + 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, + 700, 701, 702, 703, 681, 537, 543, 538, 539, 540, + 541, 542, 0, 544, 1443, 1342, 0, 1351, 1352, 419, + 1452, 623, 624, 704, 403, 510, 635, 354, 368, 371, + 360, 380, 0, 381, 356, 357, 362, 365, 366, 367, + 372, 373, 377, 383, 263, 218, 410, 420, 608, 330, + 224, 225, 226, 553, 554, 555, 556, 651, 652, 656, + 213, 486, 487, 488, 489, 308, 646, 326, 492, 491, + 350, 351, 398, 472, 569, 571, 582, 586, 588, 590, + 596, 599, 570, 572, 583, 587, 589, 591, 597, 600, + 559, 561, 563, 565, 578, 577, 574, 602, 603, 580, + 585, 564, 576, 581, 594, 601, 598, 558, 562, 566, + 575, 593, 592, 573, 584, 595, 579, 567, 560, 568, + 1413, 204, 229, 387, 1483, 478, 304, 682, 650, 508, + 645, 214, 231, 1345, 278, 1358, 1367, 0, 1374, 1382, + 1383, 1397, 1400, 1401, 1402, 1403, 1421, 1422, 1424, 1433, + 1435, 1438, 1440, 1447, 1465, 1486, 206, 208, 217, 230, + 242, 247, 254, 277, 292, 294, 301, 314, 327, 328, + 337, 338, 341, 347, 399, 406, 407, 408, 409, 431, + 432, 433, 436, 439, 440, 443, 445, 446, 449, 454, + 458, 459, 460, 462, 464, 466, 479, 484, 498, 499, + 500, 501, 502, 505, 506, 513, 514, 515, 516, 517, + 525, 526, 531, 532, 533, 534, 545, 618, 620, 637, + 657, 664, 504, 404, 452, 476, 611, 1430, 1391, 317, + 318, 467, 468, 332, 333, 678, 679, 316, 632, 665, + 629, 677, 659, 461, 397, 1412, 1418, 400, 297, 322, + 339, 1427, 649, 527, 236, 490, 306, 265, 1446, 1448, + 219, 257, 239, 275, 290, 293, 343, 411, 421, 451, + 457, 312, 287, 255, 483, 252, 509, 548, 549, 550, + 552, 415, 282, 456, 1408, 1437, 395, 606, 607, 335, + 1472, 1451, 557, 0, 1392, 1475, 1357, 1378, 1485, 1381, + 1384, 1429, 1332, 1407, 438, 1375, 1361, 1327, 1369, 1328, + 1359, 1394, 286, 1356, 1453, 1411, 1474, 385, 283, 1334, + 1325, 212, 530, 1362, 453, 1380, 211, 1432, 511, 268, + 396, 393, 615, 298, 289, 285, 264, 336, 405, 450, + 547, 444, 1481, 389, 1417, 0, 522, 422, 0, 0, + 0, 1458, 1457, 1385, 1396, 1463, 1405, 1444, 1390, 1431, + 1344, 1416, 1476, 1376, 1426, 1477, 342, 262, 344, 210, + 435, 523, 302, 0, 0, 0, 0, 0, 536, 756, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, + 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, + 359, 361, 363, 369, 376, 382, 355, 364, 1372, 1423, + 641, 1470, 1373, 1425, 281, 340, 288, 280, 612, 1482, + 1462, 1331, 1404, 1469, 1399, 628, 0, 0, 238, 1473, + 1398, 0, 1428, 0, 1488, 1326, 1419, 0, 1329, 1333, + 1484, 1467, 1365, 1366, 291, 0, 0, 0, 0, 0, + 0, 0, 1395, 1406, 1441, 1445, 1388, 0, 416, 0, + 0, 0, 0, 0, 3318, 0, 1363, 0, 1415, 0, + 0, 0, 1338, 1330, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1393, 0, 0, 0, + 0, 1343, 0, 1364, 1442, 0, 1324, 313, 1335, 423, + 273, 0, 477, 1355, 319, 334, 1341, 1370, 1471, 1459, + 1460, 1461, 1340, 1449, 1466, 1389, 661, 1468, 1387, 1386, + 1436, 1339, 1456, 1379, 384, 1337, 349, 205, 233, 0, + 1377, 434, 485, 497, 1455, 1454, 1360, 1371, 269, 1368, + 495, 448, 636, 243, 300, 482, 455, 493, 463, 303, + 1414, 1434, 494, 391, 617, 473, 633, 662, 663, 279, + 428, 647, 551, 655, 680, 234, 276, 442, 535, 639, + 519, 417, 613, 614, 348, 518, 311, 209, 388, 668, + 232, 503, 390, 253, 241, 619, 644, 315, 267, 305, + 480, 675, 221, 546, 630, 250, 507, 0, 0, 683, + 258, 529, 642, 631, 223, 626, 528, 413, 345, 346, + 222, 0, 481, 284, 309, 0, 0, 274, 437, 621, + 622, 272, 684, 237, 654, 228, 1336, 653, 430, 616, + 627, 414, 402, 227, 625, 412, 401, 353, 374, 375, + 296, 324, 470, 394, 471, 323, 325, 425, 424, 426, + 215, 640, 658, 0, 216, 0, 524, 643, 685, 475, + 220, 244, 245, 248, 1354, 295, 299, 307, 310, 320, + 321, 331, 386, 441, 469, 465, 474, 1450, 610, 634, + 648, 660, 666, 667, 669, 670, 671, 672, 673, 676, + 674, 429, 329, 520, 352, 392, 1439, 1487, 447, 496, + 251, 638, 521, 240, 604, 418, 427, 259, 261, 260, + 235, 512, 609, 246, 266, 207, 1348, 1353, 1346, 0, + 270, 271, 1420, 605, 1349, 1347, 1409, 1410, 1350, 1478, + 1479, 1480, 1464, 686, 687, 688, 689, 690, 691, 692, + 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, + 703, 681, 537, 543, 538, 539, 540, 541, 542, 0, + 544, 1443, 1342, 0, 1351, 1352, 419, 1452, 623, 624, + 704, 403, 510, 635, 354, 368, 371, 360, 380, 0, + 381, 356, 357, 362, 365, 366, 367, 372, 373, 377, + 383, 263, 218, 410, 420, 608, 330, 224, 225, 226, + 553, 554, 555, 556, 651, 652, 656, 213, 486, 487, + 488, 489, 308, 646, 326, 492, 491, 350, 351, 398, + 472, 569, 571, 582, 586, 588, 590, 596, 599, 570, + 572, 583, 587, 589, 591, 597, 600, 559, 561, 563, + 565, 578, 577, 574, 602, 603, 580, 585, 564, 576, + 581, 594, 601, 598, 558, 562, 566, 575, 593, 592, + 573, 584, 595, 579, 567, 560, 568, 1413, 204, 229, + 387, 1483, 478, 304, 682, 650, 508, 645, 214, 231, + 1345, 278, 1358, 1367, 0, 1374, 1382, 1383, 1397, 1400, + 1401, 1402, 1403, 1421, 1422, 1424, 1433, 1435, 1438, 1440, + 1447, 1465, 1486, 206, 208, 217, 230, 242, 247, 254, + 277, 292, 294, 301, 314, 327, 328, 337, 338, 341, + 347, 399, 406, 407, 408, 409, 431, 432, 433, 436, + 439, 440, 443, 445, 446, 449, 454, 458, 459, 460, + 462, 464, 466, 479, 484, 498, 499, 500, 501, 502, + 505, 506, 513, 514, 515, 516, 517, 525, 526, 531, + 532, 533, 534, 545, 618, 620, 637, 657, 664, 504, + 404, 452, 476, 611, 1430, 1391, 317, 318, 467, 468, + 332, 333, 678, 679, 316, 632, 665, 629, 677, 659, + 461, 397, 1412, 1418, 400, 297, 322, 339, 1427, 649, + 527, 236, 490, 306, 265, 1446, 1448, 219, 257, 239, + 275, 290, 293, 343, 411, 421, 451, 457, 312, 287, + 255, 483, 252, 509, 548, 549, 550, 552, 415, 282, + 456, 1408, 1437, 395, 606, 607, 335, 1472, 1451, 557, + 0, 1392, 1475, 1357, 1378, 1485, 1381, 1384, 1429, 1332, + 1407, 438, 1375, 1361, 1327, 1369, 1328, 1359, 1394, 286, + 1356, 1453, 1411, 1474, 385, 283, 1334, 1325, 212, 530, + 1362, 453, 1380, 211, 1432, 511, 268, 396, 393, 615, + 298, 289, 285, 264, 336, 405, 450, 547, 444, 1481, + 389, 1417, 0, 522, 422, 0, 0, 0, 1458, 1457, + 1385, 1396, 1463, 1405, 1444, 1390, 1431, 1344, 1416, 1476, + 1376, 1426, 1477, 342, 262, 344, 210, 435, 523, 302, + 0, 0, 0, 0, 0, 536, 991, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, + 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, + 369, 376, 382, 355, 364, 1372, 1423, 641, 1470, 1373, + 1425, 281, 340, 288, 280, 612, 1482, 1462, 1331, 1404, + 1469, 1399, 628, 0, 0, 238, 1473, 1398, 0, 1428, + 0, 1488, 1326, 1419, 0, 1329, 1333, 1484, 1467, 1365, + 1366, 291, 0, 0, 0, 0, 0, 0, 0, 1395, + 1406, 1441, 1445, 1388, 0, 416, 0, 0, 0, 0, + 0, 2491, 0, 1363, 0, 1415, 0, 0, 0, 1338, + 1330, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1393, 0, 0, 0, 0, 1343, 0, + 1364, 1442, 0, 1324, 313, 1335, 423, 273, 0, 477, + 1355, 319, 334, 1341, 1370, 1471, 1459, 1460, 1461, 1340, + 1449, 1466, 1389, 661, 1468, 1387, 1386, 1436, 1339, 1456, + 1379, 384, 1337, 349, 205, 233, 0, 1377, 434, 485, + 497, 1455, 1454, 1360, 1371, 269, 1368, 495, 448, 636, + 243, 300, 482, 455, 493, 463, 303, 1414, 1434, 494, + 391, 617, 473, 633, 662, 663, 279, 428, 647, 551, + 655, 680, 234, 276, 442, 535, 639, 519, 417, 613, + 614, 348, 518, 311, 209, 388, 668, 232, 503, 390, + 253, 241, 619, 644, 315, 267, 305, 480, 675, 221, + 546, 630, 250, 507, 0, 0, 683, 258, 529, 642, + 631, 223, 626, 528, 413, 345, 346, 222, 0, 481, + 284, 309, 0, 0, 274, 437, 621, 622, 272, 684, + 237, 654, 228, 1336, 653, 430, 616, 627, 414, 402, + 227, 625, 412, 401, 353, 374, 375, 296, 324, 470, + 394, 471, 323, 325, 425, 424, 426, 215, 640, 658, + 0, 216, 0, 524, 643, 685, 475, 220, 244, 245, + 248, 1354, 295, 299, 307, 310, 320, 321, 331, 386, + 441, 469, 465, 474, 1450, 610, 634, 648, 660, 666, + 667, 669, 670, 671, 672, 673, 676, 674, 429, 329, + 520, 352, 392, 1439, 1487, 447, 496, 251, 638, 521, + 240, 604, 418, 427, 259, 261, 260, 235, 512, 609, + 246, 266, 207, 1348, 1353, 1346, 0, 270, 271, 1420, + 605, 1349, 1347, 1409, 1410, 1350, 1478, 1479, 1480, 1464, + 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, + 696, 697, 698, 699, 700, 701, 702, 703, 681, 537, + 543, 538, 539, 540, 541, 542, 0, 544, 1443, 1342, + 0, 1351, 1352, 419, 1452, 623, 624, 704, 403, 510, + 635, 354, 368, 371, 360, 380, 0, 381, 356, 357, + 362, 365, 366, 367, 372, 373, 377, 383, 263, 218, + 410, 420, 608, 330, 224, 225, 226, 553, 554, 555, + 556, 651, 652, 656, 213, 486, 487, 488, 489, 308, + 646, 326, 492, 491, 350, 351, 398, 472, 569, 571, + 582, 586, 588, 590, 596, 599, 570, 572, 583, 587, + 589, 591, 597, 600, 559, 561, 563, 565, 578, 577, + 574, 602, 603, 580, 585, 564, 576, 581, 594, 601, + 598, 558, 562, 566, 575, 593, 592, 573, 584, 595, + 579, 567, 560, 568, 1413, 204, 229, 387, 1483, 478, + 304, 682, 650, 508, 645, 214, 231, 1345, 278, 1358, + 1367, 0, 1374, 1382, 1383, 1397, 1400, 1401, 1402, 1403, + 1421, 1422, 1424, 1433, 1435, 1438, 1440, 1447, 1465, 1486, + 206, 208, 217, 230, 242, 247, 254, 277, 292, 294, + 301, 314, 327, 328, 337, 338, 341, 347, 399, 406, + 407, 408, 409, 431, 432, 433, 436, 439, 440, 443, + 445, 446, 449, 454, 458, 459, 460, 462, 464, 466, + 479, 484, 498, 499, 500, 501, 502, 505, 506, 513, + 514, 515, 516, 517, 525, 526, 531, 532, 533, 534, + 545, 618, 620, 637, 657, 664, 504, 404, 452, 476, + 611, 1430, 1391, 317, 318, 467, 468, 332, 333, 678, + 679, 316, 632, 665, 629, 677, 659, 461, 397, 1412, + 1418, 400, 297, 322, 339, 1427, 649, 527, 236, 490, + 306, 265, 1446, 1448, 219, 257, 239, 275, 290, 293, + 343, 411, 421, 451, 457, 312, 287, 255, 483, 252, + 509, 548, 549, 550, 552, 415, 282, 456, 1408, 1437, + 395, 606, 607, 335, 1472, 1451, 557, 0, 1392, 1475, + 1357, 1378, 1485, 1381, 1384, 1429, 1332, 1407, 438, 1375, + 1361, 1327, 1369, 1328, 1359, 1394, 286, 1356, 1453, 1411, + 1474, 385, 283, 1334, 1325, 212, 530, 1362, 453, 1380, + 211, 1432, 511, 268, 396, 393, 615, 298, 289, 285, + 264, 336, 405, 450, 547, 444, 1481, 389, 1417, 0, + 522, 422, 0, 0, 0, 1458, 1457, 1385, 1396, 1463, + 1405, 1444, 1390, 1431, 1344, 1416, 1476, 1376, 1426, 1477, + 342, 262, 344, 210, 435, 523, 302, 0, 101, 0, + 0, 0, 536, 756, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, - 355, 364, 1371, 1422, 641, 1469, 1372, 1424, 281, 340, - 288, 280, 612, 1481, 1461, 1330, 1403, 1468, 1398, 628, - 0, 0, 238, 1472, 1397, 0, 1427, 0, 1487, 1325, - 1418, 0, 1328, 1332, 1483, 1466, 1364, 1365, 291, 0, - 0, 0, 0, 0, 0, 0, 1394, 1405, 1440, 1444, - 1387, 0, 416, 0, 0, 0, 0, 0, 3350, 0, - 1362, 0, 1414, 0, 0, 0, 1337, 1329, 0, 0, + 355, 364, 1372, 1423, 641, 1470, 1373, 1425, 281, 340, + 288, 280, 612, 1482, 1462, 1331, 1404, 1469, 1399, 628, + 0, 0, 238, 1473, 1398, 0, 1428, 0, 1488, 1326, + 1419, 0, 1329, 1333, 1484, 1467, 1365, 1366, 291, 0, + 0, 0, 0, 0, 0, 0, 1395, 1406, 1441, 1445, + 1388, 0, 416, 0, 0, 0, 0, 0, 0, 0, + 1363, 0, 1415, 0, 0, 0, 1338, 1330, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1392, 0, 0, 0, 0, 1342, 0, 1363, 1441, 0, - 1323, 313, 1334, 423, 273, 0, 477, 1354, 319, 334, - 1340, 1369, 1470, 1458, 1459, 1460, 1339, 1448, 1465, 1388, - 661, 1467, 1386, 1385, 1435, 1338, 1455, 1378, 384, 1336, - 349, 205, 233, 0, 1376, 434, 485, 497, 1454, 1453, - 1359, 1370, 269, 1367, 495, 448, 636, 243, 300, 482, - 455, 493, 463, 303, 1413, 1433, 494, 391, 617, 473, + 1393, 0, 0, 0, 0, 1343, 0, 1364, 1442, 0, + 1324, 313, 1335, 423, 273, 0, 477, 1355, 319, 334, + 1341, 1370, 1471, 1459, 1460, 1461, 1340, 1449, 1466, 1389, + 661, 1468, 1387, 1386, 1436, 1339, 1456, 1379, 384, 1337, + 349, 205, 233, 0, 1377, 434, 485, 497, 1455, 1454, + 1360, 1371, 269, 1368, 495, 448, 636, 243, 300, 482, + 455, 493, 463, 303, 1414, 1434, 494, 391, 617, 473, 633, 662, 663, 279, 428, 647, 551, 655, 680, 234, 276, 442, 535, 639, 519, 417, 613, 614, 348, 518, 311, 209, 388, 668, 232, 503, 390, 253, 241, 619, @@ -3298,21 +3508,21 @@ var yyAct = [...]int{ 507, 0, 0, 683, 258, 529, 642, 631, 223, 626, 528, 413, 345, 346, 222, 0, 481, 284, 309, 0, 0, 274, 437, 621, 622, 272, 684, 237, 654, 228, - 1335, 653, 430, 616, 627, 414, 402, 227, 625, 412, + 1336, 653, 430, 616, 627, 414, 402, 227, 625, 412, 401, 353, 374, 375, 296, 324, 470, 394, 471, 323, 325, 425, 424, 426, 215, 640, 658, 0, 216, 0, - 524, 643, 685, 475, 220, 244, 245, 248, 1353, 295, + 524, 643, 685, 475, 220, 244, 245, 248, 1354, 295, 299, 307, 310, 320, 321, 331, 386, 441, 469, 465, - 474, 1449, 610, 634, 648, 660, 666, 667, 669, 670, + 474, 1450, 610, 634, 648, 660, 666, 667, 669, 670, 671, 672, 673, 676, 674, 429, 329, 520, 352, 392, - 1438, 1486, 447, 496, 251, 638, 521, 240, 604, 418, + 1439, 1487, 447, 496, 251, 638, 521, 240, 604, 418, 427, 259, 261, 260, 235, 512, 609, 246, 266, 207, - 1347, 1352, 1345, 0, 270, 271, 1419, 605, 1348, 1346, - 1408, 1409, 1349, 1477, 1478, 1479, 1463, 686, 687, 688, + 1348, 1353, 1346, 0, 270, 271, 1420, 605, 1349, 1347, + 1409, 1410, 1350, 1478, 1479, 1480, 1464, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 681, 537, 543, 538, 539, - 540, 541, 542, 0, 544, 1442, 1341, 0, 1350, 1351, - 419, 1451, 623, 624, 704, 403, 510, 635, 354, 368, + 540, 541, 542, 0, 544, 1443, 1342, 0, 1351, 1352, + 419, 1452, 623, 624, 704, 403, 510, 635, 354, 368, 371, 360, 380, 0, 381, 356, 357, 362, 365, 366, 367, 372, 373, 377, 383, 263, 218, 410, 420, 608, 330, 224, 225, 226, 553, 554, 555, 556, 651, 652, @@ -3322,74 +3532,74 @@ var yyAct = [...]int{ 600, 559, 561, 563, 565, 578, 577, 574, 602, 603, 580, 585, 564, 576, 581, 594, 601, 598, 558, 562, 566, 575, 593, 592, 573, 584, 595, 579, 567, 560, - 568, 1412, 204, 229, 387, 1482, 478, 304, 682, 650, - 508, 645, 214, 231, 1344, 278, 1357, 1366, 0, 1373, - 1381, 1382, 1396, 1399, 1400, 1401, 1402, 1420, 1421, 1423, - 1432, 1434, 1437, 1439, 1446, 1464, 1485, 206, 208, 217, + 568, 1413, 204, 229, 387, 1483, 478, 304, 682, 650, + 508, 645, 214, 231, 1345, 278, 1358, 1367, 0, 1374, + 1382, 1383, 1397, 1400, 1401, 1402, 1403, 1421, 1422, 1424, + 1433, 1435, 1438, 1440, 1447, 1465, 1486, 206, 208, 217, 230, 242, 247, 254, 277, 292, 294, 301, 314, 327, 328, 337, 338, 341, 347, 399, 406, 407, 408, 409, 431, 432, 433, 436, 439, 440, 443, 445, 446, 449, 454, 458, 459, 460, 462, 464, 466, 479, 484, 498, 499, 500, 501, 502, 505, 506, 513, 514, 515, 516, 517, 525, 526, 531, 532, 533, 534, 545, 618, 620, - 637, 657, 664, 504, 404, 452, 476, 611, 1429, 1390, + 637, 657, 664, 504, 404, 452, 476, 611, 1430, 1391, 317, 318, 467, 468, 332, 333, 678, 679, 316, 632, - 665, 629, 677, 659, 461, 397, 1411, 1417, 400, 297, - 322, 339, 1426, 649, 527, 236, 490, 306, 265, 1445, - 1447, 219, 257, 239, 275, 290, 293, 343, 411, 421, + 665, 629, 677, 659, 461, 397, 1412, 1418, 400, 297, + 322, 339, 1427, 649, 527, 236, 490, 306, 265, 1446, + 1448, 219, 257, 239, 275, 290, 293, 343, 411, 421, 451, 457, 312, 287, 255, 483, 252, 509, 548, 549, - 550, 552, 415, 282, 456, 1407, 1436, 395, 606, 607, - 335, 1471, 1450, 557, 0, 1391, 1474, 1356, 1377, 1484, - 1380, 1383, 1428, 1331, 1406, 438, 1374, 1360, 1326, 1368, - 1327, 1358, 1393, 286, 1355, 1452, 1410, 1473, 385, 283, - 1333, 1324, 212, 530, 1361, 453, 1379, 211, 1431, 511, + 550, 552, 415, 282, 456, 1408, 1437, 395, 606, 607, + 335, 1472, 1451, 557, 0, 1392, 1475, 1357, 1378, 1485, + 1381, 1384, 1429, 1332, 1407, 438, 1375, 1361, 1327, 1369, + 1328, 1359, 1394, 286, 1356, 1453, 1411, 1474, 385, 283, + 1334, 1325, 212, 530, 1362, 453, 1380, 211, 1432, 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, - 450, 547, 444, 1480, 389, 1416, 0, 522, 422, 0, - 0, 0, 1457, 1456, 1384, 1395, 1462, 1404, 1443, 1389, - 1430, 1343, 1415, 1475, 1375, 1425, 1476, 342, 262, 344, + 450, 547, 444, 1481, 389, 1417, 0, 522, 422, 0, + 0, 0, 1458, 1457, 1385, 1396, 1463, 1405, 1444, 1390, + 1431, 1344, 1416, 1476, 1376, 1426, 1477, 342, 262, 344, 210, 435, 523, 302, 0, 0, 0, 0, 0, 536, - 756, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, - 358, 359, 361, 363, 369, 376, 382, 355, 364, 1371, - 1422, 641, 1469, 1372, 1424, 281, 340, 288, 280, 612, - 1481, 1461, 1330, 1403, 1468, 1398, 628, 0, 0, 238, - 1472, 1397, 0, 1427, 0, 1487, 1325, 1418, 0, 1328, - 1332, 1483, 1466, 1364, 1365, 291, 0, 0, 0, 0, - 0, 0, 0, 1394, 1405, 1440, 1444, 1387, 0, 416, - 0, 0, 0, 0, 0, 3311, 0, 1362, 0, 1414, - 0, 0, 0, 1337, 1329, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1392, 0, 0, - 0, 0, 1342, 0, 1363, 1441, 0, 1323, 313, 1334, - 423, 273, 0, 477, 1354, 319, 334, 1340, 1369, 1470, - 1458, 1459, 1460, 1339, 1448, 1465, 1388, 661, 1467, 1386, - 1385, 1435, 1338, 1455, 1378, 384, 1336, 349, 205, 233, - 0, 1376, 434, 485, 497, 1454, 1453, 1359, 1370, 269, - 1367, 495, 448, 636, 243, 300, 482, 455, 493, 463, - 303, 1413, 1433, 494, 391, 617, 473, 633, 662, 663, + 358, 359, 361, 363, 369, 376, 382, 355, 364, 1372, + 1423, 641, 1470, 1373, 1425, 281, 340, 288, 280, 612, + 1482, 1462, 1331, 1404, 1469, 1399, 628, 0, 0, 238, + 1473, 1398, 0, 1428, 0, 1488, 1326, 1419, 0, 1329, + 1333, 1484, 1467, 1365, 1366, 291, 0, 0, 0, 0, + 0, 0, 0, 1395, 1406, 1441, 1445, 1388, 0, 416, + 0, 0, 0, 0, 0, 0, 0, 1363, 0, 1415, + 0, 0, 0, 1338, 1330, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1393, 0, 0, + 0, 0, 1343, 0, 1364, 1442, 0, 1324, 313, 1335, + 423, 273, 0, 477, 1355, 319, 334, 1341, 1370, 1471, + 1459, 1460, 1461, 1340, 1449, 1466, 1389, 661, 1468, 1387, + 1386, 1436, 1339, 1456, 1379, 384, 1337, 349, 205, 233, + 0, 1377, 434, 485, 497, 1455, 1454, 1360, 1371, 269, + 1368, 495, 448, 636, 243, 300, 482, 455, 493, 463, + 303, 1414, 1434, 494, 391, 617, 473, 633, 662, 663, 279, 428, 647, 551, 655, 680, 234, 276, 442, 535, 639, 519, 417, 613, 614, 348, 518, 311, 209, 388, 668, 232, 503, 390, 253, 241, 619, 644, 315, 267, 305, 480, 675, 221, 546, 630, 250, 507, 0, 0, 683, 258, 529, 642, 631, 223, 626, 528, 413, 345, 346, 222, 0, 481, 284, 309, 0, 0, 274, 437, - 621, 622, 272, 684, 237, 654, 228, 1335, 653, 430, + 621, 622, 272, 684, 237, 654, 228, 1336, 653, 430, 616, 627, 414, 402, 227, 625, 412, 401, 353, 374, 375, 296, 324, 470, 394, 471, 323, 325, 425, 424, 426, 215, 640, 658, 0, 216, 0, 524, 643, 685, - 475, 220, 244, 245, 248, 1353, 295, 299, 307, 310, - 320, 321, 331, 386, 441, 469, 465, 474, 1449, 610, + 475, 220, 244, 245, 248, 1354, 295, 299, 307, 310, + 320, 321, 331, 386, 441, 469, 465, 474, 1450, 610, 634, 648, 660, 666, 667, 669, 670, 671, 672, 673, - 676, 674, 429, 329, 520, 352, 392, 1438, 1486, 447, + 676, 674, 429, 329, 520, 352, 392, 1439, 1487, 447, 496, 251, 638, 521, 240, 604, 418, 427, 259, 261, - 260, 235, 512, 609, 246, 266, 207, 1347, 1352, 1345, - 0, 270, 271, 1419, 605, 1348, 1346, 1408, 1409, 1349, - 1477, 1478, 1479, 1463, 686, 687, 688, 689, 690, 691, + 260, 235, 512, 609, 246, 266, 207, 1348, 1353, 1346, + 0, 270, 271, 1420, 605, 1349, 1347, 1409, 1410, 1350, + 1478, 1479, 1480, 1464, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 681, 537, 543, 538, 539, 540, 541, 542, - 0, 544, 1442, 1341, 0, 1350, 1351, 419, 1451, 623, + 0, 544, 1443, 1342, 0, 1351, 1352, 419, 1452, 623, 624, 704, 403, 510, 635, 354, 368, 371, 360, 380, 0, 381, 356, 357, 362, 365, 366, 367, 372, 373, 377, 383, 263, 218, 410, 420, 608, 330, 224, 225, @@ -3399,53 +3609,53 @@ var yyAct = [...]int{ 570, 572, 583, 587, 589, 591, 597, 600, 559, 561, 563, 565, 578, 577, 574, 602, 603, 580, 585, 564, 576, 581, 594, 601, 598, 558, 562, 566, 575, 593, - 592, 573, 584, 595, 579, 567, 560, 568, 1412, 204, - 229, 387, 1482, 478, 304, 682, 650, 508, 645, 214, - 231, 1344, 278, 1357, 1366, 0, 1373, 1381, 1382, 1396, - 1399, 1400, 1401, 1402, 1420, 1421, 1423, 1432, 1434, 1437, - 1439, 1446, 1464, 1485, 206, 208, 217, 230, 242, 247, + 592, 573, 584, 595, 579, 567, 560, 568, 1413, 204, + 229, 387, 1483, 478, 304, 682, 650, 508, 645, 214, + 231, 1345, 278, 1358, 1367, 0, 1374, 1382, 1383, 1397, + 1400, 1401, 1402, 1403, 1421, 1422, 1424, 1433, 1435, 1438, + 1440, 1447, 1465, 1486, 206, 208, 217, 230, 242, 247, 254, 277, 292, 294, 301, 314, 327, 328, 337, 338, 341, 347, 399, 406, 407, 408, 409, 431, 432, 433, 436, 439, 440, 443, 445, 446, 449, 454, 458, 459, 460, 462, 464, 466, 479, 484, 498, 499, 500, 501, 502, 505, 506, 513, 514, 515, 516, 517, 525, 526, 531, 532, 533, 534, 545, 618, 620, 637, 657, 664, - 504, 404, 452, 476, 611, 1429, 1390, 317, 318, 467, + 504, 404, 452, 476, 611, 1430, 1391, 317, 318, 467, 468, 332, 333, 678, 679, 316, 632, 665, 629, 677, - 659, 461, 397, 1411, 1417, 400, 297, 322, 339, 1426, - 649, 527, 236, 490, 306, 265, 1445, 1447, 219, 257, + 659, 461, 397, 1412, 1418, 400, 297, 322, 339, 1427, + 649, 527, 236, 490, 306, 265, 1446, 1448, 219, 257, 239, 275, 290, 293, 343, 411, 421, 451, 457, 312, 287, 255, 483, 252, 509, 548, 549, 550, 552, 415, - 282, 456, 1407, 1436, 395, 606, 607, 335, 1471, 1450, - 557, 0, 1391, 1474, 1356, 1377, 1484, 1380, 1383, 1428, - 1331, 1406, 438, 1374, 1360, 1326, 1368, 1327, 1358, 1393, - 286, 1355, 1452, 1410, 1473, 385, 283, 1333, 1324, 212, - 530, 1361, 453, 1379, 211, 1431, 511, 268, 396, 393, + 282, 456, 1408, 1437, 395, 606, 607, 335, 1472, 1451, + 557, 0, 1392, 1475, 1357, 1378, 1485, 1381, 1384, 1429, + 1332, 1407, 438, 1375, 1361, 1327, 1369, 1328, 1359, 1394, + 286, 1356, 1453, 1411, 1474, 385, 283, 1334, 1325, 212, + 530, 1362, 453, 1380, 211, 1432, 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, 450, 547, 444, - 1480, 389, 1416, 0, 522, 422, 0, 0, 0, 1457, - 1456, 1384, 1395, 1462, 1404, 1443, 1389, 1430, 1343, 1415, - 1475, 1375, 1425, 1476, 342, 262, 344, 210, 435, 523, - 302, 0, 0, 0, 0, 0, 536, 991, 0, 0, + 1481, 389, 1417, 0, 522, 422, 0, 0, 0, 1458, + 1457, 1385, 1396, 1463, 1405, 1444, 1390, 1431, 1344, 1416, + 1476, 1376, 1426, 1477, 342, 262, 344, 210, 435, 523, + 302, 0, 0, 0, 0, 0, 536, 756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, - 363, 369, 376, 382, 355, 364, 1371, 1422, 641, 1469, - 1372, 1424, 281, 340, 288, 280, 612, 1481, 1461, 1330, - 1403, 1468, 1398, 628, 0, 0, 238, 1472, 1397, 0, - 1427, 0, 1487, 1325, 1418, 0, 1328, 1332, 1483, 1466, - 1364, 1365, 291, 0, 0, 0, 0, 0, 0, 0, - 1394, 1405, 1440, 1444, 1387, 0, 416, 0, 0, 0, - 0, 0, 2486, 0, 1362, 0, 1414, 0, 0, 0, - 1337, 1329, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1392, 0, 0, 0, 0, 1342, - 0, 1363, 1441, 0, 1323, 313, 1334, 423, 273, 0, - 477, 1354, 319, 334, 1340, 1369, 1470, 1458, 1459, 1460, - 1339, 1448, 1465, 1388, 661, 1467, 1386, 1385, 1435, 1338, - 1455, 1378, 384, 1336, 349, 205, 233, 0, 1376, 434, - 485, 497, 1454, 1453, 1359, 1370, 269, 1367, 495, 448, - 636, 243, 300, 482, 455, 493, 463, 303, 1413, 1433, + 363, 369, 376, 382, 355, 364, 1372, 1423, 641, 1470, + 1373, 1425, 281, 340, 288, 280, 612, 1482, 1462, 1331, + 1404, 1469, 1399, 628, 0, 0, 238, 1473, 1398, 0, + 1428, 0, 1488, 1326, 1419, 0, 1329, 1333, 1484, 1467, + 1365, 1366, 291, 0, 0, 0, 0, 0, 0, 0, + 1395, 1406, 1441, 1445, 1388, 0, 416, 0, 0, 0, + 0, 0, 0, 0, 1363, 0, 1415, 0, 0, 0, + 1338, 1330, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1393, 0, 0, 0, 0, 1343, + 0, 1364, 1442, 0, 1324, 313, 1335, 423, 273, 0, + 477, 1355, 319, 334, 1341, 1370, 1471, 1459, 1460, 1461, + 1340, 1449, 1466, 1389, 661, 1468, 1387, 1386, 1436, 1339, + 1456, 1379, 384, 1337, 349, 205, 233, 0, 1377, 434, + 485, 497, 1455, 1454, 1360, 1371, 269, 1368, 495, 448, + 636, 243, 300, 482, 455, 493, 463, 303, 1414, 1434, 494, 391, 617, 473, 633, 662, 663, 279, 428, 647, 551, 655, 680, 234, 276, 442, 535, 639, 519, 417, 613, 614, 348, 518, 311, 209, 388, 668, 232, 503, @@ -3453,21 +3663,21 @@ var yyAct = [...]int{ 221, 546, 630, 250, 507, 0, 0, 683, 258, 529, 642, 631, 223, 626, 528, 413, 345, 346, 222, 0, 481, 284, 309, 0, 0, 274, 437, 621, 622, 272, - 684, 237, 654, 228, 1335, 653, 430, 616, 627, 414, + 684, 237, 654, 228, 1336, 653, 430, 616, 627, 414, 402, 227, 625, 412, 401, 353, 374, 375, 296, 324, 470, 394, 471, 323, 325, 425, 424, 426, 215, 640, 658, 0, 216, 0, 524, 643, 685, 475, 220, 244, - 245, 248, 1353, 295, 299, 307, 310, 320, 321, 331, - 386, 441, 469, 465, 474, 1449, 610, 634, 648, 660, + 245, 248, 1354, 295, 299, 307, 310, 320, 321, 331, + 386, 441, 469, 465, 474, 1450, 610, 634, 648, 660, 666, 667, 669, 670, 671, 672, 673, 676, 674, 429, - 329, 520, 352, 392, 1438, 1486, 447, 496, 251, 638, + 329, 520, 352, 392, 1439, 1487, 447, 496, 251, 638, 521, 240, 604, 418, 427, 259, 261, 260, 235, 512, - 609, 246, 266, 207, 1347, 1352, 1345, 0, 270, 271, - 1419, 605, 1348, 1346, 1408, 1409, 1349, 1477, 1478, 1479, - 1463, 686, 687, 688, 689, 690, 691, 692, 693, 694, + 609, 246, 266, 207, 1348, 1353, 1346, 0, 270, 271, + 1420, 605, 1349, 1347, 1409, 1410, 1350, 1478, 1479, 1480, + 1464, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 681, - 537, 543, 538, 539, 540, 541, 542, 0, 544, 1442, - 1341, 0, 1350, 1351, 419, 1451, 623, 624, 704, 403, + 537, 543, 538, 539, 540, 541, 542, 0, 544, 1443, + 1342, 0, 1351, 1352, 419, 1452, 623, 624, 704, 403, 510, 635, 354, 368, 371, 360, 380, 0, 381, 356, 357, 362, 365, 366, 367, 372, 373, 377, 383, 263, 218, 410, 420, 608, 330, 224, 225, 226, 553, 554, @@ -3477,53 +3687,53 @@ var yyAct = [...]int{ 587, 589, 591, 597, 600, 559, 561, 563, 565, 578, 577, 574, 602, 603, 580, 585, 564, 576, 581, 594, 601, 598, 558, 562, 566, 575, 593, 592, 573, 584, - 595, 579, 567, 560, 568, 1412, 204, 229, 387, 1482, - 478, 304, 682, 650, 508, 645, 214, 231, 1344, 278, - 1357, 1366, 0, 1373, 1381, 1382, 1396, 1399, 1400, 1401, - 1402, 1420, 1421, 1423, 1432, 1434, 1437, 1439, 1446, 1464, - 1485, 206, 208, 217, 230, 242, 247, 254, 277, 292, + 595, 579, 567, 560, 568, 1413, 204, 229, 387, 1483, + 478, 304, 682, 650, 508, 645, 214, 231, 1345, 278, + 1358, 1367, 0, 1374, 1382, 1383, 1397, 1400, 1401, 1402, + 1403, 1421, 1422, 1424, 1433, 1435, 1438, 1440, 1447, 1465, + 1486, 206, 208, 217, 230, 242, 247, 254, 277, 292, 294, 301, 314, 327, 328, 337, 338, 341, 347, 399, 406, 407, 408, 409, 431, 432, 433, 436, 439, 440, 443, 445, 446, 449, 454, 458, 459, 460, 462, 464, 466, 479, 484, 498, 499, 500, 501, 502, 505, 506, 513, 514, 515, 516, 517, 525, 526, 531, 532, 533, 534, 545, 618, 620, 637, 657, 664, 504, 404, 452, - 476, 611, 1429, 1390, 317, 318, 467, 468, 332, 333, + 476, 611, 1430, 1391, 317, 318, 467, 468, 332, 333, 678, 679, 316, 632, 665, 629, 677, 659, 461, 397, - 1411, 1417, 400, 297, 322, 339, 1426, 649, 527, 236, - 490, 306, 265, 1445, 1447, 219, 257, 239, 275, 290, + 1412, 1418, 400, 297, 322, 339, 1427, 649, 527, 236, + 490, 306, 265, 1446, 1448, 219, 257, 239, 275, 290, 293, 343, 411, 421, 451, 457, 312, 287, 255, 483, - 252, 509, 548, 549, 550, 552, 415, 282, 456, 1407, - 1436, 395, 606, 607, 335, 1471, 1450, 557, 0, 1391, - 1474, 1356, 1377, 1484, 1380, 1383, 1428, 1331, 1406, 438, - 1374, 1360, 1326, 1368, 1327, 1358, 1393, 286, 1355, 1452, - 1410, 1473, 385, 283, 1333, 1324, 212, 530, 1361, 453, - 1379, 211, 1431, 511, 268, 396, 393, 615, 298, 289, - 285, 264, 336, 405, 450, 547, 444, 1480, 389, 1416, - 0, 522, 422, 0, 0, 0, 1457, 1456, 1384, 1395, - 1462, 1404, 1443, 1389, 1430, 1343, 1415, 1475, 1375, 1425, - 1476, 342, 262, 344, 210, 435, 523, 302, 0, 101, - 0, 0, 0, 536, 756, 0, 0, 0, 0, 0, + 252, 509, 548, 549, 550, 552, 415, 282, 456, 1408, + 1437, 395, 606, 607, 335, 1472, 1451, 557, 0, 1392, + 1475, 1357, 1378, 1485, 1381, 1384, 1429, 1332, 1407, 438, + 1375, 1361, 1327, 1369, 1328, 1359, 1394, 286, 1356, 1453, + 1411, 1474, 385, 283, 1334, 1325, 212, 530, 1362, 453, + 1380, 211, 1432, 511, 268, 396, 393, 615, 298, 289, + 285, 264, 336, 405, 450, 547, 444, 1481, 389, 1417, + 0, 522, 422, 0, 0, 0, 1458, 1457, 1385, 1396, + 1463, 1405, 1444, 1390, 1431, 1344, 1416, 1476, 1376, 1426, + 1477, 342, 262, 344, 210, 435, 523, 302, 0, 0, + 0, 0, 0, 536, 991, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, - 382, 355, 364, 1371, 1422, 641, 1469, 1372, 1424, 281, - 340, 288, 280, 612, 1481, 1461, 1330, 1403, 1468, 1398, - 628, 0, 0, 238, 1472, 1397, 0, 1427, 0, 1487, - 1325, 1418, 0, 1328, 1332, 1483, 1466, 1364, 1365, 291, - 0, 0, 0, 0, 0, 0, 0, 1394, 1405, 1440, - 1444, 1387, 0, 416, 0, 0, 0, 0, 0, 0, - 0, 1362, 0, 1414, 0, 0, 0, 1337, 1329, 0, + 382, 355, 364, 1372, 1423, 641, 1470, 1373, 1425, 281, + 340, 288, 280, 612, 1482, 1462, 1331, 1404, 1469, 1399, + 628, 0, 0, 238, 1473, 1398, 0, 1428, 0, 1488, + 1326, 1419, 0, 1329, 1333, 1484, 1467, 1365, 1366, 291, + 0, 0, 0, 0, 0, 0, 0, 1395, 1406, 1441, + 1445, 1388, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 1363, 0, 1415, 0, 0, 0, 1338, 1330, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1392, 0, 0, 0, 0, 1342, 0, 1363, 1441, - 0, 1323, 313, 1334, 423, 273, 0, 477, 1354, 319, - 334, 1340, 1369, 1470, 1458, 1459, 1460, 1339, 1448, 1465, - 1388, 661, 1467, 1386, 1385, 1435, 1338, 1455, 1378, 384, - 1336, 349, 205, 233, 0, 1376, 434, 485, 497, 1454, - 1453, 1359, 1370, 269, 1367, 495, 448, 636, 243, 300, - 482, 455, 493, 463, 303, 1413, 1433, 494, 391, 617, + 0, 1393, 0, 0, 0, 0, 1343, 0, 1364, 1442, + 0, 1324, 313, 1335, 423, 273, 0, 477, 1355, 319, + 334, 1341, 1370, 1471, 1459, 1460, 1461, 1340, 1449, 1466, + 1389, 661, 1468, 1387, 1386, 1436, 1339, 1456, 1379, 384, + 1337, 349, 205, 233, 0, 1377, 434, 485, 497, 1455, + 1454, 1360, 1371, 269, 1368, 495, 448, 636, 243, 300, + 482, 455, 493, 463, 303, 1414, 1434, 494, 391, 617, 473, 633, 662, 663, 279, 428, 647, 551, 655, 680, 234, 276, 442, 535, 639, 519, 417, 613, 614, 348, 518, 311, 209, 388, 668, 232, 503, 390, 253, 241, @@ -3531,21 +3741,21 @@ var yyAct = [...]int{ 250, 507, 0, 0, 683, 258, 529, 642, 631, 223, 626, 528, 413, 345, 346, 222, 0, 481, 284, 309, 0, 0, 274, 437, 621, 622, 272, 684, 237, 654, - 228, 1335, 653, 430, 616, 627, 414, 402, 227, 625, + 228, 1336, 653, 430, 616, 627, 414, 402, 227, 625, 412, 401, 353, 374, 375, 296, 324, 470, 394, 471, 323, 325, 425, 424, 426, 215, 640, 658, 0, 216, - 0, 524, 643, 685, 475, 220, 244, 245, 248, 1353, + 0, 524, 643, 685, 475, 220, 244, 245, 248, 1354, 295, 299, 307, 310, 320, 321, 331, 386, 441, 469, - 465, 474, 1449, 610, 634, 648, 660, 666, 667, 669, + 465, 474, 1450, 610, 634, 648, 660, 666, 667, 669, 670, 671, 672, 673, 676, 674, 429, 329, 520, 352, - 392, 1438, 1486, 447, 496, 251, 638, 521, 240, 604, + 392, 1439, 1487, 447, 496, 251, 638, 521, 240, 604, 418, 427, 259, 261, 260, 235, 512, 609, 246, 266, - 207, 1347, 1352, 1345, 0, 270, 271, 1419, 605, 1348, - 1346, 1408, 1409, 1349, 1477, 1478, 1479, 1463, 686, 687, + 207, 1348, 1353, 1346, 0, 270, 271, 1420, 605, 1349, + 1347, 1409, 1410, 1350, 1478, 1479, 1480, 1464, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 681, 537, 543, 538, - 539, 540, 541, 542, 0, 544, 1442, 1341, 0, 1350, - 1351, 419, 1451, 623, 624, 704, 403, 510, 635, 354, + 539, 540, 541, 542, 0, 544, 1443, 1342, 0, 1351, + 1352, 419, 1452, 623, 624, 704, 403, 510, 635, 354, 368, 371, 360, 380, 0, 381, 356, 357, 362, 365, 366, 367, 372, 373, 377, 383, 263, 218, 410, 420, 608, 330, 224, 225, 226, 553, 554, 555, 556, 651, @@ -3555,243 +3765,320 @@ var yyAct = [...]int{ 597, 600, 559, 561, 563, 565, 578, 577, 574, 602, 603, 580, 585, 564, 576, 581, 594, 601, 598, 558, 562, 566, 575, 593, 592, 573, 584, 595, 579, 567, - 560, 568, 1412, 204, 229, 387, 1482, 478, 304, 682, - 650, 508, 645, 214, 231, 1344, 278, 1357, 1366, 0, - 1373, 1381, 1382, 1396, 1399, 1400, 1401, 1402, 1420, 1421, - 1423, 1432, 1434, 1437, 1439, 1446, 1464, 1485, 206, 208, + 560, 568, 1413, 204, 229, 387, 1483, 478, 304, 682, + 650, 508, 645, 214, 231, 1345, 278, 1358, 1367, 0, + 1374, 1382, 1383, 1397, 1400, 1401, 1402, 1403, 1421, 1422, + 1424, 1433, 1435, 1438, 1440, 1447, 1465, 1486, 206, 208, 217, 230, 242, 247, 254, 277, 292, 294, 301, 314, 327, 328, 337, 338, 341, 347, 399, 406, 407, 408, 409, 431, 432, 433, 436, 439, 440, 443, 445, 446, 449, 454, 458, 459, 460, 462, 464, 466, 479, 484, 498, 499, 500, 501, 502, 505, 506, 513, 514, 515, 516, 517, 525, 526, 531, 532, 533, 534, 545, 618, - 620, 637, 657, 664, 504, 404, 452, 476, 611, 1429, - 1390, 317, 318, 467, 468, 332, 333, 678, 679, 316, - 632, 665, 629, 677, 659, 461, 397, 1411, 1417, 400, - 297, 322, 339, 1426, 649, 527, 236, 490, 306, 265, - 1445, 1447, 219, 257, 239, 275, 290, 293, 343, 411, + 620, 637, 657, 664, 504, 404, 452, 476, 611, 1430, + 1391, 317, 318, 467, 468, 332, 333, 678, 679, 316, + 632, 665, 629, 677, 659, 461, 397, 1412, 1418, 400, + 297, 322, 339, 1427, 649, 527, 236, 490, 306, 265, + 1446, 1448, 219, 257, 239, 275, 290, 293, 343, 411, 421, 451, 457, 312, 287, 255, 483, 252, 509, 548, - 549, 550, 552, 415, 282, 456, 1407, 1436, 395, 606, - 607, 335, 1471, 1450, 557, 0, 1391, 1474, 1356, 1377, - 1484, 1380, 1383, 1428, 1331, 1406, 438, 1374, 1360, 1326, - 1368, 1327, 1358, 1393, 286, 1355, 1452, 1410, 1473, 385, - 283, 1333, 1324, 212, 530, 1361, 453, 1379, 211, 1431, - 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, - 405, 450, 547, 444, 1480, 389, 1416, 0, 522, 422, - 0, 0, 0, 1457, 1456, 1384, 1395, 1462, 1404, 1443, - 1389, 1430, 1343, 1415, 1475, 1375, 1425, 1476, 342, 262, - 344, 210, 435, 523, 302, 0, 0, 0, 0, 0, - 536, 202, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, - 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, - 1371, 1422, 641, 1469, 1372, 1424, 281, 340, 288, 280, - 612, 1481, 1461, 1330, 1403, 1468, 1398, 628, 0, 0, - 238, 1472, 1397, 0, 1427, 0, 1487, 1325, 1418, 0, - 1328, 1332, 1483, 1466, 1364, 1365, 291, 0, 0, 0, - 0, 0, 0, 0, 1394, 1405, 1440, 1444, 1387, 0, - 416, 0, 0, 0, 0, 0, 0, 0, 1362, 0, - 1414, 0, 0, 0, 1337, 1329, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1392, 0, - 0, 0, 0, 1342, 0, 1363, 1441, 0, 1323, 313, - 1334, 423, 273, 0, 477, 1354, 319, 334, 1340, 1369, - 1470, 1458, 1459, 1460, 1339, 1448, 1465, 1388, 661, 1467, - 1386, 1385, 1435, 1338, 1455, 1378, 384, 1336, 349, 205, - 233, 0, 1376, 434, 485, 497, 1454, 1453, 1359, 1370, - 269, 1367, 495, 448, 636, 243, 300, 482, 455, 493, - 463, 303, 1413, 1433, 494, 391, 617, 473, 633, 662, - 663, 279, 428, 647, 551, 655, 680, 234, 276, 442, - 535, 639, 519, 417, 613, 614, 348, 518, 311, 209, - 388, 668, 232, 503, 390, 253, 241, 619, 644, 315, - 267, 305, 480, 675, 221, 546, 630, 250, 507, 0, - 0, 683, 258, 529, 642, 631, 223, 626, 528, 413, - 345, 346, 222, 0, 481, 284, 309, 0, 0, 274, - 437, 621, 622, 272, 684, 237, 654, 228, 1335, 653, - 430, 616, 627, 414, 402, 227, 625, 412, 401, 353, - 374, 375, 296, 324, 470, 394, 471, 323, 325, 425, - 424, 426, 215, 640, 658, 0, 216, 0, 524, 643, - 685, 475, 220, 244, 245, 248, 1353, 295, 299, 307, - 310, 320, 321, 331, 386, 441, 469, 465, 474, 1449, - 610, 634, 648, 660, 666, 667, 669, 670, 671, 672, - 673, 676, 674, 429, 329, 520, 352, 392, 1438, 1486, - 447, 496, 251, 638, 521, 240, 604, 418, 427, 259, - 261, 260, 235, 512, 609, 246, 266, 207, 1347, 1352, - 1345, 0, 270, 271, 1419, 605, 1348, 1346, 1408, 1409, - 1349, 1477, 1478, 1479, 1463, 686, 687, 688, 689, 690, - 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, - 701, 702, 703, 681, 537, 543, 538, 539, 540, 541, - 542, 0, 544, 1442, 1341, 0, 1350, 1351, 419, 1451, - 623, 624, 704, 403, 510, 635, 354, 368, 371, 360, - 380, 0, 381, 356, 357, 362, 365, 366, 367, 372, - 373, 377, 383, 263, 218, 410, 420, 608, 330, 224, - 225, 226, 553, 554, 555, 556, 651, 652, 656, 213, - 486, 487, 488, 489, 308, 646, 326, 492, 491, 350, - 351, 398, 472, 569, 571, 582, 586, 588, 590, 596, - 599, 570, 572, 583, 587, 589, 591, 597, 600, 559, - 561, 563, 565, 578, 577, 574, 602, 603, 580, 585, - 564, 576, 581, 594, 601, 598, 558, 562, 566, 575, - 593, 592, 573, 584, 595, 579, 567, 560, 568, 1412, - 204, 229, 387, 1482, 478, 304, 682, 650, 508, 645, - 214, 231, 1344, 278, 1357, 1366, 0, 1373, 1381, 1382, - 1396, 1399, 1400, 1401, 1402, 1420, 1421, 1423, 1432, 1434, - 1437, 1439, 1446, 1464, 1485, 206, 208, 217, 230, 242, - 247, 254, 277, 292, 294, 301, 314, 327, 328, 337, - 338, 341, 347, 399, 406, 407, 408, 409, 431, 432, - 433, 436, 439, 440, 443, 445, 446, 449, 454, 458, - 459, 460, 462, 464, 466, 479, 484, 498, 499, 500, - 501, 502, 505, 506, 513, 514, 515, 516, 517, 525, - 526, 531, 532, 533, 534, 545, 618, 620, 637, 657, - 664, 504, 404, 452, 476, 611, 1429, 1390, 317, 318, - 467, 468, 332, 333, 678, 679, 316, 632, 665, 629, - 677, 659, 461, 397, 1411, 1417, 400, 297, 322, 339, - 1426, 649, 527, 236, 490, 306, 265, 1445, 1447, 219, - 257, 239, 275, 290, 293, 343, 411, 421, 451, 457, - 312, 287, 255, 483, 252, 509, 548, 549, 550, 552, - 415, 282, 456, 1407, 1436, 395, 606, 607, 335, 1471, - 1450, 557, 0, 1391, 1474, 1356, 1377, 1484, 1380, 1383, - 1428, 1331, 1406, 438, 1374, 1360, 1326, 1368, 1327, 1358, - 1393, 286, 1355, 1452, 1410, 1473, 385, 283, 1333, 1324, - 212, 530, 1361, 453, 1379, 211, 1431, 511, 268, 396, - 393, 615, 298, 289, 285, 264, 336, 405, 450, 547, - 444, 1480, 389, 1416, 0, 522, 422, 0, 0, 0, - 1457, 1456, 1384, 1395, 1462, 1404, 1443, 1389, 1430, 1343, - 1415, 1475, 1375, 1425, 1476, 342, 262, 344, 210, 435, - 523, 302, 0, 0, 0, 0, 0, 536, 756, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, - 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, - 361, 363, 369, 376, 382, 355, 364, 1371, 1422, 641, - 1469, 1372, 1424, 281, 340, 288, 280, 612, 1481, 1461, - 1330, 1403, 1468, 1398, 628, 0, 0, 238, 1472, 1397, - 0, 1427, 0, 1487, 1325, 1418, 0, 1328, 1332, 1483, - 1466, 1364, 1365, 291, 0, 0, 0, 0, 0, 0, - 0, 1394, 1405, 1440, 1444, 1387, 0, 416, 0, 0, - 0, 0, 0, 0, 0, 1362, 0, 1414, 0, 0, - 0, 1337, 1329, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1392, 0, 0, 0, 0, - 1342, 0, 1363, 1441, 0, 1323, 313, 1334, 423, 273, - 0, 477, 1354, 319, 334, 1340, 1369, 1470, 1458, 1459, - 1460, 1339, 1448, 1465, 1388, 661, 1467, 1386, 1385, 1435, - 1338, 1455, 1378, 384, 1336, 349, 205, 233, 0, 1376, - 434, 485, 497, 1454, 1453, 1359, 1370, 269, 1367, 495, - 448, 636, 243, 300, 482, 455, 493, 463, 303, 1413, - 1433, 494, 391, 617, 473, 633, 662, 663, 279, 428, - 647, 551, 655, 680, 234, 276, 442, 535, 639, 519, - 417, 613, 614, 348, 518, 311, 209, 388, 668, 232, - 503, 390, 253, 241, 619, 644, 315, 267, 305, 480, - 675, 221, 546, 630, 250, 507, 0, 0, 683, 258, - 529, 642, 631, 223, 626, 528, 413, 345, 346, 222, - 0, 481, 284, 309, 0, 0, 274, 437, 621, 622, - 272, 684, 237, 654, 228, 1335, 653, 430, 616, 627, - 414, 402, 227, 625, 412, 401, 353, 374, 375, 296, - 324, 470, 394, 471, 323, 325, 425, 424, 426, 215, - 640, 658, 0, 216, 0, 524, 643, 685, 475, 220, - 244, 245, 248, 1353, 295, 299, 307, 310, 320, 321, - 331, 386, 441, 469, 465, 474, 1449, 610, 634, 648, - 660, 666, 667, 669, 670, 671, 672, 673, 676, 674, - 429, 329, 520, 352, 392, 1438, 1486, 447, 496, 251, - 638, 521, 240, 604, 418, 427, 259, 261, 260, 235, - 512, 609, 246, 266, 207, 1347, 1352, 1345, 0, 270, - 271, 1419, 605, 1348, 1346, 1408, 1409, 1349, 1477, 1478, - 1479, 1463, 686, 687, 688, 689, 690, 691, 692, 693, - 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, - 681, 537, 543, 538, 539, 540, 541, 542, 0, 544, - 1442, 1341, 0, 1350, 1351, 419, 1451, 623, 624, 704, - 403, 510, 635, 354, 368, 371, 360, 380, 0, 381, - 356, 357, 362, 365, 366, 367, 372, 373, 377, 383, - 263, 218, 410, 420, 608, 330, 224, 225, 226, 553, - 554, 555, 556, 651, 652, 656, 213, 486, 487, 488, - 489, 308, 646, 326, 492, 491, 350, 351, 398, 472, - 569, 571, 582, 586, 588, 590, 596, 599, 570, 572, - 583, 587, 589, 591, 597, 600, 559, 561, 563, 565, - 578, 577, 574, 602, 603, 580, 585, 564, 576, 581, - 594, 601, 598, 558, 562, 566, 575, 593, 592, 573, - 584, 595, 579, 567, 560, 568, 1412, 204, 229, 387, - 1482, 478, 304, 682, 650, 508, 645, 214, 231, 1344, - 278, 1357, 1366, 0, 1373, 1381, 1382, 1396, 1399, 1400, - 1401, 1402, 1420, 1421, 1423, 1432, 1434, 1437, 1439, 1446, - 1464, 1485, 206, 208, 217, 230, 242, 247, 254, 277, - 292, 294, 301, 314, 327, 328, 337, 338, 341, 347, - 399, 406, 407, 408, 409, 431, 432, 433, 436, 439, - 440, 443, 445, 446, 449, 454, 458, 459, 460, 462, - 464, 466, 479, 484, 498, 499, 500, 501, 502, 505, - 506, 513, 514, 515, 516, 517, 525, 526, 531, 532, - 533, 534, 545, 618, 620, 637, 657, 664, 504, 404, - 452, 476, 611, 1429, 1390, 317, 318, 467, 468, 332, - 333, 678, 679, 316, 632, 665, 629, 677, 659, 461, - 397, 1411, 1417, 400, 297, 322, 339, 1426, 649, 527, - 236, 490, 306, 265, 1445, 1447, 219, 257, 239, 275, - 290, 293, 343, 411, 421, 451, 457, 312, 287, 255, - 483, 252, 509, 548, 549, 550, 552, 415, 282, 456, - 1407, 1436, 395, 606, 607, 335, 1471, 1450, 557, 0, - 1391, 1474, 1356, 1377, 1484, 1380, 1383, 1428, 1331, 1406, - 438, 1374, 1360, 1326, 1368, 1327, 1358, 1393, 286, 1355, - 1452, 1410, 1473, 385, 283, 1333, 1324, 212, 530, 1361, - 453, 1379, 211, 1431, 511, 268, 396, 393, 615, 298, - 289, 285, 264, 336, 405, 450, 547, 444, 1480, 389, - 1416, 0, 522, 422, 0, 0, 0, 1457, 1456, 1384, - 1395, 1462, 1404, 1443, 1389, 1430, 1343, 1415, 1475, 1375, - 1425, 1476, 342, 262, 344, 210, 435, 523, 302, 0, - 0, 0, 0, 0, 536, 991, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, - 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, - 376, 382, 355, 364, 1371, 1422, 641, 1469, 1372, 1424, - 281, 340, 288, 280, 612, 1481, 1461, 1330, 1403, 1468, - 1398, 628, 0, 0, 238, 1472, 1397, 0, 1427, 0, - 1487, 1325, 1418, 0, 1328, 1332, 1483, 1466, 1364, 1365, - 291, 0, 0, 0, 0, 0, 0, 0, 1394, 1405, - 1440, 1444, 1387, 0, 416, 0, 0, 0, 0, 0, - 0, 0, 1362, 0, 1414, 0, 0, 0, 1337, 1329, + 549, 550, 552, 415, 282, 456, 1408, 1437, 395, 606, + 607, 335, 557, 0, 809, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 438, 0, 0, 0, 796, 0, + 0, 0, 286, 801, 0, 0, 0, 385, 283, 0, + 0, 212, 530, 0, 453, 0, 211, 0, 511, 268, + 396, 393, 615, 298, 289, 285, 264, 336, 405, 450, + 547, 444, 808, 389, 0, 0, 522, 422, 0, 0, + 0, 0, 0, 0, 0, 0, 803, 804, 0, 0, + 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, + 435, 523, 302, 0, 101, 0, 0, 1057, 536, 991, + 780, 957, 995, 1058, 1009, 1010, 1011, 996, 0, 249, + 997, 998, 256, 999, 0, 956, 839, 841, 840, 906, + 907, 908, 909, 910, 911, 912, 842, 843, 837, 1004, + 641, 1012, 1013, 0, 281, 340, 288, 280, 612, 0, + 0, 2297, 2298, 2299, 0, 628, 0, 0, 238, 0, + 0, 0, 0, 0, 0, 0, 776, 793, 0, 807, + 0, 0, 0, 0, 291, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 416, 0, + 0, 0, 790, 791, 0, 0, 0, 0, 951, 0, + 792, 0, 0, 800, 1014, 1015, 1016, 1017, 1018, 1019, + 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, + 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, + 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, + 1050, 1051, 1052, 1053, 1054, 1055, 802, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 313, 0, 423, + 273, 0, 477, 0, 319, 334, 0, 0, 0, 0, + 0, 0, 0, 950, 0, 0, 661, 0, 0, 948, + 0, 0, 0, 0, 384, 0, 349, 205, 233, 0, + 0, 434, 485, 497, 0, 0, 0, 0, 1001, 0, + 495, 448, 636, 243, 300, 482, 455, 493, 463, 303, + 0, 0, 494, 391, 617, 473, 633, 662, 663, 279, + 428, 647, 551, 655, 680, 234, 276, 442, 535, 639, + 519, 417, 613, 614, 348, 518, 311, 209, 388, 668, + 232, 503, 390, 253, 241, 619, 644, 315, 267, 305, + 480, 675, 221, 546, 630, 250, 507, 0, 0, 683, + 258, 529, 642, 631, 223, 626, 528, 413, 345, 346, + 222, 0, 481, 284, 309, 0, 0, 274, 437, 1002, + 1003, 272, 684, 847, 654, 228, 0, 653, 430, 616, + 627, 414, 402, 227, 625, 412, 401, 353, 855, 856, + 296, 324, 932, 931, 930, 323, 325, 928, 929, 927, + 215, 640, 658, 0, 216, 0, 524, 643, 685, 475, + 220, 244, 245, 248, 0, 295, 299, 307, 310, 320, + 321, 331, 386, 441, 469, 465, 474, 0, 610, 634, + 648, 660, 666, 667, 669, 670, 671, 672, 673, 676, + 674, 429, 329, 520, 352, 392, 0, 0, 447, 496, + 251, 638, 521, 240, 604, 418, 427, 259, 261, 260, + 235, 512, 609, 246, 266, 938, 960, 949, 813, 814, + 939, 940, 964, 941, 816, 817, 961, 962, 810, 811, + 815, 963, 965, 686, 687, 688, 689, 690, 691, 692, + 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, + 703, 681, 537, 543, 538, 539, 540, 541, 542, 0, + 544, 952, 799, 798, 0, 805, 806, 0, 835, 836, + 838, 844, 845, 846, 857, 904, 905, 913, 915, 916, + 914, 917, 918, 919, 922, 923, 924, 925, 920, 921, + 926, 818, 822, 819, 820, 821, 833, 823, 824, 825, + 826, 827, 828, 829, 830, 831, 832, 834, 975, 976, + 977, 978, 979, 980, 850, 854, 853, 851, 852, 848, + 849, 876, 875, 877, 878, 879, 880, 881, 882, 884, + 883, 885, 886, 887, 888, 889, 890, 858, 859, 862, + 863, 861, 860, 864, 873, 874, 865, 866, 867, 868, + 869, 870, 872, 871, 891, 892, 893, 894, 895, 897, + 896, 900, 901, 899, 898, 903, 902, 797, 204, 229, + 387, 0, 478, 304, 682, 650, 508, 645, 214, 231, + 966, 278, 967, 0, 0, 971, 0, 0, 0, 973, + 972, 0, 974, 936, 935, 0, 0, 968, 969, 0, + 970, 0, 0, 206, 208, 217, 230, 242, 247, 254, + 277, 292, 294, 301, 314, 327, 328, 337, 338, 341, + 347, 399, 406, 407, 408, 409, 431, 432, 433, 436, + 439, 440, 443, 445, 446, 449, 454, 458, 459, 460, + 462, 464, 466, 479, 484, 498, 499, 500, 501, 502, + 505, 506, 513, 514, 515, 516, 517, 525, 526, 531, + 532, 533, 534, 545, 618, 620, 637, 657, 664, 504, + 404, 452, 476, 611, 0, 0, 981, 982, 983, 984, + 985, 986, 987, 988, 316, 632, 665, 629, 677, 659, + 461, 397, 0, 0, 400, 297, 322, 339, 0, 649, + 527, 236, 490, 306, 265, 1056, 0, 219, 257, 239, + 275, 290, 293, 343, 411, 421, 451, 457, 312, 287, + 255, 483, 252, 509, 548, 549, 550, 552, 415, 282, + 456, 0, 0, 395, 606, 607, 335, 557, 0, 809, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 438, + 0, 0, 0, 796, 0, 0, 0, 286, 801, 0, + 0, 0, 385, 283, 0, 0, 212, 530, 0, 453, + 0, 211, 0, 511, 268, 396, 393, 615, 298, 289, + 285, 264, 336, 405, 450, 547, 444, 808, 389, 0, + 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, + 0, 803, 804, 0, 0, 0, 0, 0, 0, 2521, + 0, 342, 262, 344, 210, 435, 523, 302, 0, 101, + 0, 0, 1057, 536, 991, 780, 957, 995, 1058, 1009, + 1010, 1011, 996, 0, 249, 997, 998, 256, 999, 0, + 956, 839, 841, 840, 906, 907, 908, 909, 910, 911, + 912, 842, 843, 837, 1004, 641, 1012, 1013, 2522, 281, + 340, 288, 280, 612, 0, 0, 0, 0, 0, 0, + 628, 0, 0, 238, 0, 0, 0, 0, 0, 0, + 0, 776, 793, 0, 807, 0, 0, 0, 0, 291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1392, 0, 0, 0, 0, 1342, 0, 1363, - 1441, 0, 1323, 313, 1334, 423, 273, 0, 477, 1354, - 319, 334, 1340, 1369, 1470, 1458, 1459, 1460, 1339, 1448, - 1465, 1388, 661, 1467, 1386, 1385, 1435, 1338, 1455, 1378, - 384, 1336, 349, 205, 233, 0, 1376, 434, 485, 497, - 1454, 1453, 1359, 1370, 269, 1367, 495, 448, 636, 243, - 300, 482, 455, 493, 463, 303, 1413, 1433, 494, 391, + 0, 0, 0, 416, 0, 0, 0, 790, 791, 0, + 0, 0, 0, 951, 0, 792, 0, 0, 800, 1014, + 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, + 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, + 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, + 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, + 1055, 802, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 313, 0, 423, 273, 0, 477, 0, 319, + 334, 0, 0, 0, 0, 0, 0, 0, 950, 0, + 0, 661, 0, 0, 948, 0, 0, 0, 0, 384, + 0, 349, 205, 233, 0, 0, 434, 485, 497, 0, + 0, 0, 0, 1001, 0, 495, 448, 636, 243, 300, + 482, 455, 493, 463, 303, 0, 0, 494, 391, 617, + 473, 633, 662, 663, 279, 428, 647, 551, 655, 680, + 234, 276, 442, 535, 639, 519, 417, 613, 614, 348, + 518, 311, 209, 388, 668, 232, 503, 390, 253, 241, + 619, 644, 315, 267, 305, 480, 675, 221, 546, 630, + 250, 507, 0, 0, 683, 258, 529, 642, 631, 223, + 626, 528, 413, 345, 346, 222, 0, 481, 284, 309, + 0, 0, 274, 437, 1002, 1003, 272, 684, 847, 654, + 228, 0, 653, 430, 616, 627, 414, 402, 227, 625, + 412, 401, 353, 855, 856, 296, 324, 932, 931, 930, + 323, 325, 928, 929, 927, 215, 640, 658, 0, 216, + 0, 524, 643, 685, 475, 220, 244, 245, 248, 0, + 295, 299, 307, 310, 320, 321, 331, 386, 441, 469, + 465, 474, 0, 610, 634, 648, 660, 666, 667, 669, + 670, 671, 672, 673, 676, 674, 429, 329, 520, 352, + 392, 0, 0, 447, 496, 251, 638, 521, 240, 604, + 418, 427, 259, 261, 260, 235, 512, 609, 246, 266, + 938, 960, 949, 813, 814, 939, 940, 964, 941, 816, + 817, 961, 962, 810, 811, 815, 963, 965, 686, 687, + 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, + 698, 699, 700, 701, 702, 703, 681, 537, 543, 538, + 539, 540, 541, 542, 0, 544, 952, 799, 798, 0, + 805, 806, 0, 835, 836, 838, 844, 845, 846, 857, + 904, 905, 913, 915, 916, 914, 917, 918, 919, 922, + 923, 924, 925, 920, 921, 926, 818, 822, 819, 820, + 821, 833, 823, 824, 825, 826, 827, 828, 829, 830, + 831, 832, 834, 975, 976, 977, 978, 979, 980, 850, + 854, 853, 851, 852, 848, 849, 876, 875, 877, 878, + 879, 880, 881, 882, 884, 883, 885, 886, 887, 888, + 889, 890, 858, 859, 862, 863, 861, 860, 864, 873, + 874, 865, 866, 867, 868, 869, 870, 872, 871, 891, + 892, 893, 894, 895, 897, 896, 900, 901, 899, 898, + 903, 902, 797, 204, 229, 387, 0, 478, 304, 682, + 650, 508, 645, 214, 231, 966, 278, 967, 0, 0, + 971, 0, 0, 0, 973, 972, 0, 974, 936, 935, + 0, 0, 968, 969, 0, 970, 0, 0, 206, 208, + 217, 230, 242, 247, 254, 277, 292, 294, 301, 314, + 327, 328, 337, 338, 341, 347, 399, 406, 407, 408, + 409, 431, 432, 433, 436, 439, 440, 443, 445, 446, + 449, 454, 458, 459, 460, 462, 464, 466, 479, 484, + 498, 499, 500, 501, 502, 505, 506, 513, 514, 515, + 516, 517, 525, 526, 531, 532, 533, 534, 545, 618, + 620, 637, 657, 664, 504, 404, 452, 476, 611, 0, + 0, 981, 982, 983, 984, 985, 986, 987, 988, 316, + 632, 665, 629, 677, 659, 461, 397, 0, 0, 400, + 297, 322, 339, 0, 649, 527, 236, 490, 306, 265, + 1056, 0, 219, 257, 239, 275, 290, 293, 343, 411, + 421, 451, 457, 312, 287, 255, 483, 252, 509, 548, + 549, 550, 552, 415, 282, 456, 0, 0, 395, 606, + 607, 335, 91, 557, 0, 809, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 438, 0, 0, 0, 796, + 0, 0, 0, 286, 801, 0, 0, 0, 385, 283, + 0, 0, 212, 530, 0, 453, 0, 211, 0, 511, + 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, + 450, 547, 444, 1768, 389, 0, 0, 522, 422, 0, + 0, 0, 0, 0, 0, 0, 0, 803, 804, 0, + 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, + 210, 435, 523, 302, 0, 101, 0, 0, 1057, 536, + 991, 780, 957, 995, 1058, 1009, 1010, 1011, 996, 0, + 249, 997, 998, 256, 999, 0, 956, 839, 841, 840, + 906, 907, 908, 909, 910, 911, 912, 842, 843, 837, + 1004, 641, 1012, 1013, 0, 281, 340, 288, 280, 612, + 0, 0, 0, 0, 0, 0, 628, 0, 0, 238, + 0, 0, 0, 0, 0, 0, 0, 776, 793, 0, + 807, 0, 0, 0, 0, 291, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, + 0, 0, 0, 790, 791, 0, 0, 0, 0, 951, + 0, 792, 0, 0, 800, 1014, 1015, 1016, 1017, 1018, + 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, + 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, + 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, + 1049, 1050, 1051, 1052, 1053, 1054, 1055, 802, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 313, 0, + 423, 273, 0, 477, 0, 319, 334, 0, 0, 0, + 0, 0, 0, 0, 950, 0, 0, 661, 0, 0, + 948, 0, 0, 0, 0, 384, 0, 349, 205, 233, + 0, 0, 434, 485, 497, 0, 0, 0, 0, 1001, + 0, 495, 448, 636, 243, 300, 482, 455, 493, 463, + 303, 0, 0, 494, 391, 617, 473, 633, 662, 663, + 279, 428, 647, 551, 655, 680, 234, 276, 442, 535, + 639, 519, 417, 613, 614, 348, 518, 311, 209, 388, + 668, 232, 503, 390, 253, 241, 619, 644, 315, 267, + 305, 480, 675, 221, 546, 630, 250, 507, 0, 0, + 683, 258, 529, 642, 631, 223, 626, 528, 413, 345, + 346, 222, 0, 481, 284, 309, 0, 0, 274, 437, + 1002, 1003, 272, 684, 847, 654, 228, 0, 653, 430, + 616, 627, 414, 402, 227, 625, 412, 401, 353, 855, + 856, 296, 324, 932, 931, 930, 323, 325, 928, 929, + 927, 215, 640, 658, 0, 216, 0, 524, 643, 685, + 475, 220, 244, 245, 248, 0, 295, 299, 307, 310, + 320, 321, 331, 386, 441, 469, 465, 474, 0, 610, + 634, 648, 660, 666, 667, 669, 670, 671, 672, 673, + 676, 674, 429, 329, 520, 352, 392, 0, 0, 447, + 496, 251, 638, 521, 240, 604, 418, 427, 259, 261, + 260, 235, 512, 609, 246, 266, 938, 960, 949, 813, + 814, 939, 940, 964, 941, 816, 817, 961, 962, 810, + 811, 815, 963, 965, 686, 687, 688, 689, 690, 691, + 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, + 702, 703, 681, 537, 543, 538, 539, 540, 541, 542, + 0, 544, 952, 799, 798, 0, 805, 806, 0, 835, + 836, 838, 844, 845, 846, 857, 904, 905, 913, 915, + 916, 914, 917, 918, 919, 922, 923, 924, 925, 920, + 921, 926, 818, 822, 819, 820, 821, 833, 823, 824, + 825, 826, 827, 828, 829, 830, 831, 832, 834, 975, + 976, 977, 978, 979, 980, 850, 854, 853, 851, 852, + 848, 849, 876, 875, 877, 878, 879, 880, 881, 882, + 884, 883, 885, 886, 887, 888, 889, 890, 858, 859, + 862, 863, 861, 860, 864, 873, 874, 865, 866, 867, + 868, 869, 870, 872, 871, 891, 892, 893, 894, 895, + 897, 896, 900, 901, 899, 898, 903, 902, 797, 204, + 229, 387, 100, 478, 304, 682, 650, 508, 645, 214, + 231, 966, 278, 967, 0, 0, 971, 0, 0, 0, + 973, 972, 0, 974, 936, 935, 0, 0, 968, 969, + 0, 970, 0, 0, 206, 208, 217, 230, 242, 247, + 254, 277, 292, 294, 301, 314, 327, 328, 337, 338, + 341, 347, 399, 406, 407, 408, 409, 431, 432, 433, + 436, 439, 440, 443, 445, 446, 449, 454, 458, 459, + 460, 462, 464, 466, 479, 484, 498, 499, 500, 501, + 502, 505, 506, 513, 514, 515, 516, 517, 525, 526, + 531, 532, 533, 534, 545, 618, 620, 637, 657, 664, + 504, 404, 452, 476, 611, 0, 0, 981, 982, 983, + 984, 985, 986, 987, 988, 316, 632, 665, 629, 677, + 659, 461, 397, 0, 0, 400, 297, 322, 339, 0, + 649, 527, 236, 490, 306, 265, 1056, 0, 219, 257, + 239, 275, 290, 293, 343, 411, 421, 451, 457, 312, + 287, 255, 483, 252, 509, 548, 549, 550, 552, 415, + 282, 456, 0, 0, 395, 606, 607, 335, 557, 0, + 809, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 438, 0, 0, 0, 796, 0, 0, 0, 286, 801, + 0, 0, 0, 385, 283, 0, 0, 212, 530, 0, + 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, + 289, 285, 264, 336, 405, 450, 547, 444, 808, 389, + 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, + 0, 0, 803, 804, 0, 0, 0, 0, 0, 0, + 0, 0, 342, 262, 344, 210, 435, 523, 302, 0, + 101, 0, 0, 1057, 536, 991, 780, 957, 995, 1058, + 1009, 1010, 1011, 996, 0, 249, 997, 998, 256, 999, + 0, 956, 839, 841, 840, 906, 907, 908, 909, 910, + 911, 912, 842, 843, 837, 1004, 641, 1012, 1013, 0, + 281, 340, 288, 280, 612, 0, 0, 0, 0, 0, + 0, 628, 0, 0, 238, 0, 0, 0, 0, 0, + 0, 0, 776, 793, 0, 807, 0, 0, 0, 0, + 291, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 416, 0, 0, 0, 790, 791, + 0, 0, 0, 0, 951, 0, 792, 0, 0, 800, + 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, + 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, + 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, + 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, + 1054, 1055, 802, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 313, 0, 423, 273, 0, 477, 0, + 319, 334, 0, 0, 0, 0, 0, 0, 0, 950, + 0, 0, 661, 0, 0, 948, 0, 0, 0, 0, + 384, 0, 349, 205, 233, 0, 0, 434, 485, 497, + 0, 0, 0, 0, 1001, 0, 495, 448, 636, 243, + 300, 482, 455, 493, 463, 303, 4215, 0, 494, 391, 617, 473, 633, 662, 663, 279, 428, 647, 551, 655, 680, 234, 276, 442, 535, 639, 519, 417, 613, 614, 348, 518, 311, 209, 388, 668, 232, 503, 390, 253, 241, 619, 644, 315, 267, 305, 480, 675, 221, 546, 630, 250, 507, 0, 0, 683, 258, 529, 642, 631, 223, 626, 528, 413, 345, 346, 222, 0, 481, 284, - 309, 0, 0, 274, 437, 621, 622, 272, 684, 237, - 654, 228, 1335, 653, 430, 616, 627, 414, 402, 227, - 625, 412, 401, 353, 374, 375, 296, 324, 470, 394, - 471, 323, 325, 425, 424, 426, 215, 640, 658, 0, + 309, 0, 0, 274, 437, 1002, 1003, 272, 684, 847, + 654, 228, 0, 653, 430, 616, 627, 414, 402, 227, + 625, 412, 401, 353, 855, 856, 296, 324, 932, 931, + 930, 323, 325, 928, 929, 927, 215, 640, 658, 0, 216, 0, 524, 643, 685, 475, 220, 244, 245, 248, - 1353, 295, 299, 307, 310, 320, 321, 331, 386, 441, - 469, 465, 474, 1449, 610, 634, 648, 660, 666, 667, + 0, 295, 299, 307, 310, 320, 321, 331, 386, 441, + 469, 465, 474, 0, 610, 634, 648, 660, 666, 667, 669, 670, 671, 672, 673, 676, 674, 429, 329, 520, - 352, 392, 1438, 1486, 447, 496, 251, 638, 521, 240, + 352, 392, 0, 0, 447, 496, 251, 638, 521, 240, 604, 418, 427, 259, 261, 260, 235, 512, 609, 246, - 266, 207, 1347, 1352, 1345, 0, 270, 271, 1419, 605, - 1348, 1346, 1408, 1409, 1349, 1477, 1478, 1479, 1463, 686, + 266, 938, 960, 949, 813, 814, 939, 940, 964, 941, + 816, 817, 961, 962, 810, 811, 815, 963, 965, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 681, 537, 543, - 538, 539, 540, 541, 542, 0, 544, 1442, 1341, 0, - 1350, 1351, 419, 1451, 623, 624, 704, 403, 510, 635, - 354, 368, 371, 360, 380, 0, 381, 356, 357, 362, - 365, 366, 367, 372, 373, 377, 383, 263, 218, 410, - 420, 608, 330, 224, 225, 226, 553, 554, 555, 556, - 651, 652, 656, 213, 486, 487, 488, 489, 308, 646, - 326, 492, 491, 350, 351, 398, 472, 569, 571, 582, - 586, 588, 590, 596, 599, 570, 572, 583, 587, 589, - 591, 597, 600, 559, 561, 563, 565, 578, 577, 574, - 602, 603, 580, 585, 564, 576, 581, 594, 601, 598, - 558, 562, 566, 575, 593, 592, 573, 584, 595, 579, - 567, 560, 568, 1412, 204, 229, 387, 1482, 478, 304, - 682, 650, 508, 645, 214, 231, 1344, 278, 1357, 1366, - 0, 1373, 1381, 1382, 1396, 1399, 1400, 1401, 1402, 1420, - 1421, 1423, 1432, 1434, 1437, 1439, 1446, 1464, 1485, 206, + 538, 539, 540, 541, 542, 0, 544, 952, 799, 798, + 0, 805, 806, 0, 835, 836, 838, 844, 845, 846, + 857, 904, 905, 913, 915, 916, 914, 917, 918, 919, + 922, 923, 924, 925, 920, 921, 926, 818, 822, 819, + 820, 821, 833, 823, 824, 825, 826, 827, 828, 829, + 830, 831, 832, 834, 975, 976, 977, 978, 979, 980, + 850, 854, 853, 851, 852, 848, 849, 876, 875, 877, + 878, 879, 880, 881, 882, 884, 883, 885, 886, 887, + 888, 889, 890, 858, 859, 862, 863, 861, 860, 864, + 873, 874, 865, 866, 867, 868, 869, 870, 872, 871, + 891, 892, 893, 894, 895, 897, 896, 900, 901, 899, + 898, 903, 902, 797, 204, 229, 387, 0, 478, 304, + 682, 650, 508, 645, 214, 231, 966, 278, 967, 0, + 0, 971, 0, 0, 0, 973, 972, 0, 974, 936, + 935, 0, 0, 968, 969, 0, 970, 0, 0, 206, 208, 217, 230, 242, 247, 254, 277, 292, 294, 301, 314, 327, 328, 337, 338, 341, 347, 399, 406, 407, 408, 409, 431, 432, 433, 436, 439, 440, 443, 445, @@ -3799,12 +4086,12 @@ var yyAct = [...]int{ 484, 498, 499, 500, 501, 502, 505, 506, 513, 514, 515, 516, 517, 525, 526, 531, 532, 533, 534, 545, 618, 620, 637, 657, 664, 504, 404, 452, 476, 611, - 1429, 1390, 317, 318, 467, 468, 332, 333, 678, 679, - 316, 632, 665, 629, 677, 659, 461, 397, 1411, 1417, - 400, 297, 322, 339, 1426, 649, 527, 236, 490, 306, - 265, 1445, 1447, 219, 257, 239, 275, 290, 293, 343, + 0, 0, 981, 982, 983, 984, 985, 986, 987, 988, + 316, 632, 665, 629, 677, 659, 461, 397, 0, 0, + 400, 297, 322, 339, 0, 649, 527, 236, 490, 306, + 265, 1056, 0, 219, 257, 239, 275, 290, 293, 343, 411, 421, 451, 457, 312, 287, 255, 483, 252, 509, - 548, 549, 550, 552, 415, 282, 456, 1407, 1436, 395, + 548, 549, 550, 552, 415, 282, 456, 0, 0, 395, 606, 607, 335, 557, 0, 809, 0, 0, 0, 0, 0, 0, 0, 0, 0, 438, 0, 0, 0, 796, 0, 0, 0, 286, 801, 0, 0, 0, 385, 283, @@ -3813,12 +4100,12 @@ var yyAct = [...]int{ 450, 547, 444, 808, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 803, 804, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, - 210, 435, 523, 302, 0, 101, 0, 0, 1057, 536, + 210, 435, 523, 302, 0, 101, 0, 1805, 1057, 536, 991, 780, 957, 995, 1058, 1009, 1010, 1011, 996, 0, 249, 997, 998, 256, 999, 0, 956, 839, 841, 840, 906, 907, 908, 909, 910, 911, 912, 842, 843, 837, 1004, 641, 1012, 1013, 0, 281, 340, 288, 280, 612, - 0, 0, 2294, 2295, 2296, 0, 628, 0, 0, 238, + 0, 0, 0, 0, 0, 0, 628, 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, 776, 793, 0, 807, 0, 0, 0, 0, 291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, @@ -3890,17 +4177,17 @@ var yyAct = [...]int{ 289, 285, 264, 336, 405, 450, 547, 444, 808, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 803, 804, 0, 0, 0, 0, 0, 0, - 2515, 0, 342, 262, 344, 210, 435, 523, 302, 0, + 0, 0, 342, 262, 344, 210, 435, 523, 302, 0, 101, 0, 0, 1057, 536, 991, 780, 957, 995, 1058, 1009, 1010, 1011, 996, 0, 249, 997, 998, 256, 999, 0, 956, 839, 841, 840, 906, 907, 908, 909, 910, - 911, 912, 842, 843, 837, 1004, 641, 1012, 1013, 2516, + 911, 912, 842, 843, 837, 1004, 641, 1012, 1013, 0, 281, 340, 288, 280, 612, 0, 0, 0, 0, 0, 0, 628, 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, 776, 793, 0, 807, 0, 0, 0, 0, 291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, 0, 790, 791, - 0, 0, 0, 0, 951, 0, 792, 0, 0, 800, + 2450, 0, 0, 0, 951, 0, 792, 0, 0, 800, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, @@ -3960,809 +4247,422 @@ var yyAct = [...]int{ 265, 1056, 0, 219, 257, 239, 275, 290, 293, 343, 411, 421, 451, 457, 312, 287, 255, 483, 252, 509, 548, 549, 550, 552, 415, 282, 456, 0, 0, 395, - 606, 607, 335, 91, 557, 0, 809, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 438, 0, 0, 0, - 796, 0, 0, 0, 286, 801, 0, 0, 0, 385, - 283, 0, 0, 212, 530, 0, 453, 0, 211, 0, - 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, - 405, 450, 547, 444, 1767, 389, 0, 0, 522, 422, - 0, 0, 0, 0, 0, 0, 0, 0, 803, 804, - 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, - 344, 210, 435, 523, 302, 0, 101, 0, 0, 1057, - 536, 991, 780, 957, 995, 1058, 1009, 1010, 1011, 996, - 0, 249, 997, 998, 256, 999, 0, 956, 839, 841, - 840, 906, 907, 908, 909, 910, 911, 912, 842, 843, - 837, 1004, 641, 1012, 1013, 0, 281, 340, 288, 280, - 612, 0, 0, 0, 0, 0, 0, 628, 0, 0, - 238, 0, 0, 0, 0, 0, 0, 0, 776, 793, - 0, 807, 0, 0, 0, 0, 291, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 416, 0, 0, 0, 790, 791, 0, 0, 0, 0, - 951, 0, 792, 0, 0, 800, 1014, 1015, 1016, 1017, - 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, - 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, - 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, - 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 802, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 313, - 0, 423, 273, 0, 477, 0, 319, 334, 0, 0, - 0, 0, 0, 0, 0, 950, 0, 0, 661, 0, - 0, 948, 0, 0, 0, 0, 384, 0, 349, 205, - 233, 0, 0, 434, 485, 497, 0, 0, 0, 0, - 1001, 0, 495, 448, 636, 243, 300, 482, 455, 493, - 463, 303, 0, 0, 494, 391, 617, 473, 633, 662, - 663, 279, 428, 647, 551, 655, 680, 234, 276, 442, - 535, 639, 519, 417, 613, 614, 348, 518, 311, 209, - 388, 668, 232, 503, 390, 253, 241, 619, 644, 315, - 267, 305, 480, 675, 221, 546, 630, 250, 507, 0, - 0, 683, 258, 529, 642, 631, 223, 626, 528, 413, - 345, 346, 222, 0, 481, 284, 309, 0, 0, 274, - 437, 1002, 1003, 272, 684, 847, 654, 228, 0, 653, - 430, 616, 627, 414, 402, 227, 625, 412, 401, 353, - 855, 856, 296, 324, 932, 931, 930, 323, 325, 928, - 929, 927, 215, 640, 658, 0, 216, 0, 524, 643, - 685, 475, 220, 244, 245, 248, 0, 295, 299, 307, - 310, 320, 321, 331, 386, 441, 469, 465, 474, 0, - 610, 634, 648, 660, 666, 667, 669, 670, 671, 672, - 673, 676, 674, 429, 329, 520, 352, 392, 0, 0, - 447, 496, 251, 638, 521, 240, 604, 418, 427, 259, - 261, 260, 235, 512, 609, 246, 266, 938, 960, 949, - 813, 814, 939, 940, 964, 941, 816, 817, 961, 962, - 810, 811, 815, 963, 965, 686, 687, 688, 689, 690, - 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, - 701, 702, 703, 681, 537, 543, 538, 539, 540, 541, - 542, 0, 544, 952, 799, 798, 0, 805, 806, 0, - 835, 836, 838, 844, 845, 846, 857, 904, 905, 913, - 915, 916, 914, 917, 918, 919, 922, 923, 924, 925, - 920, 921, 926, 818, 822, 819, 820, 821, 833, 823, - 824, 825, 826, 827, 828, 829, 830, 831, 832, 834, - 975, 976, 977, 978, 979, 980, 850, 854, 853, 851, - 852, 848, 849, 876, 875, 877, 878, 879, 880, 881, - 882, 884, 883, 885, 886, 887, 888, 889, 890, 858, - 859, 862, 863, 861, 860, 864, 873, 874, 865, 866, - 867, 868, 869, 870, 872, 871, 891, 892, 893, 894, - 895, 897, 896, 900, 901, 899, 898, 903, 902, 797, - 204, 229, 387, 100, 478, 304, 682, 650, 508, 645, - 214, 231, 966, 278, 967, 0, 0, 971, 0, 0, - 0, 973, 972, 0, 974, 936, 935, 0, 0, 968, - 969, 0, 970, 0, 0, 206, 208, 217, 230, 242, - 247, 254, 277, 292, 294, 301, 314, 327, 328, 337, - 338, 341, 347, 399, 406, 407, 408, 409, 431, 432, - 433, 436, 439, 440, 443, 445, 446, 449, 454, 458, - 459, 460, 462, 464, 466, 479, 484, 498, 499, 500, - 501, 502, 505, 506, 513, 514, 515, 516, 517, 525, - 526, 531, 532, 533, 534, 545, 618, 620, 637, 657, - 664, 504, 404, 452, 476, 611, 0, 0, 981, 982, - 983, 984, 985, 986, 987, 988, 316, 632, 665, 629, - 677, 659, 461, 397, 0, 0, 400, 297, 322, 339, - 0, 649, 527, 236, 490, 306, 265, 1056, 0, 219, - 257, 239, 275, 290, 293, 343, 411, 421, 451, 457, - 312, 287, 255, 483, 252, 509, 548, 549, 550, 552, - 415, 282, 456, 0, 0, 395, 606, 607, 335, 557, - 0, 809, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 438, 0, 0, 0, 796, 0, 0, 0, 286, - 801, 0, 0, 0, 385, 283, 0, 0, 212, 530, - 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, - 298, 289, 285, 264, 336, 405, 450, 547, 444, 808, - 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, - 0, 0, 0, 803, 804, 0, 0, 0, 0, 0, - 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, - 0, 101, 0, 0, 1057, 536, 991, 780, 957, 995, - 1058, 1009, 1010, 1011, 996, 0, 249, 997, 998, 256, - 999, 0, 956, 839, 841, 840, 906, 907, 908, 909, - 910, 911, 912, 842, 843, 837, 1004, 641, 1012, 1013, - 0, 281, 340, 288, 280, 612, 0, 0, 0, 0, - 0, 0, 628, 0, 0, 238, 0, 0, 0, 0, - 0, 0, 0, 776, 793, 0, 807, 0, 0, 0, - 0, 291, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 416, 0, 0, 0, 790, - 791, 0, 0, 0, 0, 951, 0, 792, 0, 0, - 800, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, - 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, - 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, - 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, - 1053, 1054, 1055, 802, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 313, 0, 423, 273, 0, 477, - 0, 319, 334, 0, 0, 0, 0, 0, 0, 0, - 950, 0, 0, 661, 0, 0, 948, 0, 0, 0, - 0, 384, 0, 349, 205, 233, 0, 0, 434, 485, - 497, 0, 0, 0, 0, 1001, 0, 495, 448, 636, - 243, 300, 482, 455, 493, 463, 303, 4207, 0, 494, - 391, 617, 473, 633, 662, 663, 279, 428, 647, 551, - 655, 680, 234, 276, 442, 535, 639, 519, 417, 613, - 614, 348, 518, 311, 209, 388, 668, 232, 503, 390, - 253, 241, 619, 644, 315, 267, 305, 480, 675, 221, - 546, 630, 250, 507, 0, 0, 683, 258, 529, 642, - 631, 223, 626, 528, 413, 345, 346, 222, 0, 481, - 284, 309, 0, 0, 274, 437, 1002, 1003, 272, 684, - 847, 654, 228, 0, 653, 430, 616, 627, 414, 402, - 227, 625, 412, 401, 353, 855, 856, 296, 324, 932, - 931, 930, 323, 325, 928, 929, 927, 215, 640, 658, - 0, 216, 0, 524, 643, 685, 475, 220, 244, 245, - 248, 0, 295, 299, 307, 310, 320, 321, 331, 386, - 441, 469, 465, 474, 0, 610, 634, 648, 660, 666, - 667, 669, 670, 671, 672, 673, 676, 674, 429, 329, - 520, 352, 392, 0, 0, 447, 496, 251, 638, 521, - 240, 604, 418, 427, 259, 261, 260, 235, 512, 609, - 246, 266, 938, 960, 949, 813, 814, 939, 940, 964, - 941, 816, 817, 961, 962, 810, 811, 815, 963, 965, - 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, - 696, 697, 698, 699, 700, 701, 702, 703, 681, 537, - 543, 538, 539, 540, 541, 542, 0, 544, 952, 799, - 798, 0, 805, 806, 0, 835, 836, 838, 844, 845, - 846, 857, 904, 905, 913, 915, 916, 914, 917, 918, - 919, 922, 923, 924, 925, 920, 921, 926, 818, 822, - 819, 820, 821, 833, 823, 824, 825, 826, 827, 828, - 829, 830, 831, 832, 834, 975, 976, 977, 978, 979, - 980, 850, 854, 853, 851, 852, 848, 849, 876, 875, - 877, 878, 879, 880, 881, 882, 884, 883, 885, 886, - 887, 888, 889, 890, 858, 859, 862, 863, 861, 860, - 864, 873, 874, 865, 866, 867, 868, 869, 870, 872, - 871, 891, 892, 893, 894, 895, 897, 896, 900, 901, - 899, 898, 903, 902, 797, 204, 229, 387, 0, 478, - 304, 682, 650, 508, 645, 214, 231, 966, 278, 967, - 0, 0, 971, 0, 0, 0, 973, 972, 0, 974, - 936, 935, 0, 0, 968, 969, 0, 970, 0, 0, - 206, 208, 217, 230, 242, 247, 254, 277, 292, 294, - 301, 314, 327, 328, 337, 338, 341, 347, 399, 406, - 407, 408, 409, 431, 432, 433, 436, 439, 440, 443, - 445, 446, 449, 454, 458, 459, 460, 462, 464, 466, - 479, 484, 498, 499, 500, 501, 502, 505, 506, 513, - 514, 515, 516, 517, 525, 526, 531, 532, 533, 534, - 545, 618, 620, 637, 657, 664, 504, 404, 452, 476, - 611, 0, 0, 981, 982, 983, 984, 985, 986, 987, - 988, 316, 632, 665, 629, 677, 659, 461, 397, 0, - 0, 400, 297, 322, 339, 0, 649, 527, 236, 490, - 306, 265, 1056, 0, 219, 257, 239, 275, 290, 293, - 343, 411, 421, 451, 457, 312, 287, 255, 483, 252, - 509, 548, 549, 550, 552, 415, 282, 456, 0, 0, - 395, 606, 607, 335, 557, 0, 809, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 438, 0, 0, 0, - 796, 0, 0, 0, 286, 801, 0, 0, 0, 385, - 283, 0, 0, 212, 530, 0, 453, 0, 211, 0, - 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, - 405, 450, 547, 444, 808, 389, 0, 0, 522, 422, - 0, 0, 0, 0, 0, 0, 0, 0, 803, 804, - 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, - 344, 210, 435, 523, 302, 0, 101, 0, 1804, 1057, - 536, 991, 780, 957, 995, 1058, 1009, 1010, 1011, 996, - 0, 249, 997, 998, 256, 999, 0, 956, 839, 841, - 840, 906, 907, 908, 909, 910, 911, 912, 842, 843, - 837, 1004, 641, 1012, 1013, 0, 281, 340, 288, 280, - 612, 0, 0, 0, 0, 0, 0, 628, 0, 0, - 238, 0, 0, 0, 0, 0, 0, 0, 776, 793, - 0, 807, 0, 0, 0, 0, 291, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 416, 0, 0, 0, 790, 791, 0, 0, 0, 0, - 951, 0, 792, 0, 0, 800, 1014, 1015, 1016, 1017, - 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, - 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, - 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, - 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 802, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 313, - 0, 423, 273, 0, 477, 0, 319, 334, 0, 0, - 0, 0, 0, 0, 0, 950, 0, 0, 661, 0, - 0, 948, 0, 0, 0, 0, 384, 0, 349, 205, - 233, 0, 0, 434, 485, 497, 0, 0, 0, 0, - 1001, 0, 495, 448, 636, 243, 300, 482, 455, 493, - 463, 303, 0, 0, 494, 391, 617, 473, 633, 662, - 663, 279, 428, 647, 551, 655, 680, 234, 276, 442, - 535, 639, 519, 417, 613, 614, 348, 518, 311, 209, - 388, 668, 232, 503, 390, 253, 241, 619, 644, 315, - 267, 305, 480, 675, 221, 546, 630, 250, 507, 0, - 0, 683, 258, 529, 642, 631, 223, 626, 528, 413, - 345, 346, 222, 0, 481, 284, 309, 0, 0, 274, - 437, 1002, 1003, 272, 684, 847, 654, 228, 0, 653, - 430, 616, 627, 414, 402, 227, 625, 412, 401, 353, - 855, 856, 296, 324, 932, 931, 930, 323, 325, 928, - 929, 927, 215, 640, 658, 0, 216, 0, 524, 643, - 685, 475, 220, 244, 245, 248, 0, 295, 299, 307, - 310, 320, 321, 331, 386, 441, 469, 465, 474, 0, - 610, 634, 648, 660, 666, 667, 669, 670, 671, 672, - 673, 676, 674, 429, 329, 520, 352, 392, 0, 0, - 447, 496, 251, 638, 521, 240, 604, 418, 427, 259, - 261, 260, 235, 512, 609, 246, 266, 938, 960, 949, - 813, 814, 939, 940, 964, 941, 816, 817, 961, 962, - 810, 811, 815, 963, 965, 686, 687, 688, 689, 690, - 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, - 701, 702, 703, 681, 537, 543, 538, 539, 540, 541, - 542, 0, 544, 952, 799, 798, 0, 805, 806, 0, - 835, 836, 838, 844, 845, 846, 857, 904, 905, 913, - 915, 916, 914, 917, 918, 919, 922, 923, 924, 925, - 920, 921, 926, 818, 822, 819, 820, 821, 833, 823, - 824, 825, 826, 827, 828, 829, 830, 831, 832, 834, - 975, 976, 977, 978, 979, 980, 850, 854, 853, 851, - 852, 848, 849, 876, 875, 877, 878, 879, 880, 881, - 882, 884, 883, 885, 886, 887, 888, 889, 890, 858, - 859, 862, 863, 861, 860, 864, 873, 874, 865, 866, - 867, 868, 869, 870, 872, 871, 891, 892, 893, 894, - 895, 897, 896, 900, 901, 899, 898, 903, 902, 797, - 204, 229, 387, 0, 478, 304, 682, 650, 508, 645, - 214, 231, 966, 278, 967, 0, 0, 971, 0, 0, - 0, 973, 972, 0, 974, 936, 935, 0, 0, 968, - 969, 0, 970, 0, 0, 206, 208, 217, 230, 242, - 247, 254, 277, 292, 294, 301, 314, 327, 328, 337, - 338, 341, 347, 399, 406, 407, 408, 409, 431, 432, - 433, 436, 439, 440, 443, 445, 446, 449, 454, 458, - 459, 460, 462, 464, 466, 479, 484, 498, 499, 500, - 501, 502, 505, 506, 513, 514, 515, 516, 517, 525, - 526, 531, 532, 533, 534, 545, 618, 620, 637, 657, - 664, 504, 404, 452, 476, 611, 0, 0, 981, 982, - 983, 984, 985, 986, 987, 988, 316, 632, 665, 629, - 677, 659, 461, 397, 0, 0, 400, 297, 322, 339, - 0, 649, 527, 236, 490, 306, 265, 1056, 0, 219, - 257, 239, 275, 290, 293, 343, 411, 421, 451, 457, - 312, 287, 255, 483, 252, 509, 548, 549, 550, 552, - 415, 282, 456, 0, 0, 395, 606, 607, 335, 557, - 0, 809, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 438, 0, 0, 0, 796, 0, 0, 0, 286, - 801, 0, 0, 0, 385, 283, 0, 0, 212, 530, - 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, - 298, 289, 285, 264, 336, 405, 450, 547, 444, 808, - 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, - 0, 0, 0, 803, 804, 0, 0, 0, 0, 0, - 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, - 0, 101, 0, 0, 1057, 536, 991, 780, 957, 995, - 1058, 1009, 1010, 1011, 996, 0, 249, 997, 998, 256, - 999, 0, 956, 839, 841, 840, 906, 907, 908, 909, - 910, 911, 912, 842, 843, 837, 1004, 641, 1012, 1013, - 0, 281, 340, 288, 280, 612, 0, 0, 0, 0, - 0, 0, 628, 0, 0, 238, 0, 0, 0, 0, - 0, 0, 0, 776, 793, 0, 807, 0, 0, 0, - 0, 291, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 416, 0, 0, 0, 790, - 791, 1110, 0, 0, 0, 951, 0, 792, 0, 0, - 800, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, - 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, - 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, - 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, - 1053, 1054, 1055, 802, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 313, 0, 423, 273, 0, 477, - 0, 319, 334, 0, 0, 0, 0, 0, 0, 0, - 950, 0, 0, 661, 0, 0, 948, 0, 0, 0, - 0, 384, 0, 349, 205, 233, 0, 0, 434, 485, - 497, 0, 0, 0, 0, 1001, 0, 495, 448, 636, - 243, 300, 482, 455, 493, 463, 303, 0, 0, 494, - 391, 617, 473, 633, 662, 663, 279, 428, 647, 551, - 655, 680, 234, 276, 442, 535, 639, 519, 417, 613, - 614, 348, 518, 311, 209, 388, 668, 232, 503, 390, - 253, 241, 619, 644, 315, 267, 305, 480, 675, 221, - 546, 630, 250, 507, 0, 0, 683, 258, 529, 642, - 631, 223, 626, 528, 413, 345, 346, 222, 0, 481, - 284, 309, 0, 0, 274, 437, 1002, 1003, 272, 684, - 847, 654, 228, 0, 653, 430, 616, 627, 414, 402, - 227, 625, 412, 401, 353, 855, 856, 296, 324, 932, - 931, 930, 323, 325, 928, 929, 927, 215, 640, 658, - 0, 216, 0, 524, 643, 685, 475, 220, 244, 245, - 248, 0, 295, 299, 307, 310, 320, 321, 331, 386, - 441, 469, 465, 474, 0, 610, 634, 648, 660, 666, - 667, 669, 670, 671, 672, 673, 676, 674, 429, 329, - 520, 352, 392, 0, 0, 447, 496, 251, 638, 521, - 240, 604, 418, 427, 259, 261, 260, 235, 512, 609, - 246, 266, 938, 960, 949, 813, 814, 939, 940, 964, - 941, 816, 817, 961, 962, 810, 811, 815, 963, 965, - 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, - 696, 697, 698, 699, 700, 701, 702, 703, 681, 537, - 543, 538, 539, 540, 541, 542, 0, 544, 952, 799, - 798, 0, 805, 806, 0, 835, 836, 838, 844, 845, - 846, 857, 904, 905, 913, 915, 916, 914, 917, 918, - 919, 922, 923, 924, 925, 920, 921, 926, 818, 822, - 819, 820, 821, 833, 823, 824, 825, 826, 827, 828, - 829, 830, 831, 832, 834, 975, 976, 977, 978, 979, - 980, 850, 854, 853, 851, 852, 848, 849, 876, 875, - 877, 878, 879, 880, 881, 882, 884, 883, 885, 886, - 887, 888, 889, 890, 858, 859, 862, 863, 861, 860, - 864, 873, 874, 865, 866, 867, 868, 869, 870, 872, - 871, 891, 892, 893, 894, 895, 897, 896, 900, 901, - 899, 898, 903, 902, 797, 204, 229, 387, 0, 478, - 304, 682, 650, 508, 645, 214, 231, 966, 278, 967, - 0, 0, 971, 0, 0, 0, 973, 972, 0, 974, - 936, 935, 0, 0, 968, 969, 0, 970, 0, 0, - 206, 208, 217, 230, 242, 247, 254, 277, 292, 294, - 301, 314, 327, 328, 337, 338, 341, 347, 399, 406, - 407, 408, 409, 431, 432, 433, 436, 439, 440, 443, - 445, 446, 449, 454, 458, 459, 460, 462, 464, 466, - 479, 484, 498, 499, 500, 501, 502, 505, 506, 513, - 514, 515, 516, 517, 525, 526, 531, 532, 533, 534, - 545, 618, 620, 637, 657, 664, 504, 404, 452, 476, - 611, 0, 0, 981, 982, 983, 984, 985, 986, 987, - 988, 316, 632, 665, 629, 677, 659, 461, 397, 0, - 0, 400, 297, 322, 339, 0, 649, 527, 236, 490, - 306, 265, 1056, 0, 219, 257, 239, 275, 290, 293, - 343, 411, 421, 451, 457, 312, 287, 255, 483, 252, - 509, 548, 549, 550, 552, 415, 282, 456, 0, 0, - 395, 606, 607, 335, 557, 0, 809, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 438, 0, 0, 0, - 796, 0, 0, 0, 286, 801, 0, 0, 0, 385, - 283, 0, 0, 212, 530, 0, 453, 0, 211, 0, - 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, - 405, 450, 547, 444, 808, 389, 0, 0, 522, 422, - 0, 0, 0, 0, 0, 0, 0, 0, 803, 804, - 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, - 344, 210, 435, 523, 302, 0, 101, 0, 0, 1057, - 536, 991, 780, 957, 995, 1058, 1009, 1010, 1011, 996, - 0, 249, 997, 998, 256, 999, 0, 956, 839, 841, - 840, 906, 907, 908, 909, 910, 911, 912, 842, 843, - 837, 1004, 641, 1012, 1013, 0, 281, 340, 288, 280, - 612, 0, 0, 0, 0, 0, 0, 628, 0, 0, - 238, 0, 0, 0, 0, 0, 0, 0, 776, 793, - 0, 807, 0, 0, 0, 0, 291, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 416, 0, 0, 0, 790, 791, 0, 0, 0, 0, - 951, 0, 792, 0, 0, 800, 1014, 1015, 1016, 1017, - 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, - 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, - 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, - 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 802, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 313, - 0, 423, 273, 0, 477, 0, 319, 334, 0, 0, - 0, 0, 0, 0, 0, 950, 0, 0, 661, 0, - 0, 948, 0, 0, 0, 0, 384, 0, 349, 205, - 233, 0, 0, 434, 485, 497, 0, 0, 0, 0, - 1001, 0, 495, 448, 636, 243, 300, 482, 455, 493, - 463, 303, 0, 0, 494, 391, 617, 473, 633, 662, - 663, 279, 428, 647, 551, 655, 680, 234, 276, 442, - 535, 639, 519, 417, 613, 614, 348, 518, 311, 209, - 388, 668, 232, 503, 390, 253, 241, 619, 644, 315, - 267, 305, 480, 675, 221, 546, 630, 250, 507, 0, - 0, 683, 258, 529, 642, 631, 223, 626, 528, 413, - 345, 346, 222, 0, 481, 284, 309, 0, 0, 274, - 437, 1002, 1003, 272, 684, 847, 654, 228, 0, 653, - 430, 616, 627, 414, 402, 227, 625, 412, 401, 353, - 855, 856, 296, 324, 932, 931, 930, 323, 325, 928, - 929, 927, 215, 640, 658, 0, 216, 0, 524, 643, - 685, 475, 220, 244, 245, 248, 0, 295, 299, 307, - 310, 320, 321, 331, 386, 441, 469, 465, 474, 0, - 610, 634, 648, 660, 666, 667, 669, 670, 671, 672, - 673, 676, 674, 429, 329, 520, 352, 392, 0, 0, - 447, 496, 251, 638, 521, 240, 604, 418, 427, 259, - 261, 260, 235, 512, 609, 246, 266, 938, 960, 949, - 813, 814, 939, 940, 964, 941, 816, 817, 961, 962, - 810, 811, 815, 963, 965, 686, 687, 688, 689, 690, - 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, - 701, 702, 703, 681, 537, 543, 538, 539, 540, 541, - 542, 0, 544, 952, 799, 798, 0, 805, 806, 0, - 835, 836, 838, 844, 845, 846, 857, 904, 905, 913, - 915, 916, 914, 917, 918, 919, 922, 923, 924, 925, - 920, 921, 926, 818, 822, 819, 820, 821, 833, 823, - 824, 825, 826, 827, 828, 829, 830, 831, 832, 834, - 975, 976, 977, 978, 979, 980, 850, 854, 853, 851, - 852, 848, 849, 876, 875, 877, 878, 879, 880, 881, - 882, 884, 883, 885, 886, 887, 888, 889, 890, 858, - 859, 862, 863, 861, 860, 864, 873, 874, 865, 866, - 867, 868, 869, 870, 872, 871, 891, 892, 893, 894, - 895, 897, 896, 900, 901, 899, 898, 903, 902, 797, - 204, 229, 387, 0, 478, 304, 682, 650, 508, 645, - 214, 231, 966, 278, 967, 0, 0, 971, 0, 0, - 0, 973, 972, 0, 974, 936, 935, 0, 0, 968, - 969, 0, 970, 0, 0, 206, 208, 217, 230, 242, - 247, 254, 277, 292, 294, 301, 314, 327, 328, 337, - 338, 341, 347, 399, 406, 407, 408, 409, 431, 432, - 433, 436, 439, 440, 443, 445, 446, 449, 454, 458, - 459, 460, 462, 464, 466, 479, 484, 498, 499, 500, - 501, 502, 505, 506, 513, 514, 515, 516, 517, 525, - 526, 531, 532, 533, 534, 545, 618, 620, 637, 657, - 664, 504, 404, 452, 476, 611, 0, 0, 981, 982, - 983, 984, 985, 986, 987, 988, 316, 632, 665, 629, - 677, 659, 461, 397, 0, 0, 400, 297, 322, 339, - 0, 649, 527, 236, 490, 306, 265, 1056, 0, 219, - 257, 239, 275, 290, 293, 343, 411, 421, 451, 457, - 312, 287, 255, 483, 252, 509, 548, 549, 550, 552, - 415, 282, 456, 0, 0, 395, 606, 607, 335, 557, - 0, 809, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 438, 0, 0, 0, 796, 0, 0, 0, 286, - 801, 0, 0, 0, 385, 283, 0, 0, 212, 530, - 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, - 298, 289, 285, 264, 336, 405, 450, 547, 444, 808, - 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, - 0, 0, 0, 803, 804, 0, 0, 0, 0, 0, - 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, - 0, 101, 0, 0, 1057, 536, 991, 780, 957, 995, - 1058, 1009, 1010, 1011, 996, 0, 249, 997, 998, 256, - 999, 0, 956, 839, 841, 840, 906, 907, 908, 909, - 910, 911, 912, 842, 843, 837, 1004, 641, 1012, 1013, - 0, 281, 340, 288, 280, 612, 0, 0, 0, 0, - 0, 0, 628, 0, 0, 238, 0, 0, 0, 0, - 0, 0, 0, 776, 793, 0, 807, 0, 0, 0, - 0, 291, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 416, 0, 0, 0, 790, - 791, 0, 0, 0, 0, 951, 0, 792, 0, 0, - 800, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, - 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, - 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, - 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, - 1053, 1054, 1055, 3252, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 313, 0, 423, 273, 0, 477, - 0, 319, 334, 0, 0, 0, 0, 0, 0, 0, - 950, 0, 0, 661, 0, 0, 948, 0, 0, 0, - 0, 384, 0, 349, 205, 233, 0, 0, 434, 485, - 497, 0, 0, 0, 0, 1001, 0, 495, 448, 636, - 243, 300, 482, 455, 493, 463, 303, 0, 0, 494, - 391, 617, 473, 633, 662, 663, 279, 428, 647, 551, - 655, 680, 234, 276, 442, 535, 639, 519, 417, 613, - 614, 348, 518, 311, 209, 388, 668, 232, 503, 390, - 253, 241, 619, 644, 315, 267, 305, 480, 675, 221, - 546, 630, 250, 507, 0, 0, 683, 258, 529, 642, - 631, 223, 626, 528, 413, 345, 346, 222, 0, 481, - 284, 309, 0, 0, 274, 437, 1002, 1003, 272, 684, - 847, 654, 228, 0, 653, 430, 616, 627, 414, 402, - 227, 625, 412, 401, 353, 855, 856, 296, 324, 932, - 931, 930, 323, 325, 928, 929, 927, 215, 640, 658, - 0, 216, 0, 524, 643, 685, 475, 220, 244, 245, - 248, 0, 295, 299, 307, 310, 320, 321, 331, 386, - 441, 469, 465, 474, 0, 610, 634, 648, 660, 666, - 667, 669, 670, 671, 672, 673, 676, 674, 429, 329, - 520, 352, 392, 0, 0, 447, 496, 251, 638, 521, - 240, 604, 418, 427, 259, 261, 260, 235, 512, 609, - 246, 266, 938, 960, 949, 813, 814, 939, 940, 964, - 941, 816, 817, 961, 962, 810, 811, 815, 963, 965, - 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, - 696, 697, 698, 699, 700, 701, 702, 703, 681, 537, - 543, 538, 539, 540, 541, 542, 0, 544, 952, 799, - 798, 0, 805, 806, 0, 835, 836, 838, 844, 845, - 846, 857, 904, 905, 913, 915, 916, 914, 917, 918, - 919, 922, 923, 924, 925, 920, 921, 926, 818, 822, - 819, 820, 821, 833, 823, 824, 825, 826, 827, 828, - 829, 830, 831, 832, 834, 975, 976, 977, 978, 979, - 980, 850, 854, 853, 851, 852, 848, 849, 876, 875, - 877, 878, 879, 880, 881, 882, 884, 883, 885, 886, - 887, 888, 889, 890, 858, 859, 862, 863, 861, 860, - 864, 873, 874, 865, 866, 867, 868, 869, 870, 872, - 871, 891, 892, 893, 894, 895, 897, 896, 900, 901, - 899, 898, 903, 902, 797, 204, 229, 387, 0, 478, - 304, 682, 650, 508, 645, 214, 231, 966, 278, 967, - 0, 0, 971, 0, 0, 0, 973, 972, 0, 974, - 936, 935, 0, 0, 968, 969, 0, 970, 0, 0, - 206, 208, 217, 230, 242, 247, 254, 277, 292, 294, - 301, 314, 327, 328, 337, 338, 341, 347, 399, 406, - 407, 408, 409, 431, 432, 433, 436, 439, 440, 443, - 445, 446, 449, 454, 458, 459, 460, 462, 464, 466, - 479, 484, 498, 499, 500, 501, 502, 505, 506, 513, - 514, 515, 516, 517, 525, 526, 531, 532, 533, 534, - 545, 618, 620, 637, 657, 664, 504, 404, 452, 476, - 611, 0, 0, 981, 982, 983, 984, 985, 986, 987, - 988, 316, 632, 665, 629, 677, 659, 461, 397, 0, - 0, 400, 297, 322, 339, 0, 649, 527, 236, 490, - 306, 265, 1056, 0, 219, 257, 239, 275, 290, 293, - 343, 411, 421, 451, 457, 312, 287, 255, 483, 252, - 509, 548, 549, 550, 552, 415, 282, 456, 0, 0, - 395, 606, 607, 335, 557, 0, 809, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 438, 0, 0, 0, - 796, 0, 0, 0, 286, 801, 0, 0, 0, 385, - 283, 0, 0, 212, 530, 0, 453, 0, 211, 0, - 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, - 405, 450, 547, 444, 808, 389, 0, 0, 522, 422, - 0, 0, 0, 0, 0, 0, 0, 0, 803, 804, - 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, - 344, 210, 435, 523, 302, 0, 101, 0, 0, 1057, - 536, 991, 780, 957, 995, 1058, 1009, 1010, 1011, 996, - 0, 249, 997, 998, 256, 999, 0, 956, 839, 841, - 840, 906, 907, 908, 909, 910, 911, 912, 842, 843, - 837, 1004, 641, 1012, 1013, 0, 281, 340, 288, 280, - 612, 0, 0, 0, 0, 0, 0, 628, 0, 0, - 238, 0, 0, 0, 0, 0, 0, 0, 776, 793, - 0, 807, 0, 0, 0, 0, 291, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 416, 0, 0, 0, 790, 791, 0, 0, 0, 0, - 951, 0, 792, 0, 0, 800, 1014, 1015, 1016, 1017, - 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, - 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, - 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, - 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 3248, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 313, - 0, 423, 273, 0, 477, 0, 319, 334, 0, 0, - 0, 0, 0, 0, 0, 950, 0, 0, 661, 0, - 0, 948, 0, 0, 0, 0, 384, 0, 349, 205, - 233, 0, 0, 434, 485, 497, 0, 0, 0, 0, - 1001, 0, 495, 448, 636, 243, 300, 482, 455, 493, - 463, 303, 0, 0, 494, 391, 617, 473, 633, 662, - 663, 279, 428, 647, 551, 655, 680, 234, 276, 442, - 535, 639, 519, 417, 613, 614, 348, 518, 311, 209, - 388, 668, 232, 503, 390, 253, 241, 619, 644, 315, - 267, 305, 480, 675, 221, 546, 630, 250, 507, 0, - 0, 683, 258, 529, 642, 631, 223, 626, 528, 413, - 345, 346, 222, 0, 481, 284, 309, 0, 0, 274, - 437, 1002, 1003, 272, 684, 847, 654, 228, 0, 653, - 430, 616, 627, 414, 402, 227, 625, 412, 401, 353, - 855, 856, 296, 324, 932, 931, 930, 323, 325, 928, - 929, 927, 215, 640, 658, 0, 216, 0, 524, 643, - 685, 475, 220, 244, 245, 248, 0, 295, 299, 307, - 310, 320, 321, 331, 386, 441, 469, 465, 474, 0, - 610, 634, 648, 660, 666, 667, 669, 670, 671, 672, - 673, 676, 674, 429, 329, 520, 352, 392, 0, 0, - 447, 496, 251, 638, 521, 240, 604, 418, 427, 259, - 261, 260, 235, 512, 609, 246, 266, 938, 960, 949, - 813, 814, 939, 940, 964, 941, 816, 817, 961, 962, - 810, 811, 815, 963, 965, 686, 687, 688, 689, 690, - 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, - 701, 702, 703, 681, 537, 543, 538, 539, 540, 541, - 542, 0, 544, 952, 799, 798, 0, 805, 806, 0, - 835, 836, 838, 844, 845, 846, 857, 904, 905, 913, - 915, 916, 914, 917, 918, 919, 922, 923, 924, 925, - 920, 921, 926, 818, 822, 819, 820, 821, 833, 823, - 824, 825, 826, 827, 828, 829, 830, 831, 832, 834, - 975, 976, 977, 978, 979, 980, 850, 854, 853, 851, - 852, 848, 849, 876, 875, 877, 878, 879, 880, 881, - 882, 884, 883, 885, 886, 887, 888, 889, 890, 858, - 859, 862, 863, 861, 860, 864, 873, 874, 865, 866, - 867, 868, 869, 870, 872, 871, 891, 892, 893, 894, - 895, 897, 896, 900, 901, 899, 898, 903, 902, 797, - 204, 229, 387, 0, 478, 304, 682, 650, 508, 645, - 214, 231, 966, 278, 967, 0, 0, 971, 0, 0, - 0, 973, 972, 0, 974, 936, 935, 0, 0, 968, - 969, 0, 970, 0, 0, 206, 208, 217, 230, 242, - 247, 254, 277, 292, 294, 301, 314, 327, 328, 337, - 338, 341, 347, 399, 406, 407, 408, 409, 431, 432, - 433, 436, 439, 440, 443, 445, 446, 449, 454, 458, - 459, 460, 462, 464, 466, 479, 484, 498, 499, 500, - 501, 502, 505, 506, 513, 514, 515, 516, 517, 525, - 526, 531, 532, 533, 534, 545, 618, 620, 637, 657, - 664, 504, 404, 452, 476, 611, 0, 0, 981, 982, - 983, 984, 985, 986, 987, 988, 316, 632, 665, 629, - 677, 659, 461, 397, 0, 0, 400, 297, 322, 339, - 0, 649, 527, 236, 490, 306, 265, 1056, 0, 219, - 257, 239, 275, 290, 293, 343, 411, 421, 451, 457, - 312, 287, 255, 483, 252, 509, 548, 549, 550, 552, - 415, 282, 456, 0, 0, 395, 606, 607, 335, 557, - 0, 809, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 438, 0, 0, 0, 796, 0, 0, 0, 286, - 801, 0, 0, 0, 385, 283, 0, 0, 212, 530, - 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, - 298, 289, 285, 264, 336, 405, 450, 547, 444, 808, - 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, - 0, 0, 0, 803, 804, 0, 0, 0, 0, 0, - 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, - 0, 101, 0, 0, 1057, 536, 991, 1131, 957, 995, - 1058, 1009, 1010, 1011, 996, 0, 249, 997, 998, 256, - 999, 0, 956, 839, 841, 840, 906, 907, 908, 909, - 910, 911, 912, 842, 843, 837, 1004, 641, 1012, 1013, - 0, 281, 340, 288, 280, 612, 0, 0, 0, 0, - 0, 0, 628, 0, 0, 238, 0, 0, 0, 0, - 0, 0, 0, 0, 793, 0, 807, 0, 0, 0, - 0, 291, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 416, 0, 0, 0, 790, - 791, 0, 0, 0, 0, 951, 0, 792, 0, 0, - 800, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, - 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, - 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, - 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, - 1053, 1054, 1055, 802, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 313, 0, 423, 273, 0, 477, - 0, 319, 334, 0, 0, 0, 0, 0, 0, 0, - 950, 0, 0, 661, 0, 0, 948, 0, 0, 0, - 0, 384, 0, 349, 205, 233, 0, 0, 434, 485, - 497, 0, 0, 0, 0, 1001, 0, 495, 448, 636, - 243, 300, 482, 455, 493, 463, 303, 0, 0, 494, - 391, 617, 473, 633, 662, 663, 279, 428, 647, 551, - 655, 680, 234, 276, 442, 535, 639, 519, 417, 613, - 614, 348, 518, 311, 209, 388, 668, 232, 503, 390, - 253, 241, 619, 644, 315, 267, 305, 480, 675, 221, - 546, 630, 250, 507, 0, 0, 683, 258, 529, 642, - 631, 223, 626, 528, 413, 345, 346, 222, 0, 481, - 284, 309, 0, 0, 274, 437, 1002, 1003, 272, 684, - 847, 654, 228, 0, 653, 430, 616, 627, 414, 402, - 227, 625, 412, 401, 353, 855, 856, 296, 324, 932, - 931, 930, 323, 325, 928, 929, 927, 215, 640, 658, - 0, 216, 0, 524, 643, 685, 475, 220, 244, 245, - 248, 0, 295, 299, 307, 310, 320, 321, 331, 386, - 441, 469, 465, 474, 0, 610, 634, 648, 660, 666, - 667, 669, 670, 671, 672, 673, 676, 674, 429, 329, - 520, 352, 392, 0, 0, 447, 496, 251, 638, 521, - 240, 604, 418, 427, 259, 261, 260, 235, 512, 609, - 246, 266, 938, 960, 949, 813, 814, 939, 940, 964, - 941, 816, 817, 961, 962, 810, 811, 815, 963, 965, - 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, - 696, 697, 698, 699, 700, 701, 702, 703, 681, 537, - 543, 538, 539, 540, 541, 542, 0, 544, 952, 799, - 798, 0, 805, 806, 0, 835, 836, 838, 844, 845, - 846, 857, 904, 905, 913, 915, 916, 914, 917, 918, - 919, 922, 923, 924, 925, 920, 921, 926, 818, 822, - 819, 820, 821, 833, 823, 824, 825, 826, 827, 828, - 829, 830, 831, 832, 834, 975, 976, 977, 978, 979, - 980, 850, 854, 853, 851, 852, 848, 849, 876, 875, - 877, 878, 879, 880, 881, 882, 884, 883, 885, 886, - 887, 888, 889, 890, 858, 859, 862, 863, 861, 860, - 864, 873, 874, 865, 866, 867, 868, 869, 870, 872, - 871, 891, 892, 893, 894, 895, 897, 896, 900, 901, - 899, 898, 903, 902, 797, 204, 229, 387, 0, 478, - 304, 682, 650, 508, 645, 214, 231, 966, 278, 967, - 0, 0, 971, 0, 0, 0, 973, 972, 0, 974, - 936, 935, 0, 0, 968, 969, 0, 970, 0, 0, - 206, 208, 217, 230, 242, 247, 254, 277, 292, 294, - 301, 314, 327, 328, 337, 338, 341, 347, 399, 406, - 407, 408, 409, 431, 432, 433, 436, 439, 440, 443, - 445, 446, 449, 454, 458, 459, 460, 462, 464, 466, - 479, 484, 498, 499, 500, 501, 502, 505, 506, 513, - 514, 515, 516, 517, 525, 526, 531, 532, 533, 534, - 545, 618, 620, 637, 657, 664, 504, 404, 452, 476, - 611, 0, 0, 981, 982, 983, 984, 985, 986, 987, - 988, 316, 632, 665, 629, 677, 659, 461, 397, 0, - 0, 400, 297, 322, 339, 0, 649, 527, 236, 490, - 306, 265, 1056, 0, 219, 257, 239, 275, 290, 293, - 343, 411, 421, 451, 457, 312, 287, 255, 483, 252, - 509, 548, 549, 550, 552, 415, 282, 456, 0, 0, - 395, 606, 607, 335, 557, 0, 809, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 438, 0, 0, 0, - 796, 0, 0, 0, 286, 801, 0, 0, 0, 385, - 283, 0, 0, 212, 530, 0, 453, 0, 211, 0, - 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, - 405, 450, 547, 444, 808, 389, 0, 0, 522, 422, - 0, 0, 0, 0, 0, 0, 0, 0, 803, 804, - 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, - 344, 210, 435, 523, 302, 0, 101, 0, 0, 1057, - 536, 991, 1131, 957, 995, 1058, 1009, 1010, 1011, 996, - 0, 249, 997, 998, 256, 999, 0, 956, 839, 841, - 840, 906, 907, 908, 909, 910, 911, 912, 842, 843, - 837, 1004, 641, 1012, 1013, 0, 281, 340, 288, 280, - 612, 0, 0, 0, 0, 0, 0, 628, 0, 0, - 238, 0, 0, 0, 0, 0, 0, 0, 0, 793, - 0, 807, 0, 0, 0, 0, 291, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 416, 0, 0, 0, 790, 791, 0, 0, 0, 0, - 951, 0, 792, 0, 0, 800, 1014, 1015, 1016, 1017, - 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, - 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, - 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, - 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 2185, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 313, - 0, 423, 273, 0, 477, 0, 319, 334, 0, 0, - 0, 0, 0, 0, 0, 950, 0, 0, 661, 0, - 0, 948, 0, 0, 0, 0, 384, 0, 349, 205, - 233, 0, 0, 434, 485, 497, 0, 0, 0, 0, - 1001, 0, 495, 448, 636, 243, 300, 482, 455, 493, - 463, 303, 0, 0, 494, 391, 617, 473, 633, 662, - 663, 279, 428, 647, 551, 655, 680, 234, 276, 442, - 535, 639, 519, 417, 613, 614, 348, 518, 311, 209, - 388, 668, 232, 503, 390, 253, 241, 619, 644, 315, - 267, 305, 480, 675, 221, 546, 630, 250, 507, 0, - 0, 683, 258, 529, 642, 631, 223, 626, 528, 413, - 345, 346, 222, 0, 481, 284, 309, 0, 0, 274, - 437, 1002, 1003, 272, 684, 847, 654, 228, 0, 653, - 430, 616, 627, 414, 402, 227, 625, 412, 401, 353, - 855, 856, 296, 324, 932, 931, 930, 323, 325, 928, - 929, 927, 215, 640, 658, 0, 216, 0, 524, 643, - 685, 475, 220, 244, 245, 248, 0, 295, 299, 307, - 310, 320, 321, 331, 386, 441, 469, 465, 474, 0, - 610, 634, 648, 660, 666, 667, 669, 670, 671, 672, - 673, 676, 674, 429, 329, 520, 352, 392, 0, 0, - 447, 496, 251, 638, 521, 240, 604, 418, 427, 259, - 261, 260, 235, 512, 609, 246, 266, 938, 960, 949, - 813, 814, 939, 940, 964, 941, 816, 817, 961, 962, - 810, 811, 815, 963, 965, 686, 687, 688, 689, 690, - 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, - 701, 702, 703, 681, 537, 543, 538, 539, 540, 541, - 542, 0, 544, 952, 799, 798, 0, 805, 806, 0, - 835, 836, 838, 844, 845, 846, 857, 904, 905, 913, - 915, 916, 914, 917, 918, 919, 922, 923, 924, 925, - 920, 921, 926, 818, 822, 819, 820, 821, 833, 823, - 824, 825, 826, 827, 828, 829, 830, 831, 832, 834, - 975, 976, 977, 978, 979, 980, 850, 854, 853, 851, - 852, 848, 849, 876, 875, 877, 878, 879, 880, 881, - 882, 884, 883, 885, 886, 887, 888, 889, 890, 858, - 859, 862, 863, 861, 860, 864, 873, 874, 865, 866, - 867, 868, 869, 870, 872, 871, 891, 892, 893, 894, - 895, 897, 896, 900, 901, 899, 898, 903, 902, 797, - 204, 229, 387, 0, 478, 304, 682, 650, 508, 645, - 214, 231, 966, 278, 967, 0, 0, 971, 0, 0, - 0, 973, 972, 0, 974, 936, 935, 0, 0, 968, - 969, 0, 970, 0, 0, 206, 208, 217, 230, 242, - 247, 254, 277, 292, 294, 301, 314, 327, 328, 337, - 338, 341, 347, 399, 406, 407, 408, 409, 431, 432, - 433, 436, 439, 440, 443, 445, 446, 449, 454, 458, - 459, 460, 462, 464, 466, 479, 484, 498, 499, 500, - 501, 502, 505, 506, 513, 514, 515, 516, 517, 525, - 526, 531, 532, 533, 534, 545, 618, 620, 637, 657, - 664, 504, 404, 452, 476, 611, 0, 0, 981, 982, - 983, 984, 985, 986, 987, 988, 316, 632, 665, 629, - 677, 659, 461, 397, 0, 0, 400, 297, 322, 339, - 0, 649, 527, 236, 490, 306, 265, 1056, 0, 219, - 257, 239, 275, 290, 293, 343, 411, 421, 451, 457, - 312, 287, 255, 483, 252, 509, 548, 549, 550, 552, - 415, 282, 456, 0, 0, 395, 606, 607, 335, 557, - 0, 809, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 438, 0, 0, 0, 796, 0, 0, 0, 286, - 801, 0, 0, 0, 385, 283, 0, 0, 212, 530, - 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, - 298, 289, 285, 264, 336, 405, 450, 547, 444, 808, - 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, - 0, 0, 0, 803, 804, 0, 0, 0, 0, 0, - 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, - 0, 101, 0, 0, 1057, 536, 991, 1131, 957, 995, - 1058, 1009, 1010, 1011, 996, 0, 249, 997, 998, 256, - 999, 0, 956, 839, 841, 840, 906, 907, 908, 909, - 910, 911, 912, 842, 843, 837, 1004, 641, 1012, 1013, - 0, 281, 340, 288, 280, 612, 0, 0, 0, 0, - 0, 0, 628, 0, 0, 238, 0, 0, 0, 0, - 0, 0, 0, 0, 793, 0, 807, 0, 0, 0, - 0, 291, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 416, 0, 0, 0, 790, - 791, 0, 0, 0, 0, 951, 0, 792, 0, 0, - 800, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, - 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, - 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, - 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, - 1053, 1054, 1055, 2183, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 313, 0, 423, 273, 0, 477, - 0, 319, 334, 0, 0, 0, 0, 0, 0, 0, - 950, 0, 0, 661, 0, 0, 948, 0, 0, 0, - 0, 384, 0, 349, 205, 233, 0, 0, 434, 485, - 497, 0, 0, 0, 0, 1001, 0, 495, 448, 636, - 243, 300, 482, 455, 493, 463, 303, 0, 0, 494, - 391, 617, 473, 633, 662, 663, 279, 428, 647, 551, - 655, 680, 234, 276, 442, 535, 639, 519, 417, 613, - 614, 348, 518, 311, 209, 388, 668, 232, 503, 390, - 253, 241, 619, 644, 315, 267, 305, 480, 675, 221, - 546, 630, 250, 507, 0, 0, 683, 258, 529, 642, - 631, 223, 626, 528, 413, 345, 346, 222, 0, 481, - 284, 309, 0, 0, 274, 437, 1002, 1003, 272, 684, - 847, 654, 228, 0, 653, 430, 616, 627, 414, 402, - 227, 625, 412, 401, 353, 855, 856, 296, 324, 932, - 931, 930, 323, 325, 928, 929, 927, 215, 640, 658, - 0, 216, 0, 524, 643, 685, 475, 220, 244, 245, - 248, 0, 295, 299, 307, 310, 320, 321, 331, 386, - 441, 469, 465, 474, 0, 610, 634, 648, 660, 666, - 667, 669, 670, 671, 672, 673, 676, 674, 429, 329, - 520, 352, 392, 0, 0, 447, 496, 251, 638, 521, - 240, 604, 418, 427, 259, 261, 260, 235, 512, 609, - 246, 266, 938, 960, 949, 813, 814, 939, 940, 964, - 941, 816, 817, 961, 962, 810, 811, 815, 963, 965, - 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, - 696, 697, 698, 699, 700, 701, 702, 703, 681, 537, - 543, 538, 539, 540, 541, 542, 0, 544, 952, 799, - 798, 0, 805, 806, 0, 835, 836, 838, 844, 845, - 846, 857, 904, 905, 913, 915, 916, 914, 917, 918, - 919, 922, 923, 924, 925, 920, 921, 926, 818, 822, - 819, 820, 821, 833, 823, 824, 825, 826, 827, 828, - 829, 830, 831, 832, 834, 975, 976, 977, 978, 979, - 980, 850, 854, 853, 851, 852, 848, 849, 876, 875, - 877, 878, 879, 880, 881, 882, 884, 883, 885, 886, - 887, 888, 889, 890, 858, 859, 862, 863, 861, 860, - 864, 873, 874, 865, 866, 867, 868, 869, 870, 872, - 871, 891, 892, 893, 894, 895, 897, 896, 900, 901, - 899, 898, 903, 902, 797, 204, 229, 387, 0, 478, - 304, 682, 650, 508, 645, 214, 231, 966, 278, 967, - 0, 0, 971, 0, 0, 0, 973, 972, 0, 974, - 936, 935, 0, 0, 968, 969, 0, 970, 0, 0, - 206, 208, 217, 230, 242, 247, 254, 277, 292, 294, - 301, 314, 327, 328, 337, 338, 341, 347, 399, 406, - 407, 408, 409, 431, 432, 433, 436, 439, 440, 443, - 445, 446, 449, 454, 458, 459, 460, 462, 464, 466, - 479, 484, 498, 499, 500, 501, 502, 505, 506, 513, - 514, 515, 516, 517, 525, 526, 531, 532, 533, 534, - 545, 618, 620, 637, 657, 664, 504, 404, 452, 476, - 611, 0, 0, 981, 982, 983, 984, 985, 986, 987, - 988, 316, 632, 665, 629, 677, 659, 461, 397, 0, - 0, 400, 297, 322, 339, 0, 649, 527, 236, 490, - 306, 265, 1056, 0, 219, 257, 239, 275, 290, 293, - 343, 411, 421, 451, 457, 312, 287, 255, 483, 252, - 509, 548, 549, 550, 552, 415, 282, 456, 557, 0, - 395, 606, 607, 335, 0, 0, 0, 0, 0, 0, - 438, 0, 0, 0, 0, 0, 0, 0, 286, 0, + 606, 607, 335, 557, 0, 809, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 438, 0, 0, 0, 796, + 0, 0, 0, 286, 801, 0, 0, 0, 385, 283, + 0, 0, 212, 530, 0, 453, 0, 211, 0, 511, + 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, + 450, 547, 444, 808, 389, 0, 0, 522, 422, 0, + 0, 0, 0, 0, 0, 0, 0, 803, 804, 0, + 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, + 210, 435, 523, 302, 0, 101, 0, 0, 1057, 536, + 991, 780, 957, 995, 1058, 1009, 1010, 1011, 996, 0, + 249, 997, 998, 256, 999, 0, 956, 839, 841, 840, + 906, 907, 908, 909, 910, 911, 912, 842, 843, 837, + 1004, 641, 1012, 1013, 0, 281, 340, 288, 280, 612, + 0, 0, 0, 0, 0, 0, 628, 0, 0, 238, + 0, 0, 0, 0, 0, 0, 0, 776, 793, 0, + 807, 0, 0, 0, 0, 291, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, + 0, 0, 0, 790, 791, 1113, 0, 0, 0, 951, + 0, 792, 0, 0, 800, 1014, 1015, 1016, 1017, 1018, + 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, + 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, + 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, + 1049, 1050, 1051, 1052, 1053, 1054, 1055, 802, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 313, 0, + 423, 273, 0, 477, 0, 319, 334, 0, 0, 0, + 0, 0, 0, 0, 950, 0, 0, 661, 0, 0, + 948, 0, 0, 0, 0, 384, 0, 349, 205, 233, + 0, 0, 434, 485, 497, 0, 0, 0, 0, 1001, + 0, 495, 448, 636, 243, 300, 482, 455, 493, 463, + 303, 0, 0, 494, 391, 617, 473, 633, 662, 663, + 279, 428, 647, 551, 655, 680, 234, 276, 442, 535, + 639, 519, 417, 613, 614, 348, 518, 311, 209, 388, + 668, 232, 503, 390, 253, 241, 619, 644, 315, 267, + 305, 480, 675, 221, 546, 630, 250, 507, 0, 0, + 683, 258, 529, 642, 631, 223, 626, 528, 413, 345, + 346, 222, 0, 481, 284, 309, 0, 0, 274, 437, + 1002, 1003, 272, 684, 847, 654, 228, 0, 653, 430, + 616, 627, 414, 402, 227, 625, 412, 401, 353, 855, + 856, 296, 324, 932, 931, 930, 323, 325, 928, 929, + 927, 215, 640, 658, 0, 216, 0, 524, 643, 685, + 475, 220, 244, 245, 248, 0, 295, 299, 307, 310, + 320, 321, 331, 386, 441, 469, 465, 474, 0, 610, + 634, 648, 660, 666, 667, 669, 670, 671, 672, 673, + 676, 674, 429, 329, 520, 352, 392, 0, 0, 447, + 496, 251, 638, 521, 240, 604, 418, 427, 259, 261, + 260, 235, 512, 609, 246, 266, 938, 960, 949, 813, + 814, 939, 940, 964, 941, 816, 817, 961, 962, 810, + 811, 815, 963, 965, 686, 687, 688, 689, 690, 691, + 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, + 702, 703, 681, 537, 543, 538, 539, 540, 541, 542, + 0, 544, 952, 799, 798, 0, 805, 806, 0, 835, + 836, 838, 844, 845, 846, 857, 904, 905, 913, 915, + 916, 914, 917, 918, 919, 922, 923, 924, 925, 920, + 921, 926, 818, 822, 819, 820, 821, 833, 823, 824, + 825, 826, 827, 828, 829, 830, 831, 832, 834, 975, + 976, 977, 978, 979, 980, 850, 854, 853, 851, 852, + 848, 849, 876, 875, 877, 878, 879, 880, 881, 882, + 884, 883, 885, 886, 887, 888, 889, 890, 858, 859, + 862, 863, 861, 860, 864, 873, 874, 865, 866, 867, + 868, 869, 870, 872, 871, 891, 892, 893, 894, 895, + 897, 896, 900, 901, 899, 898, 903, 902, 797, 204, + 229, 387, 0, 478, 304, 682, 650, 508, 645, 214, + 231, 966, 278, 967, 0, 0, 971, 0, 0, 0, + 973, 972, 0, 974, 936, 935, 0, 0, 968, 969, + 0, 970, 0, 0, 206, 208, 217, 230, 242, 247, + 254, 277, 292, 294, 301, 314, 327, 328, 337, 338, + 341, 347, 399, 406, 407, 408, 409, 431, 432, 433, + 436, 439, 440, 443, 445, 446, 449, 454, 458, 459, + 460, 462, 464, 466, 479, 484, 498, 499, 500, 501, + 502, 505, 506, 513, 514, 515, 516, 517, 525, 526, + 531, 532, 533, 534, 545, 618, 620, 637, 657, 664, + 504, 404, 452, 476, 611, 0, 0, 981, 982, 983, + 984, 985, 986, 987, 988, 316, 632, 665, 629, 677, + 659, 461, 397, 0, 0, 400, 297, 322, 339, 0, + 649, 527, 236, 490, 306, 265, 1056, 0, 219, 257, + 239, 275, 290, 293, 343, 411, 421, 451, 457, 312, + 287, 255, 483, 252, 509, 548, 549, 550, 552, 415, + 282, 456, 0, 0, 395, 606, 607, 335, 557, 0, + 809, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 438, 0, 0, 0, 796, 0, 0, 0, 286, 801, + 0, 0, 0, 385, 283, 0, 0, 212, 530, 0, + 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, + 289, 285, 264, 336, 405, 450, 547, 444, 808, 389, + 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, + 0, 0, 803, 804, 0, 0, 0, 0, 0, 0, + 0, 0, 342, 262, 344, 210, 435, 523, 302, 0, + 101, 0, 0, 1057, 536, 991, 780, 957, 995, 1058, + 1009, 1010, 1011, 996, 0, 249, 997, 998, 256, 999, + 0, 956, 839, 841, 840, 906, 907, 908, 909, 910, + 911, 912, 842, 843, 837, 1004, 641, 1012, 1013, 0, + 281, 340, 288, 280, 612, 0, 0, 0, 0, 0, + 0, 628, 0, 0, 238, 0, 0, 0, 0, 0, + 0, 0, 776, 793, 0, 807, 0, 0, 0, 0, + 291, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 416, 0, 0, 0, 790, 791, + 1109, 0, 0, 0, 951, 0, 792, 0, 0, 800, + 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, + 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, + 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, + 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, + 1054, 1055, 802, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 313, 0, 423, 273, 0, 477, 0, + 319, 334, 0, 0, 0, 0, 0, 0, 0, 950, + 0, 0, 661, 0, 0, 948, 0, 0, 0, 0, + 384, 0, 349, 205, 233, 0, 0, 434, 485, 497, + 0, 0, 0, 0, 1001, 0, 495, 448, 636, 243, + 300, 482, 455, 493, 463, 303, 0, 0, 494, 391, + 617, 473, 633, 662, 663, 279, 428, 647, 551, 655, + 680, 234, 276, 442, 535, 639, 519, 417, 613, 614, + 348, 518, 311, 209, 388, 668, 232, 503, 390, 253, + 241, 619, 644, 315, 267, 305, 480, 675, 221, 546, + 630, 250, 507, 0, 0, 683, 258, 529, 642, 631, + 223, 626, 528, 413, 345, 346, 222, 0, 481, 284, + 309, 0, 0, 274, 437, 1002, 1003, 272, 684, 847, + 654, 228, 0, 653, 430, 616, 627, 414, 402, 227, + 625, 412, 401, 353, 855, 856, 296, 324, 932, 931, + 930, 323, 325, 928, 929, 927, 215, 640, 658, 0, + 216, 0, 524, 643, 685, 475, 220, 244, 245, 248, + 0, 295, 299, 307, 310, 320, 321, 331, 386, 441, + 469, 465, 474, 0, 610, 634, 648, 660, 666, 667, + 669, 670, 671, 672, 673, 676, 674, 429, 329, 520, + 352, 392, 0, 0, 447, 496, 251, 638, 521, 240, + 604, 418, 427, 259, 261, 260, 235, 512, 609, 246, + 266, 938, 960, 949, 813, 814, 939, 940, 964, 941, + 816, 817, 961, 962, 810, 811, 815, 963, 965, 686, + 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, + 697, 698, 699, 700, 701, 702, 703, 681, 537, 543, + 538, 539, 540, 541, 542, 0, 544, 952, 799, 798, + 0, 805, 806, 0, 835, 836, 838, 844, 845, 846, + 857, 904, 905, 913, 915, 916, 914, 917, 918, 919, + 922, 923, 924, 925, 920, 921, 926, 818, 822, 819, + 820, 821, 833, 823, 824, 825, 826, 827, 828, 829, + 830, 831, 832, 834, 975, 976, 977, 978, 979, 980, + 850, 854, 853, 851, 852, 848, 849, 876, 875, 877, + 878, 879, 880, 881, 882, 884, 883, 885, 886, 887, + 888, 889, 890, 858, 859, 862, 863, 861, 860, 864, + 873, 874, 865, 866, 867, 868, 869, 870, 872, 871, + 891, 892, 893, 894, 895, 897, 896, 900, 901, 899, + 898, 903, 902, 797, 204, 229, 387, 0, 478, 304, + 682, 650, 508, 645, 214, 231, 966, 278, 967, 0, + 0, 971, 0, 0, 0, 973, 972, 0, 974, 936, + 935, 0, 0, 968, 969, 0, 970, 0, 0, 206, + 208, 217, 230, 242, 247, 254, 277, 292, 294, 301, + 314, 327, 328, 337, 338, 341, 347, 399, 406, 407, + 408, 409, 431, 432, 433, 436, 439, 440, 443, 445, + 446, 449, 454, 458, 459, 460, 462, 464, 466, 479, + 484, 498, 499, 500, 501, 502, 505, 506, 513, 514, + 515, 516, 517, 525, 526, 531, 532, 533, 534, 545, + 618, 620, 637, 657, 664, 504, 404, 452, 476, 611, + 0, 0, 981, 982, 983, 984, 985, 986, 987, 988, + 316, 632, 665, 629, 677, 659, 461, 397, 0, 0, + 400, 297, 322, 339, 0, 649, 527, 236, 490, 306, + 265, 1056, 0, 219, 257, 239, 275, 290, 293, 343, + 411, 421, 451, 457, 312, 287, 255, 483, 252, 509, + 548, 549, 550, 552, 415, 282, 456, 0, 0, 395, + 606, 607, 335, 557, 0, 809, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 438, 0, 0, 0, 796, + 0, 0, 0, 286, 801, 0, 0, 0, 385, 283, + 0, 0, 212, 530, 0, 453, 0, 211, 0, 511, + 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, + 450, 547, 444, 808, 389, 0, 0, 522, 422, 0, + 0, 0, 0, 0, 0, 0, 0, 803, 804, 0, + 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, + 210, 435, 523, 302, 0, 101, 0, 0, 1057, 536, + 991, 780, 957, 995, 1058, 1009, 1010, 1011, 996, 0, + 249, 997, 998, 256, 999, 0, 956, 839, 841, 840, + 906, 907, 908, 909, 910, 911, 912, 842, 843, 837, + 1004, 641, 1012, 1013, 0, 281, 340, 288, 280, 612, + 0, 0, 0, 0, 0, 0, 628, 0, 0, 238, + 0, 0, 0, 0, 0, 0, 0, 776, 793, 0, + 807, 0, 0, 0, 0, 291, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, + 0, 0, 0, 790, 791, 0, 0, 0, 0, 951, + 0, 792, 0, 0, 800, 1014, 1015, 1016, 1017, 1018, + 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, + 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, + 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, + 1049, 1050, 1051, 1052, 1053, 1054, 1055, 802, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 313, 0, + 423, 273, 0, 477, 0, 319, 334, 0, 0, 0, + 0, 0, 0, 0, 950, 0, 0, 661, 0, 0, + 948, 0, 0, 0, 0, 384, 0, 349, 205, 233, + 0, 0, 434, 485, 497, 0, 0, 0, 0, 1001, + 0, 495, 448, 636, 243, 300, 482, 455, 493, 463, + 303, 0, 0, 494, 391, 617, 473, 633, 662, 663, + 279, 428, 647, 551, 655, 680, 234, 276, 442, 535, + 639, 519, 417, 613, 614, 348, 518, 311, 209, 388, + 668, 232, 503, 390, 253, 241, 619, 644, 315, 267, + 305, 480, 675, 221, 546, 630, 250, 507, 0, 0, + 683, 258, 529, 642, 631, 223, 626, 528, 413, 345, + 346, 222, 0, 481, 284, 309, 0, 0, 274, 437, + 1002, 1003, 272, 684, 847, 654, 228, 0, 653, 430, + 616, 627, 414, 402, 227, 625, 412, 401, 353, 855, + 856, 296, 324, 932, 931, 930, 323, 325, 928, 929, + 927, 215, 640, 658, 0, 216, 0, 524, 643, 685, + 475, 220, 244, 245, 248, 0, 295, 299, 307, 310, + 320, 321, 331, 386, 441, 469, 465, 474, 0, 610, + 634, 648, 660, 666, 667, 669, 670, 671, 672, 673, + 676, 674, 429, 329, 520, 352, 392, 0, 0, 447, + 496, 251, 638, 521, 240, 604, 418, 427, 259, 261, + 260, 235, 512, 609, 246, 266, 938, 960, 949, 813, + 814, 939, 940, 964, 941, 816, 817, 961, 962, 810, + 811, 815, 963, 965, 686, 687, 688, 689, 690, 691, + 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, + 702, 703, 681, 537, 543, 538, 539, 540, 541, 542, + 0, 544, 952, 799, 798, 0, 805, 806, 0, 835, + 836, 838, 844, 845, 846, 857, 904, 905, 913, 915, + 916, 914, 917, 918, 919, 922, 923, 924, 925, 920, + 921, 926, 818, 822, 819, 820, 821, 833, 823, 824, + 825, 826, 827, 828, 829, 830, 831, 832, 834, 975, + 976, 977, 978, 979, 980, 850, 854, 853, 851, 852, + 848, 849, 876, 875, 877, 878, 879, 880, 881, 882, + 884, 883, 885, 886, 887, 888, 889, 890, 858, 859, + 862, 863, 861, 860, 864, 873, 874, 865, 866, 867, + 868, 869, 870, 872, 871, 891, 892, 893, 894, 895, + 897, 896, 900, 901, 899, 898, 903, 902, 797, 204, + 229, 387, 0, 478, 304, 682, 650, 508, 645, 214, + 231, 966, 278, 967, 0, 0, 971, 0, 0, 0, + 973, 972, 0, 974, 936, 935, 0, 0, 968, 969, + 0, 970, 0, 0, 206, 208, 217, 230, 242, 247, + 254, 277, 292, 294, 301, 314, 327, 328, 337, 338, + 341, 347, 399, 406, 407, 408, 409, 431, 432, 433, + 436, 439, 440, 443, 445, 446, 449, 454, 458, 459, + 460, 462, 464, 466, 479, 484, 498, 499, 500, 501, + 502, 505, 506, 513, 514, 515, 516, 517, 525, 526, + 531, 532, 533, 534, 545, 618, 620, 637, 657, 664, + 504, 404, 452, 476, 611, 0, 0, 981, 982, 983, + 984, 985, 986, 987, 988, 316, 632, 665, 629, 677, + 659, 461, 397, 0, 0, 400, 297, 322, 339, 0, + 649, 527, 236, 490, 306, 265, 1056, 0, 219, 257, + 239, 275, 290, 293, 343, 411, 421, 451, 457, 312, + 287, 255, 483, 252, 509, 548, 549, 550, 552, 415, + 282, 456, 0, 0, 395, 606, 607, 335, 557, 0, + 809, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 438, 0, 0, 0, 796, 0, 0, 0, 286, 801, + 0, 0, 0, 385, 283, 0, 0, 212, 530, 0, + 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, + 289, 285, 264, 336, 405, 450, 547, 444, 808, 389, + 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, + 0, 0, 803, 804, 0, 0, 0, 0, 0, 0, + 0, 0, 342, 262, 344, 210, 435, 523, 302, 0, + 101, 0, 0, 1057, 536, 991, 780, 957, 995, 1058, + 1009, 1010, 1011, 996, 0, 249, 997, 998, 256, 999, + 0, 956, 839, 841, 840, 906, 907, 908, 909, 910, + 911, 912, 842, 843, 837, 1004, 641, 1012, 1013, 0, + 281, 340, 288, 280, 612, 0, 0, 0, 0, 0, + 0, 628, 0, 0, 238, 0, 0, 0, 0, 0, + 0, 0, 776, 793, 0, 807, 0, 0, 0, 0, + 291, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 416, 0, 0, 0, 790, 791, + 0, 0, 0, 0, 951, 0, 792, 0, 0, 800, + 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, + 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, + 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, + 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, + 1054, 1055, 3259, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 313, 0, 423, 273, 0, 477, 0, + 319, 334, 0, 0, 0, 0, 0, 0, 0, 950, + 0, 0, 661, 0, 0, 948, 0, 0, 0, 0, + 384, 0, 349, 205, 233, 0, 0, 434, 485, 497, + 0, 0, 0, 0, 1001, 0, 495, 448, 636, 243, + 300, 482, 455, 493, 463, 303, 0, 0, 494, 391, + 617, 473, 633, 662, 663, 279, 428, 647, 551, 655, + 680, 234, 276, 442, 535, 639, 519, 417, 613, 614, + 348, 518, 311, 209, 388, 668, 232, 503, 390, 253, + 241, 619, 644, 315, 267, 305, 480, 675, 221, 546, + 630, 250, 507, 0, 0, 683, 258, 529, 642, 631, + 223, 626, 528, 413, 345, 346, 222, 0, 481, 284, + 309, 0, 0, 274, 437, 1002, 1003, 272, 684, 847, + 654, 228, 0, 653, 430, 616, 627, 414, 402, 227, + 625, 412, 401, 353, 855, 856, 296, 324, 932, 931, + 930, 323, 325, 928, 929, 927, 215, 640, 658, 0, + 216, 0, 524, 643, 685, 475, 220, 244, 245, 248, + 0, 295, 299, 307, 310, 320, 321, 331, 386, 441, + 469, 465, 474, 0, 610, 634, 648, 660, 666, 667, + 669, 670, 671, 672, 673, 676, 674, 429, 329, 520, + 352, 392, 0, 0, 447, 496, 251, 638, 521, 240, + 604, 418, 427, 259, 261, 260, 235, 512, 609, 246, + 266, 938, 960, 949, 813, 814, 939, 940, 964, 941, + 816, 817, 961, 962, 810, 811, 815, 963, 965, 686, + 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, + 697, 698, 699, 700, 701, 702, 703, 681, 537, 543, + 538, 539, 540, 541, 542, 0, 544, 952, 799, 798, + 0, 805, 806, 0, 835, 836, 838, 844, 845, 846, + 857, 904, 905, 913, 915, 916, 914, 917, 918, 919, + 922, 923, 924, 925, 920, 921, 926, 818, 822, 819, + 820, 821, 833, 823, 824, 825, 826, 827, 828, 829, + 830, 831, 832, 834, 975, 976, 977, 978, 979, 980, + 850, 854, 853, 851, 852, 848, 849, 876, 875, 877, + 878, 879, 880, 881, 882, 884, 883, 885, 886, 887, + 888, 889, 890, 858, 859, 862, 863, 861, 860, 864, + 873, 874, 865, 866, 867, 868, 869, 870, 872, 871, + 891, 892, 893, 894, 895, 897, 896, 900, 901, 899, + 898, 903, 902, 797, 204, 229, 387, 0, 478, 304, + 682, 650, 508, 645, 214, 231, 966, 278, 967, 0, + 0, 971, 0, 0, 0, 973, 972, 0, 974, 936, + 935, 0, 0, 968, 969, 0, 970, 0, 0, 206, + 208, 217, 230, 242, 247, 254, 277, 292, 294, 301, + 314, 327, 328, 337, 338, 341, 347, 399, 406, 407, + 408, 409, 431, 432, 433, 436, 439, 440, 443, 445, + 446, 449, 454, 458, 459, 460, 462, 464, 466, 479, + 484, 498, 499, 500, 501, 502, 505, 506, 513, 514, + 515, 516, 517, 525, 526, 531, 532, 533, 534, 545, + 618, 620, 637, 657, 664, 504, 404, 452, 476, 611, + 0, 0, 981, 982, 983, 984, 985, 986, 987, 988, + 316, 632, 665, 629, 677, 659, 461, 397, 0, 0, + 400, 297, 322, 339, 0, 649, 527, 236, 490, 306, + 265, 1056, 0, 219, 257, 239, 275, 290, 293, 343, + 411, 421, 451, 457, 312, 287, 255, 483, 252, 509, + 548, 549, 550, 552, 415, 282, 456, 0, 0, 395, + 606, 607, 335, 557, 0, 809, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 438, 0, 0, 0, 796, + 0, 0, 0, 286, 801, 0, 0, 0, 385, 283, + 0, 0, 212, 530, 0, 453, 0, 211, 0, 511, + 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, + 450, 547, 444, 808, 389, 0, 0, 522, 422, 0, + 0, 0, 0, 0, 0, 0, 0, 803, 804, 0, + 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, + 210, 435, 523, 302, 0, 101, 0, 0, 1057, 536, + 991, 780, 957, 995, 1058, 1009, 1010, 1011, 996, 0, + 249, 997, 998, 256, 999, 0, 956, 839, 841, 840, + 906, 907, 908, 909, 910, 911, 912, 842, 843, 837, + 1004, 641, 1012, 1013, 0, 281, 340, 288, 280, 612, + 0, 0, 0, 0, 0, 0, 628, 0, 0, 238, + 0, 0, 0, 0, 0, 0, 0, 776, 793, 0, + 807, 0, 0, 0, 0, 291, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, + 0, 0, 0, 790, 791, 0, 0, 0, 0, 951, + 0, 792, 0, 0, 800, 1014, 1015, 1016, 1017, 1018, + 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, + 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, + 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, + 1049, 1050, 1051, 1052, 1053, 1054, 1055, 3255, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 313, 0, + 423, 273, 0, 477, 0, 319, 334, 0, 0, 0, + 0, 0, 0, 0, 950, 0, 0, 661, 0, 0, + 948, 0, 0, 0, 0, 384, 0, 349, 205, 233, + 0, 0, 434, 485, 497, 0, 0, 0, 0, 1001, + 0, 495, 448, 636, 243, 300, 482, 455, 493, 463, + 303, 0, 0, 494, 391, 617, 473, 633, 662, 663, + 279, 428, 647, 551, 655, 680, 234, 276, 442, 535, + 639, 519, 417, 613, 614, 348, 518, 311, 209, 388, + 668, 232, 503, 390, 253, 241, 619, 644, 315, 267, + 305, 480, 675, 221, 546, 630, 250, 507, 0, 0, + 683, 258, 529, 642, 631, 223, 626, 528, 413, 345, + 346, 222, 0, 481, 284, 309, 0, 0, 274, 437, + 1002, 1003, 272, 684, 847, 654, 228, 0, 653, 430, + 616, 627, 414, 402, 227, 625, 412, 401, 353, 855, + 856, 296, 324, 932, 931, 930, 323, 325, 928, 929, + 927, 215, 640, 658, 0, 216, 0, 524, 643, 685, + 475, 220, 244, 245, 248, 0, 295, 299, 307, 310, + 320, 321, 331, 386, 441, 469, 465, 474, 0, 610, + 634, 648, 660, 666, 667, 669, 670, 671, 672, 673, + 676, 674, 429, 329, 520, 352, 392, 0, 0, 447, + 496, 251, 638, 521, 240, 604, 418, 427, 259, 261, + 260, 235, 512, 609, 246, 266, 938, 960, 949, 813, + 814, 939, 940, 964, 941, 816, 817, 961, 962, 810, + 811, 815, 963, 965, 686, 687, 688, 689, 690, 691, + 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, + 702, 703, 681, 537, 543, 538, 539, 540, 541, 542, + 0, 544, 952, 799, 798, 0, 805, 806, 0, 835, + 836, 838, 844, 845, 846, 857, 904, 905, 913, 915, + 916, 914, 917, 918, 919, 922, 923, 924, 925, 920, + 921, 926, 818, 822, 819, 820, 821, 833, 823, 824, + 825, 826, 827, 828, 829, 830, 831, 832, 834, 975, + 976, 977, 978, 979, 980, 850, 854, 853, 851, 852, + 848, 849, 876, 875, 877, 878, 879, 880, 881, 882, + 884, 883, 885, 886, 887, 888, 889, 890, 858, 859, + 862, 863, 861, 860, 864, 873, 874, 865, 866, 867, + 868, 869, 870, 872, 871, 891, 892, 893, 894, 895, + 897, 896, 900, 901, 899, 898, 903, 902, 797, 204, + 229, 387, 0, 478, 304, 682, 650, 508, 645, 214, + 231, 966, 278, 967, 0, 0, 971, 0, 0, 0, + 973, 972, 0, 974, 936, 935, 0, 0, 968, 969, + 0, 970, 0, 0, 206, 208, 217, 230, 242, 247, + 254, 277, 292, 294, 301, 314, 327, 328, 337, 338, + 341, 347, 399, 406, 407, 408, 409, 431, 432, 433, + 436, 439, 440, 443, 445, 446, 449, 454, 458, 459, + 460, 462, 464, 466, 479, 484, 498, 499, 500, 501, + 502, 505, 506, 513, 514, 515, 516, 517, 525, 526, + 531, 532, 533, 534, 545, 618, 620, 637, 657, 664, + 504, 404, 452, 476, 611, 0, 0, 981, 982, 983, + 984, 985, 986, 987, 988, 316, 632, 665, 629, 677, + 659, 461, 397, 0, 0, 400, 297, 322, 339, 0, + 649, 527, 236, 490, 306, 265, 1056, 0, 219, 257, + 239, 275, 290, 293, 343, 411, 421, 451, 457, 312, + 287, 255, 483, 252, 509, 548, 549, 550, 552, 415, + 282, 456, 0, 0, 395, 606, 607, 335, 557, 0, + 809, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 438, 0, 0, 0, 796, 0, 0, 0, 286, 801, 0, 0, 0, 385, 283, 0, 0, 212, 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, - 289, 285, 264, 336, 405, 450, 547, 444, 0, 389, + 289, 285, 264, 336, 405, 450, 547, 444, 808, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 803, 804, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, 0, - 0, 0, 0, 0, 536, 756, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, - 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, - 376, 382, 355, 364, 0, 0, 641, 0, 0, 0, + 101, 0, 0, 1057, 536, 991, 1132, 957, 995, 1058, + 1009, 1010, 1011, 996, 0, 249, 997, 998, 256, 999, + 0, 956, 839, 841, 840, 906, 907, 908, 909, 910, + 911, 912, 842, 843, 837, 1004, 641, 1012, 1013, 0, 281, 340, 288, 280, 612, 0, 0, 0, 0, 0, - 0, 628, 0, 0, 238, 0, 1174, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 628, 0, 0, 238, 0, 0, 0, 0, 0, + 0, 0, 0, 793, 0, 807, 0, 0, 0, 0, 291, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 416, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 416, 0, 0, 0, 790, 791, + 0, 0, 0, 0, 951, 0, 792, 0, 0, 800, + 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, + 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, + 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, + 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, + 1054, 1055, 802, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 313, 0, 423, 273, 0, 477, 0, - 319, 334, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1173, 661, 0, 0, 0, 0, 0, 1170, 1171, - 384, 1139, 349, 205, 233, 1164, 1168, 434, 485, 497, - 0, 0, 0, 0, 269, 0, 495, 448, 636, 243, + 319, 334, 0, 0, 0, 0, 0, 0, 0, 950, + 0, 0, 661, 0, 0, 948, 0, 0, 0, 0, + 384, 0, 349, 205, 233, 0, 0, 434, 485, 497, + 0, 0, 0, 0, 1001, 0, 495, 448, 636, 243, 300, 482, 455, 493, 463, 303, 0, 0, 494, 391, 617, 473, 633, 662, 663, 279, 428, 647, 551, 655, 680, 234, 276, 442, 535, 639, 519, 417, 613, 614, @@ -4770,35 +4670,35 @@ var yyAct = [...]int{ 241, 619, 644, 315, 267, 305, 480, 675, 221, 546, 630, 250, 507, 0, 0, 683, 258, 529, 642, 631, 223, 626, 528, 413, 345, 346, 222, 0, 481, 284, - 309, 0, 0, 274, 437, 621, 622, 272, 684, 237, + 309, 0, 0, 274, 437, 1002, 1003, 272, 684, 847, 654, 228, 0, 653, 430, 616, 627, 414, 402, 227, - 625, 412, 401, 353, 374, 375, 296, 324, 470, 394, - 471, 323, 325, 425, 424, 426, 215, 640, 658, 0, + 625, 412, 401, 353, 855, 856, 296, 324, 932, 931, + 930, 323, 325, 928, 929, 927, 215, 640, 658, 0, 216, 0, 524, 643, 685, 475, 220, 244, 245, 248, 0, 295, 299, 307, 310, 320, 321, 331, 386, 441, 469, 465, 474, 0, 610, 634, 648, 660, 666, 667, 669, 670, 671, 672, 673, 676, 674, 429, 329, 520, 352, 392, 0, 0, 447, 496, 251, 638, 521, 240, 604, 418, 427, 259, 261, 260, 235, 512, 609, 246, - 266, 207, 0, 0, 0, 0, 270, 271, 0, 605, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 686, + 266, 938, 960, 949, 813, 814, 939, 940, 964, 941, + 816, 817, 961, 962, 810, 811, 815, 963, 965, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 681, 537, 543, - 538, 539, 540, 541, 542, 0, 544, 0, 0, 0, - 0, 0, 419, 0, 623, 624, 704, 403, 510, 635, - 354, 368, 371, 360, 380, 0, 381, 356, 357, 362, - 365, 366, 367, 372, 373, 377, 383, 263, 218, 410, - 420, 608, 330, 224, 225, 226, 553, 554, 555, 556, - 651, 652, 656, 213, 486, 487, 488, 489, 308, 646, - 326, 492, 491, 350, 351, 398, 472, 569, 571, 582, - 586, 588, 590, 596, 599, 570, 572, 583, 587, 589, - 591, 597, 600, 559, 561, 563, 565, 578, 577, 574, - 602, 603, 580, 585, 564, 576, 581, 594, 601, 598, - 558, 562, 566, 575, 593, 592, 573, 584, 595, 579, - 567, 560, 568, 0, 204, 229, 387, 0, 478, 304, - 682, 650, 508, 645, 214, 231, 0, 278, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, + 538, 539, 540, 541, 542, 0, 544, 952, 799, 798, + 0, 805, 806, 0, 835, 836, 838, 844, 845, 846, + 857, 904, 905, 913, 915, 916, 914, 917, 918, 919, + 922, 923, 924, 925, 920, 921, 926, 818, 822, 819, + 820, 821, 833, 823, 824, 825, 826, 827, 828, 829, + 830, 831, 832, 834, 975, 976, 977, 978, 979, 980, + 850, 854, 853, 851, 852, 848, 849, 876, 875, 877, + 878, 879, 880, 881, 882, 884, 883, 885, 886, 887, + 888, 889, 890, 858, 859, 862, 863, 861, 860, 864, + 873, 874, 865, 866, 867, 868, 869, 870, 872, 871, + 891, 892, 893, 894, 895, 897, 896, 900, 901, 899, + 898, 903, 902, 797, 204, 229, 387, 0, 478, 304, + 682, 650, 508, 645, 214, 231, 966, 278, 967, 0, + 0, 971, 0, 0, 0, 973, 972, 0, 974, 936, + 935, 0, 0, 968, 969, 0, 970, 0, 0, 206, 208, 217, 230, 242, 247, 254, 277, 292, 294, 301, 314, 327, 328, 337, 338, 341, 347, 399, 406, 407, 408, 409, 431, 432, 433, 436, 439, 440, 443, 445, @@ -4806,40 +4706,118 @@ var yyAct = [...]int{ 484, 498, 499, 500, 501, 502, 505, 506, 513, 514, 515, 516, 517, 525, 526, 531, 532, 533, 534, 545, 618, 620, 637, 657, 664, 504, 404, 452, 476, 611, - 0, 0, 317, 318, 467, 468, 332, 333, 678, 679, + 0, 0, 981, 982, 983, 984, 985, 986, 987, 988, 316, 632, 665, 629, 677, 659, 461, 397, 0, 0, 400, 297, 322, 339, 0, 649, 527, 236, 490, 306, - 265, 0, 0, 219, 257, 239, 275, 290, 293, 343, + 265, 1056, 0, 219, 257, 239, 275, 290, 293, 343, 411, 421, 451, 457, 312, 287, 255, 483, 252, 509, - 548, 549, 550, 552, 415, 282, 456, 91, 557, 395, - 606, 607, 335, 0, 0, 0, 0, 0, 0, 0, - 438, 0, 0, 0, 0, 0, 0, 0, 286, 0, + 548, 549, 550, 552, 415, 282, 456, 0, 0, 395, + 606, 607, 335, 557, 0, 809, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 438, 0, 0, 0, 796, + 0, 0, 0, 286, 801, 0, 0, 0, 385, 283, + 0, 0, 212, 530, 0, 453, 0, 211, 0, 511, + 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, + 450, 547, 444, 808, 389, 0, 0, 522, 422, 0, + 0, 0, 0, 0, 0, 0, 0, 803, 804, 0, + 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, + 210, 435, 523, 302, 0, 101, 0, 0, 1057, 536, + 991, 1132, 957, 995, 1058, 1009, 1010, 1011, 996, 0, + 249, 997, 998, 256, 999, 0, 956, 839, 841, 840, + 906, 907, 908, 909, 910, 911, 912, 842, 843, 837, + 1004, 641, 1012, 1013, 0, 281, 340, 288, 280, 612, + 0, 0, 0, 0, 0, 0, 628, 0, 0, 238, + 0, 0, 0, 0, 0, 0, 0, 0, 793, 0, + 807, 0, 0, 0, 0, 291, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, + 0, 0, 0, 790, 791, 0, 0, 0, 0, 951, + 0, 792, 0, 0, 800, 1014, 1015, 1016, 1017, 1018, + 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, + 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, + 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, + 1049, 1050, 1051, 1052, 1053, 1054, 1055, 2188, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 313, 0, + 423, 273, 0, 477, 0, 319, 334, 0, 0, 0, + 0, 0, 0, 0, 950, 0, 0, 661, 0, 0, + 948, 0, 0, 0, 0, 384, 0, 349, 205, 233, + 0, 0, 434, 485, 497, 0, 0, 0, 0, 1001, + 0, 495, 448, 636, 243, 300, 482, 455, 493, 463, + 303, 0, 0, 494, 391, 617, 473, 633, 662, 663, + 279, 428, 647, 551, 655, 680, 234, 276, 442, 535, + 639, 519, 417, 613, 614, 348, 518, 311, 209, 388, + 668, 232, 503, 390, 253, 241, 619, 644, 315, 267, + 305, 480, 675, 221, 546, 630, 250, 507, 0, 0, + 683, 258, 529, 642, 631, 223, 626, 528, 413, 345, + 346, 222, 0, 481, 284, 309, 0, 0, 274, 437, + 1002, 1003, 272, 684, 847, 654, 228, 0, 653, 430, + 616, 627, 414, 402, 227, 625, 412, 401, 353, 855, + 856, 296, 324, 932, 931, 930, 323, 325, 928, 929, + 927, 215, 640, 658, 0, 216, 0, 524, 643, 685, + 475, 220, 244, 245, 248, 0, 295, 299, 307, 310, + 320, 321, 331, 386, 441, 469, 465, 474, 0, 610, + 634, 648, 660, 666, 667, 669, 670, 671, 672, 673, + 676, 674, 429, 329, 520, 352, 392, 0, 0, 447, + 496, 251, 638, 521, 240, 604, 418, 427, 259, 261, + 260, 235, 512, 609, 246, 266, 938, 960, 949, 813, + 814, 939, 940, 964, 941, 816, 817, 961, 962, 810, + 811, 815, 963, 965, 686, 687, 688, 689, 690, 691, + 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, + 702, 703, 681, 537, 543, 538, 539, 540, 541, 542, + 0, 544, 952, 799, 798, 0, 805, 806, 0, 835, + 836, 838, 844, 845, 846, 857, 904, 905, 913, 915, + 916, 914, 917, 918, 919, 922, 923, 924, 925, 920, + 921, 926, 818, 822, 819, 820, 821, 833, 823, 824, + 825, 826, 827, 828, 829, 830, 831, 832, 834, 975, + 976, 977, 978, 979, 980, 850, 854, 853, 851, 852, + 848, 849, 876, 875, 877, 878, 879, 880, 881, 882, + 884, 883, 885, 886, 887, 888, 889, 890, 858, 859, + 862, 863, 861, 860, 864, 873, 874, 865, 866, 867, + 868, 869, 870, 872, 871, 891, 892, 893, 894, 895, + 897, 896, 900, 901, 899, 898, 903, 902, 797, 204, + 229, 387, 0, 478, 304, 682, 650, 508, 645, 214, + 231, 966, 278, 967, 0, 0, 971, 0, 0, 0, + 973, 972, 0, 974, 936, 935, 0, 0, 968, 969, + 0, 970, 0, 0, 206, 208, 217, 230, 242, 247, + 254, 277, 292, 294, 301, 314, 327, 328, 337, 338, + 341, 347, 399, 406, 407, 408, 409, 431, 432, 433, + 436, 439, 440, 443, 445, 446, 449, 454, 458, 459, + 460, 462, 464, 466, 479, 484, 498, 499, 500, 501, + 502, 505, 506, 513, 514, 515, 516, 517, 525, 526, + 531, 532, 533, 534, 545, 618, 620, 637, 657, 664, + 504, 404, 452, 476, 611, 0, 0, 981, 982, 983, + 984, 985, 986, 987, 988, 316, 632, 665, 629, 677, + 659, 461, 397, 0, 0, 400, 297, 322, 339, 0, + 649, 527, 236, 490, 306, 265, 1056, 0, 219, 257, + 239, 275, 290, 293, 343, 411, 421, 451, 457, 312, + 287, 255, 483, 252, 509, 548, 549, 550, 552, 415, + 282, 456, 0, 0, 395, 606, 607, 335, 557, 0, + 809, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 438, 0, 0, 0, 796, 0, 0, 0, 286, 801, 0, 0, 0, 385, 283, 0, 0, 212, 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, - 289, 285, 264, 336, 405, 450, 547, 444, 103, 389, + 289, 285, 264, 336, 405, 450, 547, 444, 808, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 803, 804, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, 0, - 101, 0, 0, 0, 536, 202, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, - 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, - 376, 382, 355, 364, 0, 0, 641, 0, 0, 0, + 101, 0, 0, 1057, 536, 991, 1132, 957, 995, 1058, + 1009, 1010, 1011, 996, 0, 249, 997, 998, 256, 999, + 0, 956, 839, 841, 840, 906, 907, 908, 909, 910, + 911, 912, 842, 843, 837, 1004, 641, 1012, 1013, 0, 281, 340, 288, 280, 612, 0, 0, 0, 0, 0, 0, 628, 0, 0, 238, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 793, 0, 807, 0, 0, 0, 0, 291, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 416, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 416, 0, 0, 0, 790, 791, + 0, 0, 0, 0, 951, 0, 792, 0, 0, 800, + 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, + 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, + 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, + 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, + 1054, 1055, 2186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 313, 0, 423, 273, 0, 477, 0, - 319, 334, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 661, 0, 0, 0, 0, 0, 0, 0, + 319, 334, 0, 0, 0, 0, 0, 0, 0, 950, + 0, 0, 661, 0, 0, 948, 0, 0, 0, 0, 384, 0, 349, 205, 233, 0, 0, 434, 485, 497, - 0, 0, 0, 0, 269, 0, 495, 448, 636, 243, + 0, 0, 0, 0, 1001, 0, 495, 448, 636, 243, 300, 482, 455, 493, 463, 303, 0, 0, 494, 391, 617, 473, 633, 662, 663, 279, 428, 647, 551, 655, 680, 234, 276, 442, 535, 639, 519, 417, 613, 614, @@ -4847,35 +4825,35 @@ var yyAct = [...]int{ 241, 619, 644, 315, 267, 305, 480, 675, 221, 546, 630, 250, 507, 0, 0, 683, 258, 529, 642, 631, 223, 626, 528, 413, 345, 346, 222, 0, 481, 284, - 309, 0, 0, 274, 437, 621, 622, 272, 684, 237, + 309, 0, 0, 274, 437, 1002, 1003, 272, 684, 847, 654, 228, 0, 653, 430, 616, 627, 414, 402, 227, - 625, 412, 401, 353, 374, 375, 296, 324, 470, 394, - 471, 323, 325, 425, 424, 426, 215, 640, 658, 0, + 625, 412, 401, 353, 855, 856, 296, 324, 932, 931, + 930, 323, 325, 928, 929, 927, 215, 640, 658, 0, 216, 0, 524, 643, 685, 475, 220, 244, 245, 248, 0, 295, 299, 307, 310, 320, 321, 331, 386, 441, 469, 465, 474, 0, 610, 634, 648, 660, 666, 667, 669, 670, 671, 672, 673, 676, 674, 429, 329, 520, 352, 392, 0, 0, 447, 496, 251, 638, 521, 240, 604, 418, 427, 259, 261, 260, 235, 512, 609, 246, - 266, 207, 0, 0, 0, 0, 270, 271, 0, 605, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 686, + 266, 938, 960, 949, 813, 814, 939, 940, 964, 941, + 816, 817, 961, 962, 810, 811, 815, 963, 965, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 681, 537, 543, - 538, 539, 540, 541, 542, 0, 544, 0, 0, 0, - 0, 0, 419, 0, 623, 624, 704, 403, 510, 635, - 354, 368, 371, 360, 380, 0, 381, 356, 357, 362, - 365, 366, 367, 372, 373, 377, 383, 263, 218, 410, - 420, 608, 330, 224, 225, 226, 553, 554, 555, 556, - 651, 652, 656, 213, 486, 487, 488, 489, 308, 646, - 326, 492, 491, 350, 351, 398, 472, 569, 571, 582, - 586, 588, 590, 596, 599, 570, 572, 583, 587, 589, - 591, 597, 600, 559, 561, 563, 565, 578, 577, 574, - 602, 603, 580, 585, 564, 576, 581, 594, 601, 598, - 558, 562, 566, 575, 593, 592, 573, 584, 595, 579, - 567, 560, 568, 0, 204, 229, 387, 100, 478, 304, - 682, 650, 508, 645, 214, 231, 0, 278, 0, 0, - 0, 0, 0, 0, 2502, 0, 0, 2501, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, + 538, 539, 540, 541, 542, 0, 544, 952, 799, 798, + 0, 805, 806, 0, 835, 836, 838, 844, 845, 846, + 857, 904, 905, 913, 915, 916, 914, 917, 918, 919, + 922, 923, 924, 925, 920, 921, 926, 818, 822, 819, + 820, 821, 833, 823, 824, 825, 826, 827, 828, 829, + 830, 831, 832, 834, 975, 976, 977, 978, 979, 980, + 850, 854, 853, 851, 852, 848, 849, 876, 875, 877, + 878, 879, 880, 881, 882, 884, 883, 885, 886, 887, + 888, 889, 890, 858, 859, 862, 863, 861, 860, 864, + 873, 874, 865, 866, 867, 868, 869, 870, 872, 871, + 891, 892, 893, 894, 895, 897, 896, 900, 901, 899, + 898, 903, 902, 797, 204, 229, 387, 0, 478, 304, + 682, 650, 508, 645, 214, 231, 966, 278, 967, 0, + 0, 971, 0, 0, 0, 973, 972, 0, 974, 936, + 935, 0, 0, 968, 969, 0, 970, 0, 0, 206, 208, 217, 230, 242, 247, 254, 277, 292, 294, 301, 314, 327, 328, 337, 338, 341, 347, 399, 406, 407, 408, 409, 431, 432, 433, 436, 439, 440, 443, 445, @@ -4883,10 +4861,10 @@ var yyAct = [...]int{ 484, 498, 499, 500, 501, 502, 505, 506, 513, 514, 515, 516, 517, 525, 526, 531, 532, 533, 534, 545, 618, 620, 637, 657, 664, 504, 404, 452, 476, 611, - 0, 0, 317, 318, 467, 468, 332, 333, 678, 679, + 0, 0, 981, 982, 983, 984, 985, 986, 987, 988, 316, 632, 665, 629, 677, 659, 461, 397, 0, 0, 400, 297, 322, 339, 0, 649, 527, 236, 490, 306, - 265, 0, 0, 219, 257, 239, 275, 290, 293, 343, + 265, 1056, 0, 219, 257, 239, 275, 290, 293, 343, 411, 421, 451, 457, 312, 287, 255, 483, 252, 509, 548, 549, 550, 552, 415, 282, 456, 557, 0, 395, 606, 607, 335, 0, 0, 0, 0, 0, 0, 438, @@ -4897,13 +4875,13 @@ var yyAct = [...]int{ 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, 0, 0, - 0, 0, 0, 536, 756, 0, 0, 0, 0, 4390, + 0, 0, 0, 536, 756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, 0, 0, 281, 340, 288, 280, 612, 0, 0, 0, 0, 0, 0, - 628, 0, 0, 238, 0, 0, 0, 0, 0, 0, - 0, 4388, 0, 0, 0, 0, 0, 0, 0, 291, + 628, 0, 0, 238, 0, 1175, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -4913,9 +4891,9 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 313, 0, 423, 273, 0, 477, 0, 319, - 334, 0, 0, 0, 4389, 4257, 4387, 0, 0, 0, - 0, 661, 0, 0, 0, 0, 0, 0, 0, 384, - 0, 349, 205, 233, 0, 0, 434, 485, 497, 0, + 334, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1174, 661, 0, 0, 0, 0, 0, 1171, 1172, 384, + 1140, 349, 205, 233, 1165, 1169, 434, 485, 497, 0, 0, 0, 0, 269, 0, 495, 448, 636, 243, 300, 482, 455, 493, 463, 303, 0, 0, 494, 391, 617, 473, 633, 662, 663, 279, 428, 647, 551, 655, 680, @@ -4974,7 +4952,7 @@ var yyAct = [...]int{ 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, 0, 101, - 0, 1804, 0, 536, 756, 0, 0, 0, 0, 0, + 0, 0, 0, 536, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, 0, 0, 281, @@ -5028,7 +5006,7 @@ var yyAct = [...]int{ 562, 566, 575, 593, 592, 573, 584, 595, 579, 567, 560, 568, 0, 204, 229, 387, 100, 478, 304, 682, 650, 508, 645, 214, 231, 0, 278, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2508, 0, 0, 2507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 208, 217, 230, 242, 247, 254, 277, 292, 294, 301, 314, 327, 328, 337, 338, 341, 347, 399, 406, 407, 408, @@ -5044,22 +5022,99 @@ var yyAct = [...]int{ 421, 451, 457, 312, 287, 255, 483, 252, 509, 548, 549, 550, 552, 415, 282, 456, 557, 0, 395, 606, 607, 335, 0, 0, 0, 0, 0, 0, 438, 0, - 0, 1846, 0, 0, 0, 0, 286, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 286, 0, 0, 0, 0, 385, 283, 0, 0, 212, 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, 450, 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, 0, 0, 0, - 0, 1848, 536, 756, 0, 0, 0, 0, 0, 0, + 0, 0, 536, 756, 0, 0, 0, 0, 4398, 0, + 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, + 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, + 355, 364, 0, 0, 641, 0, 0, 0, 281, 340, + 288, 280, 612, 0, 0, 0, 0, 0, 0, 628, + 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, + 4396, 0, 0, 0, 0, 0, 0, 0, 291, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 313, 0, 423, 273, 0, 477, 0, 319, 334, + 0, 0, 0, 4397, 4265, 4395, 0, 0, 0, 0, + 661, 0, 0, 0, 0, 0, 0, 0, 384, 0, + 349, 205, 233, 0, 0, 434, 485, 497, 0, 0, + 0, 0, 269, 0, 495, 448, 636, 243, 300, 482, + 455, 493, 463, 303, 0, 0, 494, 391, 617, 473, + 633, 662, 663, 279, 428, 647, 551, 655, 680, 234, + 276, 442, 535, 639, 519, 417, 613, 614, 348, 518, + 311, 209, 388, 668, 232, 503, 390, 253, 241, 619, + 644, 315, 267, 305, 480, 675, 221, 546, 630, 250, + 507, 0, 0, 683, 258, 529, 642, 631, 223, 626, + 528, 413, 345, 346, 222, 0, 481, 284, 309, 0, + 0, 274, 437, 621, 622, 272, 684, 237, 654, 228, + 0, 653, 430, 616, 627, 414, 402, 227, 625, 412, + 401, 353, 374, 375, 296, 324, 470, 394, 471, 323, + 325, 425, 424, 426, 215, 640, 658, 0, 216, 0, + 524, 643, 685, 475, 220, 244, 245, 248, 0, 295, + 299, 307, 310, 320, 321, 331, 386, 441, 469, 465, + 474, 0, 610, 634, 648, 660, 666, 667, 669, 670, + 671, 672, 673, 676, 674, 429, 329, 520, 352, 392, + 0, 0, 447, 496, 251, 638, 521, 240, 604, 418, + 427, 259, 261, 260, 235, 512, 609, 246, 266, 207, + 0, 0, 0, 0, 270, 271, 0, 605, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 686, 687, 688, + 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, + 699, 700, 701, 702, 703, 681, 537, 543, 538, 539, + 540, 541, 542, 0, 544, 0, 0, 0, 0, 0, + 419, 0, 623, 624, 704, 403, 510, 635, 354, 368, + 371, 360, 380, 0, 381, 356, 357, 362, 365, 366, + 367, 372, 373, 377, 383, 263, 218, 410, 420, 608, + 330, 224, 225, 226, 553, 554, 555, 556, 651, 652, + 656, 213, 486, 487, 488, 489, 308, 646, 326, 492, + 491, 350, 351, 398, 472, 569, 571, 582, 586, 588, + 590, 596, 599, 570, 572, 583, 587, 589, 591, 597, + 600, 559, 561, 563, 565, 578, 577, 574, 602, 603, + 580, 585, 564, 576, 581, 594, 601, 598, 558, 562, + 566, 575, 593, 592, 573, 584, 595, 579, 567, 560, + 568, 0, 204, 229, 387, 0, 478, 304, 682, 650, + 508, 645, 214, 231, 0, 278, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 206, 208, 217, + 230, 242, 247, 254, 277, 292, 294, 301, 314, 327, + 328, 337, 338, 341, 347, 399, 406, 407, 408, 409, + 431, 432, 433, 436, 439, 440, 443, 445, 446, 449, + 454, 458, 459, 460, 462, 464, 466, 479, 484, 498, + 499, 500, 501, 502, 505, 506, 513, 514, 515, 516, + 517, 525, 526, 531, 532, 533, 534, 545, 618, 620, + 637, 657, 664, 504, 404, 452, 476, 611, 0, 0, + 317, 318, 467, 468, 332, 333, 678, 679, 316, 632, + 665, 629, 677, 659, 461, 397, 0, 0, 400, 297, + 322, 339, 0, 649, 527, 236, 490, 306, 265, 0, + 0, 219, 257, 239, 275, 290, 293, 343, 411, 421, + 451, 457, 312, 287, 255, 483, 252, 509, 548, 549, + 550, 552, 415, 282, 456, 91, 557, 395, 606, 607, + 335, 0, 0, 0, 0, 0, 0, 0, 438, 0, + 0, 0, 0, 0, 0, 0, 286, 0, 0, 0, + 0, 385, 283, 0, 0, 212, 530, 0, 453, 0, + 211, 0, 511, 268, 396, 393, 615, 298, 289, 285, + 264, 336, 405, 450, 547, 444, 103, 389, 0, 0, + 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 342, 262, 344, 210, 435, 523, 302, 0, 101, 0, + 1805, 0, 536, 756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, 0, 0, 281, 340, 288, 280, 612, 0, 0, 0, 0, 0, 0, 628, - 0, 0, 238, 0, 0, 0, 1529, 0, 1530, 1531, + 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1844, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5103,7 +5158,7 @@ var yyAct = [...]int{ 600, 559, 561, 563, 565, 578, 577, 574, 602, 603, 580, 585, 564, 576, 581, 594, 601, 598, 558, 562, 566, 575, 593, 592, 573, 584, 595, 579, 567, 560, - 568, 0, 204, 229, 387, 0, 478, 304, 682, 650, + 568, 0, 204, 229, 387, 100, 478, 304, 682, 650, 508, 645, 214, 231, 0, 278, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 208, 217, @@ -5121,30 +5176,30 @@ var yyAct = [...]int{ 451, 457, 312, 287, 255, 483, 252, 509, 548, 549, 550, 552, 415, 282, 456, 557, 0, 395, 606, 607, 335, 0, 0, 0, 0, 0, 0, 438, 0, 0, - 0, 0, 0, 0, 0, 286, 0, 0, 0, 0, + 1848, 0, 0, 0, 0, 286, 0, 0, 0, 0, 385, 283, 0, 0, 212, 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, 450, 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, 0, 0, 0, 0, - 0, 536, 756, 0, 0, 0, 0, 0, 0, 0, + 1850, 536, 756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, 0, 0, 281, 340, 288, 280, 612, 0, 0, 0, 0, 0, 0, 628, 0, - 0, 238, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 1530, 0, 1531, 1532, 0, 0, 0, 0, 0, 0, 0, 0, 291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1846, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 313, 0, 423, 273, 0, 477, 0, 319, 334, 4251, - 4252, 4253, 0, 0, 0, 0, 0, 0, 0, 661, + 313, 0, 423, 273, 0, 477, 0, 319, 334, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 661, 0, 0, 0, 0, 0, 0, 0, 384, 0, 349, 205, 233, 0, 0, 434, 485, 497, 0, 0, 0, 0, 269, 0, 495, 448, 636, 243, 300, 482, 455, @@ -5204,8 +5259,8 @@ var yyAct = [...]int{ 405, 450, 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, - 344, 210, 435, 523, 302, 0, 101, 0, 0, 0, - 536, 202, 0, 0, 0, 0, 0, 0, 0, 0, + 344, 210, 435, 523, 302, 0, 0, 0, 0, 0, + 536, 756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, 0, 0, 281, 340, 288, 280, @@ -5220,8 +5275,8 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 313, - 0, 423, 273, 0, 477, 0, 319, 334, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 661, 0, + 0, 423, 273, 0, 477, 0, 319, 334, 4259, 4260, + 4261, 0, 0, 0, 0, 0, 0, 0, 661, 0, 0, 0, 0, 0, 0, 0, 384, 0, 349, 205, 233, 0, 0, 434, 485, 497, 0, 0, 0, 0, 269, 0, 495, 448, 636, 243, 300, 482, 455, 493, @@ -5259,7 +5314,7 @@ var yyAct = [...]int{ 593, 592, 573, 584, 595, 579, 567, 560, 568, 0, 204, 229, 387, 0, 478, 304, 682, 650, 508, 645, 214, 231, 0, 278, 0, 0, 0, 0, 0, 0, - 2502, 0, 0, 2501, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 208, 217, 230, 242, 247, 254, 277, 292, 294, 301, 314, 327, 328, 337, 338, 341, 347, 399, 406, 407, 408, 409, 431, 432, @@ -5274,14 +5329,14 @@ var yyAct = [...]int{ 257, 239, 275, 290, 293, 343, 411, 421, 451, 457, 312, 287, 255, 483, 252, 509, 548, 549, 550, 552, 415, 282, 456, 557, 0, 395, 606, 607, 335, 0, - 0, 0, 0, 0, 0, 438, 0, 0, 2434, 0, + 0, 0, 0, 0, 0, 438, 0, 0, 0, 0, 0, 0, 0, 286, 0, 0, 0, 0, 385, 283, 0, 0, 212, 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, 450, 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, - 210, 435, 523, 302, 0, 0, 0, 0, 2023, 536, + 210, 435, 523, 302, 0, 101, 0, 0, 0, 536, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, @@ -5302,7 +5357,7 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 384, 0, 349, 205, 233, 0, 0, 434, 485, 497, 0, 0, 0, 0, 269, 0, 495, 448, 636, 243, 300, 482, 455, 493, 463, - 303, 0, 2432, 494, 391, 617, 473, 633, 662, 663, + 303, 0, 0, 494, 391, 617, 473, 633, 662, 663, 279, 428, 647, 551, 655, 680, 234, 276, 442, 535, 639, 519, 417, 613, 614, 348, 518, 311, 209, 388, 668, 232, 503, 390, 253, 241, 619, 644, 315, 267, @@ -5335,8 +5390,8 @@ var yyAct = [...]int{ 576, 581, 594, 601, 598, 558, 562, 566, 575, 593, 592, 573, 584, 595, 579, 567, 560, 568, 0, 204, 229, 387, 0, 478, 304, 682, 650, 508, 645, 214, - 231, 0, 278, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 231, 0, 278, 0, 0, 0, 0, 0, 0, 2508, + 0, 0, 2507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 208, 217, 230, 242, 247, 254, 277, 292, 294, 301, 314, 327, 328, 337, 338, 341, 347, 399, 406, 407, 408, 409, 431, 432, 433, @@ -5351,14 +5406,14 @@ var yyAct = [...]int{ 239, 275, 290, 293, 343, 411, 421, 451, 457, 312, 287, 255, 483, 252, 509, 548, 549, 550, 552, 415, 282, 456, 557, 0, 395, 606, 607, 335, 0, 0, - 0, 0, 0, 0, 438, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 438, 0, 0, 2437, 0, 0, 0, 0, 286, 0, 0, 0, 0, 385, 283, 0, 0, 212, 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, 450, 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, - 435, 523, 302, 0, 0, 0, 0, 0, 536, 756, + 435, 523, 302, 0, 0, 0, 0, 2026, 536, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, @@ -5366,7 +5421,7 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 628, 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 291, 0, 0, 0, 0, 0, - 0, 0, 0, 1133, 0, 0, 0, 0, 416, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5376,10 +5431,10 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 313, 0, 423, 273, 0, 477, 0, 319, 334, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 661, 0, 0, 0, - 0, 0, 0, 0, 384, 1139, 349, 205, 233, 1137, + 0, 0, 0, 0, 384, 0, 349, 205, 233, 0, 0, 434, 485, 497, 0, 0, 0, 0, 269, 0, 495, 448, 636, 243, 300, 482, 455, 493, 463, 303, - 0, 0, 494, 391, 617, 473, 633, 662, 663, 279, + 0, 2435, 494, 391, 617, 473, 633, 662, 663, 279, 428, 647, 551, 655, 680, 234, 276, 442, 535, 639, 519, 417, 613, 614, 348, 518, 311, 209, 388, 668, 232, 503, 390, 253, 241, 619, 644, 315, 267, 305, @@ -5428,14 +5483,14 @@ var yyAct = [...]int{ 275, 290, 293, 343, 411, 421, 451, 457, 312, 287, 255, 483, 252, 509, 548, 549, 550, 552, 415, 282, 456, 557, 0, 395, 606, 607, 335, 0, 0, 0, - 0, 0, 0, 438, 0, 0, 2434, 0, 0, 0, + 0, 0, 0, 438, 0, 0, 0, 0, 0, 0, 0, 286, 0, 0, 0, 0, 385, 283, 0, 0, 212, 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, 450, 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, - 523, 302, 0, 0, 0, 0, 2023, 536, 202, 0, + 523, 302, 0, 0, 0, 0, 0, 536, 756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, @@ -5443,7 +5498,7 @@ var yyAct = [...]int{ 0, 0, 0, 0, 628, 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 291, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, + 0, 0, 1134, 0, 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5453,7 +5508,7 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 313, 0, 423, 273, 0, 477, 0, 319, 334, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 661, 0, 0, 0, 0, - 0, 0, 0, 384, 0, 349, 205, 233, 0, 0, + 0, 0, 0, 384, 1140, 349, 205, 233, 1138, 0, 434, 485, 497, 0, 0, 0, 0, 269, 0, 495, 448, 636, 243, 300, 482, 455, 493, 463, 303, 0, 0, 494, 391, 617, 473, 633, 662, 663, 279, 428, @@ -5505,14 +5560,14 @@ var yyAct = [...]int{ 290, 293, 343, 411, 421, 451, 457, 312, 287, 255, 483, 252, 509, 548, 549, 550, 552, 415, 282, 456, 557, 0, 395, 606, 607, 335, 0, 0, 0, 0, - 0, 0, 438, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 438, 0, 0, 2437, 0, 0, 0, 0, 286, 0, 0, 0, 0, 385, 283, 0, 0, 212, 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, 450, 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, 523, - 302, 0, 0, 0, 1804, 0, 536, 756, 0, 0, + 302, 0, 0, 0, 0, 2026, 536, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, @@ -5529,7 +5584,7 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 313, 0, 423, 273, 0, 477, 0, 319, 334, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 661, 0, 0, 0, 3817, 0, + 0, 0, 0, 0, 661, 0, 0, 0, 0, 0, 0, 0, 384, 0, 349, 205, 233, 0, 0, 434, 485, 497, 0, 0, 0, 0, 269, 0, 495, 448, 636, 243, 300, 482, 455, 493, 463, 303, 0, 0, @@ -5589,7 +5644,7 @@ var yyAct = [...]int{ 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, - 0, 0, 0, 0, 2194, 536, 756, 0, 0, 0, + 0, 0, 0, 1805, 0, 536, 756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, 0, @@ -5599,14 +5654,14 @@ var yyAct = [...]int{ 0, 291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2195, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 313, 0, 423, 273, 0, 477, 0, 319, 334, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 661, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 661, 0, 0, 0, 3825, 0, 0, 0, 384, 0, 349, 205, 233, 0, 0, 434, 485, 497, 0, 0, 0, 0, 269, 0, 495, 448, 636, 243, 300, 482, 455, 493, 463, 303, 0, 0, 494, @@ -5666,7 +5721,7 @@ var yyAct = [...]int{ 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, 0, - 0, 0, 0, 2968, 536, 756, 0, 0, 0, 0, + 0, 0, 0, 2197, 536, 756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, 0, 0, @@ -5675,7 +5730,7 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 2969, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5743,8 +5798,8 @@ var yyAct = [...]int{ 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, 0, 0, - 0, 0, 0, 536, 756, 0, 0, 0, 0, 2935, - 0, 0, 0, 0, 249, 0, 0, 256, 2936, 0, + 0, 0, 2974, 536, 756, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, 0, 0, 281, 340, 288, 280, 612, 0, 0, 0, 0, 0, 0, @@ -5752,7 +5807,7 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2975, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5813,15 +5868,15 @@ var yyAct = [...]int{ 421, 451, 457, 312, 287, 255, 483, 252, 509, 548, 549, 550, 552, 415, 282, 456, 557, 0, 395, 606, 607, 335, 0, 0, 0, 0, 0, 0, 438, 0, - 0, 0, 0, 0, 0, 0, 286, 1867, 0, 0, + 0, 0, 0, 0, 0, 0, 286, 0, 0, 0, 0, 385, 283, 0, 0, 212, 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, 450, 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, 0, 0, 0, - 0, 1866, 536, 756, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, + 0, 0, 536, 756, 0, 0, 0, 0, 2941, 0, + 0, 0, 0, 249, 0, 0, 256, 2942, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, 0, 0, 281, 340, 288, 280, 612, 0, 0, 0, 0, 0, 0, 628, @@ -5890,14 +5945,14 @@ var yyAct = [...]int{ 451, 457, 312, 287, 255, 483, 252, 509, 548, 549, 550, 552, 415, 282, 456, 557, 0, 395, 606, 607, 335, 0, 0, 0, 0, 0, 0, 438, 0, 0, - 0, 0, 0, 0, 0, 286, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 286, 1870, 0, 0, 0, 385, 283, 0, 0, 212, 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, 450, 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, 0, 0, 0, 0, - 0, 536, 758, 759, 760, 0, 0, 0, 0, 0, + 1869, 536, 756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, 0, 0, 281, 340, 288, @@ -5974,7 +6029,7 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, 0, 0, 0, 0, 0, - 536, 756, 0, 0, 0, 0, 0, 0, 0, 0, + 536, 758, 759, 760, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, 0, 0, 281, 340, 288, 280, @@ -5990,7 +6045,7 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 313, 0, 423, 273, 0, 477, 0, 319, 334, 0, 0, - 0, 0, 4257, 0, 0, 0, 0, 0, 661, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 661, 0, 0, 0, 0, 0, 0, 0, 384, 0, 349, 205, 233, 0, 0, 434, 485, 497, 0, 0, 0, 0, 269, 0, 495, 448, 636, 243, 300, 482, 455, 493, @@ -6067,8 +6122,8 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 313, 0, 423, 273, 0, 477, 0, 319, 334, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 661, 0, 0, - 0, 4173, 0, 0, 0, 384, 0, 349, 205, 233, + 0, 4265, 0, 0, 0, 0, 0, 661, 0, 0, + 0, 0, 0, 0, 0, 384, 0, 349, 205, 233, 0, 0, 434, 485, 497, 0, 0, 0, 0, 269, 0, 495, 448, 636, 243, 300, 482, 455, 493, 463, 303, 0, 0, 494, 391, 617, 473, 633, 662, 663, @@ -6127,7 +6182,7 @@ var yyAct = [...]int{ 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, - 435, 523, 302, 0, 0, 0, 0, 2023, 536, 202, + 435, 523, 302, 0, 0, 0, 0, 0, 536, 756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, @@ -6145,7 +6200,7 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 313, 0, 423, 273, 0, 477, 0, 319, 334, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 661, 0, 0, 0, - 0, 0, 0, 0, 384, 0, 349, 205, 233, 0, + 4181, 0, 0, 0, 384, 0, 349, 205, 233, 0, 0, 434, 485, 497, 0, 0, 0, 0, 269, 0, 495, 448, 636, 243, 300, 482, 455, 493, 463, 303, 0, 0, 494, 391, 617, 473, 633, 662, 663, 279, @@ -6204,7 +6259,7 @@ var yyAct = [...]int{ 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, - 523, 302, 0, 0, 0, 0, 0, 536, 756, 0, + 523, 302, 0, 0, 0, 0, 2026, 536, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, @@ -6221,7 +6276,7 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 313, 0, 423, 273, 0, 477, 0, 319, 334, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 661, 0, 0, 0, 3817, + 0, 0, 0, 0, 0, 661, 0, 0, 0, 0, 0, 0, 0, 384, 0, 349, 205, 233, 0, 0, 434, 485, 497, 0, 0, 0, 0, 269, 0, 495, 448, 636, 243, 300, 482, 455, 493, 463, 303, 0, @@ -6281,7 +6336,7 @@ var yyAct = [...]int{ 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, 523, - 302, 0, 101, 0, 0, 0, 536, 756, 0, 0, + 302, 0, 0, 0, 0, 0, 536, 756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, @@ -6298,7 +6353,7 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 313, 0, 423, 273, 0, 477, 0, 319, 334, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 661, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 661, 0, 0, 0, 3825, 0, 0, 0, 384, 0, 349, 205, 233, 0, 0, 434, 485, 497, 0, 0, 0, 0, 269, 0, 495, 448, 636, 243, 300, 482, 455, 493, 463, 303, 0, 0, @@ -6349,85 +6404,85 @@ var yyAct = [...]int{ 0, 0, 400, 297, 322, 339, 0, 649, 527, 236, 490, 306, 265, 0, 0, 219, 257, 239, 275, 290, 293, 343, 411, 421, 451, 457, 312, 287, 255, 483, - 252, 509, 548, 549, 550, 552, 415, 282, 456, 0, - 557, 395, 606, 607, 335, 2503, 0, 0, 0, 0, - 0, 0, 438, 0, 0, 0, 0, 0, 0, 0, - 286, 0, 0, 0, 0, 385, 283, 0, 0, 212, - 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, - 615, 298, 289, 285, 264, 336, 405, 450, 547, 444, - 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, + 252, 509, 548, 549, 550, 552, 415, 282, 456, 557, + 0, 395, 606, 607, 335, 0, 0, 0, 0, 0, + 0, 438, 0, 0, 0, 0, 0, 0, 0, 286, + 0, 0, 0, 0, 385, 283, 0, 0, 212, 530, + 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, + 298, 289, 285, 264, 336, 405, 450, 547, 444, 0, + 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 342, 262, 344, 210, 435, 523, - 302, 0, 0, 0, 0, 0, 536, 202, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, - 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, - 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, - 0, 0, 281, 340, 288, 280, 612, 0, 0, 0, - 0, 0, 0, 628, 0, 0, 238, 0, 0, 0, + 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, + 0, 101, 0, 0, 0, 536, 756, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, + 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, + 369, 376, 382, 355, 364, 0, 0, 641, 0, 0, + 0, 281, 340, 288, 280, 612, 0, 0, 0, 0, + 0, 0, 628, 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 291, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 416, 0, 0, 0, + 0, 291, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 313, 0, 423, 273, 0, - 477, 0, 319, 334, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 661, 0, 0, 0, 0, 0, - 0, 0, 384, 0, 349, 205, 233, 0, 0, 434, - 485, 497, 0, 0, 0, 0, 269, 0, 495, 448, - 636, 243, 300, 482, 455, 493, 463, 303, 0, 0, - 494, 391, 617, 473, 633, 662, 663, 279, 428, 647, - 551, 655, 680, 234, 276, 442, 535, 639, 519, 417, - 613, 614, 348, 518, 311, 209, 388, 668, 232, 503, - 390, 253, 241, 619, 644, 315, 267, 305, 480, 675, - 221, 546, 630, 250, 507, 0, 0, 683, 258, 529, - 642, 631, 223, 626, 528, 413, 345, 346, 222, 0, - 481, 284, 309, 0, 0, 274, 437, 621, 622, 272, - 684, 237, 654, 228, 0, 653, 430, 616, 627, 414, - 402, 227, 625, 412, 401, 353, 374, 375, 296, 324, - 470, 394, 471, 323, 325, 425, 424, 426, 215, 640, - 658, 0, 216, 0, 524, 643, 685, 475, 220, 244, - 245, 248, 0, 295, 299, 307, 310, 320, 321, 331, - 386, 441, 469, 465, 474, 0, 610, 634, 648, 660, - 666, 667, 669, 670, 671, 672, 673, 676, 674, 429, - 329, 520, 352, 392, 0, 0, 447, 496, 251, 638, - 521, 240, 604, 418, 427, 259, 261, 260, 235, 512, - 609, 246, 266, 207, 0, 0, 0, 0, 270, 271, - 0, 605, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 686, 687, 688, 689, 690, 691, 692, 693, 694, - 695, 696, 697, 698, 699, 700, 701, 702, 703, 681, - 537, 543, 538, 539, 540, 541, 542, 0, 544, 0, - 0, 0, 0, 0, 419, 0, 623, 624, 704, 403, - 510, 635, 354, 368, 371, 360, 380, 0, 381, 356, - 357, 362, 365, 366, 367, 372, 373, 377, 383, 263, - 218, 410, 420, 608, 330, 224, 225, 226, 553, 554, - 555, 556, 651, 652, 656, 213, 486, 487, 488, 489, - 308, 646, 326, 492, 491, 350, 351, 398, 472, 569, - 571, 582, 586, 588, 590, 596, 599, 570, 572, 583, - 587, 589, 591, 597, 600, 559, 561, 563, 565, 578, - 577, 574, 602, 603, 580, 585, 564, 576, 581, 594, - 601, 598, 558, 562, 566, 575, 593, 592, 573, 584, - 595, 579, 567, 560, 568, 0, 204, 229, 387, 0, - 478, 304, 682, 650, 508, 645, 214, 231, 0, 278, + 0, 0, 0, 0, 313, 0, 423, 273, 0, 477, + 0, 319, 334, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 661, 0, 0, 0, 0, 0, 0, + 0, 384, 0, 349, 205, 233, 0, 0, 434, 485, + 497, 0, 0, 0, 0, 269, 0, 495, 448, 636, + 243, 300, 482, 455, 493, 463, 303, 0, 0, 494, + 391, 617, 473, 633, 662, 663, 279, 428, 647, 551, + 655, 680, 234, 276, 442, 535, 639, 519, 417, 613, + 614, 348, 518, 311, 209, 388, 668, 232, 503, 390, + 253, 241, 619, 644, 315, 267, 305, 480, 675, 221, + 546, 630, 250, 507, 0, 0, 683, 258, 529, 642, + 631, 223, 626, 528, 413, 345, 346, 222, 0, 481, + 284, 309, 0, 0, 274, 437, 621, 622, 272, 684, + 237, 654, 228, 0, 653, 430, 616, 627, 414, 402, + 227, 625, 412, 401, 353, 374, 375, 296, 324, 470, + 394, 471, 323, 325, 425, 424, 426, 215, 640, 658, + 0, 216, 0, 524, 643, 685, 475, 220, 244, 245, + 248, 0, 295, 299, 307, 310, 320, 321, 331, 386, + 441, 469, 465, 474, 0, 610, 634, 648, 660, 666, + 667, 669, 670, 671, 672, 673, 676, 674, 429, 329, + 520, 352, 392, 0, 0, 447, 496, 251, 638, 521, + 240, 604, 418, 427, 259, 261, 260, 235, 512, 609, + 246, 266, 207, 0, 0, 0, 0, 270, 271, 0, + 605, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, + 696, 697, 698, 699, 700, 701, 702, 703, 681, 537, + 543, 538, 539, 540, 541, 542, 0, 544, 0, 0, + 0, 0, 0, 419, 0, 623, 624, 704, 403, 510, + 635, 354, 368, 371, 360, 380, 0, 381, 356, 357, + 362, 365, 366, 367, 372, 373, 377, 383, 263, 218, + 410, 420, 608, 330, 224, 225, 226, 553, 554, 555, + 556, 651, 652, 656, 213, 486, 487, 488, 489, 308, + 646, 326, 492, 491, 350, 351, 398, 472, 569, 571, + 582, 586, 588, 590, 596, 599, 570, 572, 583, 587, + 589, 591, 597, 600, 559, 561, 563, 565, 578, 577, + 574, 602, 603, 580, 585, 564, 576, 581, 594, 601, + 598, 558, 562, 566, 575, 593, 592, 573, 584, 595, + 579, 567, 560, 568, 0, 204, 229, 387, 0, 478, + 304, 682, 650, 508, 645, 214, 231, 0, 278, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 206, 208, 217, 230, 242, 247, 254, 277, 292, - 294, 301, 314, 327, 328, 337, 338, 341, 347, 399, - 406, 407, 408, 409, 431, 432, 433, 436, 439, 440, - 443, 445, 446, 449, 454, 458, 459, 460, 462, 464, - 466, 479, 484, 498, 499, 500, 501, 502, 505, 506, - 513, 514, 515, 516, 517, 525, 526, 531, 532, 533, - 534, 545, 618, 620, 637, 657, 664, 504, 404, 452, - 476, 611, 0, 0, 317, 318, 467, 468, 332, 333, - 678, 679, 316, 632, 665, 629, 677, 659, 461, 397, - 0, 0, 400, 297, 322, 339, 0, 649, 527, 236, - 490, 306, 265, 0, 0, 219, 257, 239, 275, 290, - 293, 343, 411, 421, 451, 457, 312, 287, 255, 483, - 252, 509, 548, 549, 550, 552, 415, 282, 456, 557, - 0, 395, 606, 607, 335, 0, 0, 0, 0, 0, + 206, 208, 217, 230, 242, 247, 254, 277, 292, 294, + 301, 314, 327, 328, 337, 338, 341, 347, 399, 406, + 407, 408, 409, 431, 432, 433, 436, 439, 440, 443, + 445, 446, 449, 454, 458, 459, 460, 462, 464, 466, + 479, 484, 498, 499, 500, 501, 502, 505, 506, 513, + 514, 515, 516, 517, 525, 526, 531, 532, 533, 534, + 545, 618, 620, 637, 657, 664, 504, 404, 452, 476, + 611, 0, 0, 317, 318, 467, 468, 332, 333, 678, + 679, 316, 632, 665, 629, 677, 659, 461, 397, 0, + 0, 400, 297, 322, 339, 0, 649, 527, 236, 490, + 306, 265, 0, 0, 219, 257, 239, 275, 290, 293, + 343, 411, 421, 451, 457, 312, 287, 255, 483, 252, + 509, 548, 549, 550, 552, 415, 282, 456, 0, 557, + 395, 606, 607, 335, 2509, 0, 0, 0, 0, 0, 0, 438, 0, 0, 0, 0, 0, 0, 0, 286, 0, 0, 0, 0, 385, 283, 0, 0, 212, 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, @@ -6435,7 +6490,7 @@ var yyAct = [...]int{ 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, - 0, 0, 0, 0, 1848, 536, 756, 0, 0, 0, + 0, 0, 0, 0, 0, 536, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, 0, @@ -6512,7 +6567,7 @@ var yyAct = [...]int{ 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, 0, - 0, 0, 0, 0, 536, 202, 0, 0, 0, 0, + 0, 0, 0, 1850, 536, 756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, 0, 0, @@ -6564,7 +6619,7 @@ var yyAct = [...]int{ 591, 597, 600, 559, 561, 563, 565, 578, 577, 574, 602, 603, 580, 585, 564, 576, 581, 594, 601, 598, 558, 562, 566, 575, 593, 592, 573, 584, 595, 579, - 567, 560, 568, 0, 204, 229, 387, 2141, 478, 304, + 567, 560, 568, 0, 204, 229, 387, 0, 478, 304, 682, 650, 508, 645, 214, 231, 0, 278, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, @@ -6589,7 +6644,7 @@ var yyAct = [...]int{ 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, 0, 0, - 0, 0, 2132, 536, 756, 0, 0, 0, 0, 0, + 0, 0, 0, 536, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, 0, 0, 281, @@ -6641,7 +6696,7 @@ var yyAct = [...]int{ 597, 600, 559, 561, 563, 565, 578, 577, 574, 602, 603, 580, 585, 564, 576, 581, 594, 601, 598, 558, 562, 566, 575, 593, 592, 573, 584, 595, 579, 567, - 560, 568, 0, 204, 229, 387, 0, 478, 304, 682, + 560, 568, 0, 204, 229, 387, 2144, 478, 304, 682, 650, 508, 645, 214, 231, 0, 278, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 208, @@ -6660,13 +6715,13 @@ var yyAct = [...]int{ 549, 550, 552, 415, 282, 456, 557, 0, 395, 606, 607, 335, 0, 0, 0, 0, 0, 0, 438, 0, 0, 0, 0, 0, 0, 0, 286, 0, 0, 0, - 0, 385, 283, 0, 1990, 212, 530, 0, 453, 0, + 0, 385, 283, 0, 0, 212, 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, 450, 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, 0, 0, 0, - 0, 0, 536, 756, 0, 0, 0, 0, 0, 0, + 0, 2135, 536, 756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, 0, 0, 281, 340, @@ -6737,7 +6792,7 @@ var yyAct = [...]int{ 550, 552, 415, 282, 456, 557, 0, 395, 606, 607, 335, 0, 0, 0, 0, 0, 0, 438, 0, 0, 0, 0, 0, 0, 0, 286, 0, 0, 0, 0, - 385, 283, 0, 1988, 212, 530, 0, 453, 0, 211, + 385, 283, 0, 1993, 212, 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, 450, 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6814,7 +6869,7 @@ var yyAct = [...]int{ 552, 415, 282, 456, 557, 0, 395, 606, 607, 335, 0, 0, 0, 0, 0, 0, 438, 0, 0, 0, 0, 0, 0, 0, 286, 0, 0, 0, 0, 385, - 283, 0, 1986, 212, 530, 0, 453, 0, 211, 0, + 283, 0, 1991, 212, 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, 450, 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6891,7 +6946,7 @@ var yyAct = [...]int{ 415, 282, 456, 557, 0, 395, 606, 607, 335, 0, 0, 0, 0, 0, 0, 438, 0, 0, 0, 0, 0, 0, 0, 286, 0, 0, 0, 0, 385, 283, - 0, 1984, 212, 530, 0, 453, 0, 211, 0, 511, + 0, 1989, 212, 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, 450, 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6968,7 +7023,7 @@ var yyAct = [...]int{ 282, 456, 557, 0, 395, 606, 607, 335, 0, 0, 0, 0, 0, 0, 438, 0, 0, 0, 0, 0, 0, 0, 286, 0, 0, 0, 0, 385, 283, 0, - 1982, 212, 530, 0, 453, 0, 211, 0, 511, 268, + 1987, 212, 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, 450, 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -7044,7 +7099,7 @@ var yyAct = [...]int{ 255, 483, 252, 509, 548, 549, 550, 552, 415, 282, 456, 557, 0, 395, 606, 607, 335, 0, 0, 0, 0, 0, 0, 438, 0, 0, 0, 0, 0, 0, - 0, 286, 0, 0, 0, 0, 385, 283, 0, 1978, + 0, 286, 0, 0, 0, 0, 385, 283, 0, 1985, 212, 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, 450, 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, @@ -7121,7 +7176,7 @@ var yyAct = [...]int{ 483, 252, 509, 548, 549, 550, 552, 415, 282, 456, 557, 0, 395, 606, 607, 335, 0, 0, 0, 0, 0, 0, 438, 0, 0, 0, 0, 0, 0, 0, - 286, 0, 0, 0, 0, 385, 283, 0, 1976, 212, + 286, 0, 0, 0, 0, 385, 283, 0, 1981, 212, 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, 450, 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, @@ -7198,7 +7253,7 @@ var yyAct = [...]int{ 252, 509, 548, 549, 550, 552, 415, 282, 456, 557, 0, 395, 606, 607, 335, 0, 0, 0, 0, 0, 0, 438, 0, 0, 0, 0, 0, 0, 0, 286, - 0, 0, 0, 0, 385, 283, 0, 1974, 212, 530, + 0, 0, 0, 0, 385, 283, 0, 1979, 212, 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, 450, 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, @@ -7275,13 +7330,13 @@ var yyAct = [...]int{ 509, 548, 549, 550, 552, 415, 282, 456, 557, 0, 395, 606, 607, 335, 0, 0, 0, 0, 0, 0, 438, 0, 0, 0, 0, 0, 0, 0, 286, 0, - 0, 0, 0, 385, 283, 0, 0, 212, 530, 0, + 0, 0, 0, 385, 283, 0, 1977, 212, 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, 450, 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, 0, - 1949, 0, 0, 0, 536, 756, 0, 0, 0, 0, + 0, 0, 0, 0, 536, 756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, 0, 0, @@ -7351,14 +7406,14 @@ var yyAct = [...]int{ 411, 421, 451, 457, 312, 287, 255, 483, 252, 509, 548, 549, 550, 552, 415, 282, 456, 557, 0, 395, 606, 607, 335, 0, 0, 0, 0, 0, 0, 438, - 0, 0, 0, 0, 0, 0, 1852, 286, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 286, 0, 0, 0, 0, 385, 283, 0, 0, 212, 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, 450, 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 342, 262, 344, 210, 435, 523, 302, 0, 0, - 0, 0, 0, 536, 202, 0, 0, 0, 0, 0, + 0, 342, 262, 344, 210, 435, 523, 302, 0, 1952, + 0, 0, 0, 536, 756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, 0, 0, 281, @@ -7428,14 +7483,14 @@ var yyAct = [...]int{ 421, 451, 457, 312, 287, 255, 483, 252, 509, 548, 549, 550, 552, 415, 282, 456, 557, 0, 395, 606, 607, 335, 0, 0, 0, 0, 0, 0, 438, 0, - 0, 0, 0, 0, 0, 0, 286, 0, 0, 0, + 0, 0, 0, 0, 0, 1855, 286, 0, 0, 0, 0, 385, 283, 0, 0, 212, 530, 0, 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, 289, 285, 264, 336, 405, 450, 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 342, 262, 344, 210, 435, 523, 302, 0, 101, 0, - 0, 0, 536, 991, 0, 0, 0, 0, 0, 0, + 342, 262, 344, 210, 435, 523, 302, 0, 0, 0, + 0, 0, 536, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, 0, 0, 281, 340, @@ -7511,8 +7566,8 @@ var yyAct = [...]int{ 336, 405, 450, 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, - 262, 344, 210, 435, 523, 302, 0, 0, 0, 0, - 0, 536, 202, 0, 0, 0, 0, 0, 0, 0, + 262, 344, 210, 435, 523, 302, 0, 101, 0, 0, + 0, 536, 991, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, 0, 0, 281, 340, 288, @@ -7526,7 +7581,7 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1506, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 313, 0, 423, 273, 0, 477, 0, 319, 334, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 661, 0, 0, 0, 0, 0, 0, 0, 384, 0, 349, @@ -7575,7 +7630,7 @@ var yyAct = [...]int{ 500, 501, 502, 505, 506, 513, 514, 515, 516, 517, 525, 526, 531, 532, 533, 534, 545, 618, 620, 637, 657, 664, 504, 404, 452, 476, 611, 0, 0, 317, - 318, 467, 468, 332, 333, 678, 679, 1505, 632, 665, + 318, 467, 468, 332, 333, 678, 679, 316, 632, 665, 629, 677, 659, 461, 397, 0, 0, 400, 297, 322, 339, 0, 649, 527, 236, 490, 306, 265, 0, 0, 219, 257, 239, 275, 290, 293, 343, 411, 421, 451, @@ -7603,7 +7658,7 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 313, + 0, 0, 0, 0, 0, 0, 0, 1507, 0, 313, 0, 423, 273, 0, 477, 0, 319, 334, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 661, 0, 0, 0, 0, 0, 0, 0, 384, 0, 349, 205, @@ -7644,7 +7699,7 @@ var yyAct = [...]int{ 204, 229, 387, 0, 478, 304, 682, 650, 508, 645, 214, 231, 0, 278, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1084, 0, 0, 0, 206, 208, 217, 230, 242, + 0, 0, 0, 0, 0, 206, 208, 217, 230, 242, 247, 254, 277, 292, 294, 301, 314, 327, 328, 337, 338, 341, 347, 399, 406, 407, 408, 409, 431, 432, 433, 436, 439, 440, 443, 445, 446, 449, 454, 458, @@ -7652,7 +7707,7 @@ var yyAct = [...]int{ 501, 502, 505, 506, 513, 514, 515, 516, 517, 525, 526, 531, 532, 533, 534, 545, 618, 620, 637, 657, 664, 504, 404, 452, 476, 611, 0, 0, 317, 318, - 467, 468, 332, 333, 678, 679, 316, 632, 665, 629, + 467, 468, 332, 333, 678, 679, 1506, 632, 665, 629, 677, 659, 461, 397, 0, 0, 400, 297, 322, 339, 0, 649, 527, 236, 490, 306, 265, 0, 0, 219, 257, 239, 275, 290, 293, 343, 411, 421, 451, 457, @@ -7682,7 +7737,7 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 313, 0, 423, 273, 0, 477, 0, 319, 334, 0, 0, 0, - 0, 0, 0, 0, 0, 707, 0, 661, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 661, 0, 0, 0, 0, 0, 0, 0, 384, 0, 349, 205, 233, 0, 0, 434, 485, 497, 0, 0, 0, 0, 269, 0, 495, 448, 636, 243, 300, 482, 455, 493, 463, @@ -7721,7 +7776,7 @@ var yyAct = [...]int{ 229, 387, 0, 478, 304, 682, 650, 508, 645, 214, 231, 0, 278, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 206, 208, 217, 230, 242, 247, + 1084, 0, 0, 0, 206, 208, 217, 230, 242, 247, 254, 277, 292, 294, 301, 314, 327, 328, 337, 338, 341, 347, 399, 406, 407, 408, 409, 431, 432, 433, 436, 439, 440, 443, 445, 446, 449, 454, 458, 459, @@ -7742,7 +7797,7 @@ var yyAct = [...]int{ 547, 444, 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, - 435, 523, 302, 0, 0, 0, 0, 0, 536, 756, + 435, 523, 302, 0, 0, 0, 0, 0, 536, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, @@ -7759,7 +7814,7 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 313, 0, 423, 273, 0, 477, 0, 319, 334, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 661, 0, 0, 0, + 0, 0, 0, 0, 707, 0, 661, 0, 0, 0, 0, 0, 0, 0, 384, 0, 349, 205, 233, 0, 0, 434, 485, 497, 0, 0, 0, 0, 269, 0, 495, 448, 636, 243, 300, 482, 455, 493, 463, 303, @@ -7800,7 +7855,7 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 208, 217, 230, 242, 247, 254, 277, 292, 294, 301, 314, 327, 328, 337, 338, 341, - 347, 399, 406, 407, 408, 409, 4264, 432, 433, 436, + 347, 399, 406, 407, 408, 409, 431, 432, 433, 436, 439, 440, 443, 445, 446, 449, 454, 458, 459, 460, 462, 464, 466, 479, 484, 498, 499, 500, 501, 502, 505, 506, 513, 514, 515, 516, 517, 525, 526, 531, @@ -7877,7 +7932,7 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 208, 217, 230, 242, 247, 254, 277, 292, 294, 301, 314, 327, 328, 337, 338, 341, 347, - 399, 406, 407, 408, 409, 431, 432, 433, 436, 439, + 399, 406, 407, 408, 409, 4272, 432, 433, 436, 439, 440, 443, 445, 446, 449, 454, 458, 459, 460, 462, 464, 466, 479, 484, 498, 499, 500, 501, 502, 505, 506, 513, 514, 515, 516, 517, 525, 526, 531, 532, @@ -7896,7 +7951,7 @@ var yyAct = [...]int{ 0, 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, 523, - 302, 0, 0, 0, 0, 0, 536, 991, 0, 0, + 302, 0, 0, 0, 0, 0, 536, 756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, @@ -7973,7 +8028,7 @@ var yyAct = [...]int{ 389, 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342, 262, 344, 210, 435, 523, 302, - 0, 0, 0, 0, 0, 536, 202, 0, 0, 0, + 0, 0, 0, 0, 0, 536, 991, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, 376, 382, 355, 364, 0, 0, 641, 0, 0, @@ -8041,34 +8096,109 @@ var yyAct = [...]int{ 0, 400, 297, 322, 339, 0, 649, 527, 236, 490, 306, 265, 0, 0, 219, 257, 239, 275, 290, 293, 343, 411, 421, 451, 457, 312, 287, 255, 483, 252, - 509, 548, 549, 550, 552, 415, 282, 456, 0, 0, - 395, 606, 607, 335, + 509, 548, 549, 550, 552, 415, 282, 456, 557, 0, + 395, 606, 607, 335, 0, 0, 0, 0, 0, 0, + 438, 0, 0, 0, 0, 0, 0, 0, 286, 0, + 0, 0, 0, 385, 283, 0, 0, 212, 530, 0, + 453, 0, 211, 0, 511, 268, 396, 393, 615, 298, + 289, 285, 264, 336, 405, 450, 547, 444, 0, 389, + 0, 0, 522, 422, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 342, 262, 344, 210, 435, 523, 302, 0, + 0, 0, 0, 0, 536, 202, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 249, 0, 0, 256, 0, + 0, 0, 370, 379, 378, 358, 359, 361, 363, 369, + 376, 382, 355, 364, 0, 0, 641, 0, 0, 0, + 281, 340, 288, 280, 612, 0, 0, 0, 0, 0, + 0, 628, 0, 0, 238, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 291, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 416, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 313, 0, 423, 273, 0, 477, 0, + 319, 334, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 661, 0, 0, 0, 0, 0, 0, 0, + 384, 0, 349, 205, 233, 0, 0, 434, 485, 497, + 0, 0, 0, 0, 269, 0, 495, 448, 636, 243, + 300, 482, 455, 493, 463, 303, 0, 0, 494, 391, + 617, 473, 633, 662, 663, 279, 428, 647, 551, 655, + 680, 234, 276, 442, 535, 639, 519, 417, 613, 614, + 348, 518, 311, 209, 388, 668, 232, 503, 390, 253, + 241, 619, 644, 315, 267, 305, 480, 675, 221, 546, + 630, 250, 507, 0, 0, 683, 258, 529, 642, 631, + 223, 626, 528, 413, 345, 346, 222, 0, 481, 284, + 309, 0, 0, 274, 437, 621, 622, 272, 684, 237, + 654, 228, 0, 653, 430, 616, 627, 414, 402, 227, + 625, 412, 401, 353, 374, 375, 296, 324, 470, 394, + 471, 323, 325, 425, 424, 426, 215, 640, 658, 0, + 216, 0, 524, 643, 685, 475, 220, 244, 245, 248, + 0, 295, 299, 307, 310, 320, 321, 331, 386, 441, + 469, 465, 474, 0, 610, 634, 648, 660, 666, 667, + 669, 670, 671, 672, 673, 676, 674, 429, 329, 520, + 352, 392, 0, 0, 447, 496, 251, 638, 521, 240, + 604, 418, 427, 259, 261, 260, 235, 512, 609, 246, + 266, 207, 0, 0, 0, 0, 270, 271, 0, 605, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 686, + 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, + 697, 698, 699, 700, 701, 702, 703, 681, 537, 543, + 538, 539, 540, 541, 542, 0, 544, 0, 0, 0, + 0, 0, 419, 0, 623, 624, 704, 403, 510, 635, + 354, 368, 371, 360, 380, 0, 381, 356, 357, 362, + 365, 366, 367, 372, 373, 377, 383, 263, 218, 410, + 420, 608, 330, 224, 225, 226, 553, 554, 555, 556, + 651, 652, 656, 213, 486, 487, 488, 489, 308, 646, + 326, 492, 491, 350, 351, 398, 472, 569, 571, 582, + 586, 588, 590, 596, 599, 570, 572, 583, 587, 589, + 591, 597, 600, 559, 561, 563, 565, 578, 577, 574, + 602, 603, 580, 585, 564, 576, 581, 594, 601, 598, + 558, 562, 566, 575, 593, 592, 573, 584, 595, 579, + 567, 560, 568, 0, 204, 229, 387, 0, 478, 304, + 682, 650, 508, 645, 214, 231, 0, 278, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, + 208, 217, 230, 242, 247, 254, 277, 292, 294, 301, + 314, 327, 328, 337, 338, 341, 347, 399, 406, 407, + 408, 409, 431, 432, 433, 436, 439, 440, 443, 445, + 446, 449, 454, 458, 459, 460, 462, 464, 466, 479, + 484, 498, 499, 500, 501, 502, 505, 506, 513, 514, + 515, 516, 517, 525, 526, 531, 532, 533, 534, 545, + 618, 620, 637, 657, 664, 504, 404, 452, 476, 611, + 0, 0, 317, 318, 467, 468, 332, 333, 678, 679, + 316, 632, 665, 629, 677, 659, 461, 397, 0, 0, + 400, 297, 322, 339, 0, 649, 527, 236, 490, 306, + 265, 0, 0, 219, 257, 239, 275, 290, 293, 343, + 411, 421, 451, 457, 312, 287, 255, 483, 252, 509, + 548, 549, 550, 552, 415, 282, 456, 0, 0, 395, + 606, 607, 335, } var yyPact = [...]int{ - -1000, -1000, -559, -1000, 8464, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -559, -1000, 6289, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 2611, 2694, -1000, -1000, -1000, - -1000, 2795, -1000, 1092, -1000, 2290, 2216, 2587, 4447, -1000, - 61657, 530, -1000, 58581, -423, 924, 296, 40893, -1000, 262, - -1000, 253, 60119, 258, -1000, -1000, -1000, -1000, -423, 24712, - 2496, 55, 49, 61657, -1000, -1000, -1000, -1000, -346, 2761, - 2214, -1000, 474, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 57812, -1000, -1000, -1000, 1246, -1000, 2595, 2596, 2464, 980, - 1855, -1000, 2627, 2214, -1000, 24712, 2728, 2552, 23937, 23937, - 475, -1000, -1000, 333, -1000, -1000, 35510, 61657, 44738, 2636, - 60119, -1000, 2587, -1000, -1000, -1000, 187, -1000, 367, 2182, - -1000, 2172, -1000, 856, 1147, 398, 870, 865, 397, 396, - 395, 379, 377, 374, 373, 372, 406, -1000, 1008, 1008, - -233, -244, 1497, 479, 455, 455, 1114, 506, 2557, 2532, - -1000, -1000, 1008, 1008, 1008, 405, 1008, 1008, 1008, 1008, - 346, 342, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, - 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 986, - 2587, 330, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 2631, 2719, -1000, -1000, -1000, + -1000, 2855, -1000, 1167, -1000, 2301, 2219, 2663, 4499, -1000, + 62976, 798, -1000, 59900, -411, 944, 250, 42212, -1000, 255, + -1000, 234, 61438, 245, -1000, -1000, -1000, -1000, -411, 26031, + 2549, 97, 96, 62976, -1000, -1000, -1000, -1000, -345, 2821, + 2144, -1000, 488, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 59131, -1000, -1000, -1000, 1306, -1000, 2672, 2636, 2524, 1019, + 1549, -1000, 2745, 2144, -1000, 26031, 2785, 2617, 25256, 24481, + 487, -1000, -1000, 269, -1000, -1000, 36829, 62976, 46057, 2732, + 61438, -1000, 2663, -1000, -1000, -1000, 214, -1000, 420, 2185, + -1000, 2184, -1000, 1172, 1258, 437, 871, 868, 435, 434, + 433, 428, 427, 425, 424, 423, 444, -1000, 1055, 1055, + -201, -203, 2192, 485, 483, 483, 1007, 514, 2612, 2573, + -1000, -1000, 1055, 1055, 1055, 392, 1055, 1055, 1055, 1055, + 404, 400, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, + 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 910, + 2663, 336, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, @@ -8116,70 +8246,70 @@ var yyPact = [...]int{ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 61657, 289, 61657, -1000, 872, - 529, -1000, -1000, -437, 1157, 1157, 62, 1157, 1157, 1157, - 1157, 234, 1046, 48, -1000, 227, 318, 228, 324, 1126, - 795, -1000, -1000, 319, 1126, 2001, -1000, 991, 323, 171, - -1000, 1157, 1157, -1000, 16955, 224, 16955, 16955, 321, 233, - -1000, 2571, -1000, -1000, -1000, -1000, -1000, 1460, -1000, -1000, - -1000, -1000, -31, 505, -1000, -1000, -1000, -1000, 60119, 57043, - 312, -1000, -1000, 276, 2014, 1210, 24712, 2506, 968, -1000, - -1000, 1457, 934, -1000, -1000, -1000, -1000, -1000, 871, -1000, - 27037, 27037, 27037, 27037, -1000, -1000, 2184, 56274, 2184, 2184, - 27037, 2184, 27037, 2184, 2184, 2184, 2184, 24712, 2184, 2184, - 2184, 2184, -1000, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, -1000, -1000, -1000, -1000, 2184, 869, 2184, 2184, - 2184, 2184, 2184, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 2184, 2184, 2184, 2184, 2184, 2184, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, -1000, - -1000, -1000, 1792, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 1510, 1723, 1713, 1703, -1000, 21612, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 62976, 808, 62976, -1000, 896, + 795, -1000, -1000, -416, 1181, 1181, 109, 1181, 1181, 1181, + 1181, 233, 1065, 95, -1000, 232, 308, 218, 329, 1134, + 932, -1000, -1000, 304, 1134, 1937, -1000, 1027, 313, 220, + -1000, 1181, 1181, -1000, 16724, 204, 16724, 16724, 310, 210, + -1000, 2655, -1000, -1000, -1000, -1000, -1000, 1477, -1000, -1000, + -1000, -1000, -14, 510, -1000, -1000, -1000, -1000, 61438, 58362, + 359, -1000, -1000, 339, 1953, 1571, 26031, 3651, 987, -1000, + -1000, 1455, 948, -1000, -1000, -1000, -1000, -1000, 864, -1000, + 28356, 28356, 28356, 28356, -1000, -1000, 2193, 57593, 2193, 2193, + 28356, 2193, 28356, 2193, 2193, 2193, 2193, 26031, 2193, 2193, + 2193, 2193, -1000, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, -1000, -1000, -1000, -1000, 2193, 892, 2193, 2193, + 2193, 2193, 2193, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 2193, 2193, 2193, 2193, 2193, 2193, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, -1000, + -1000, -1000, 1796, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 2817, 1666, 1653, 1640, -1000, 21381, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 2184, -1000, -1000, -1000, - 61657, -1000, 2184, 280, 60119, 60119, 383, 1447, -1000, -1000, - 2627, 2214, -1000, 2761, 2736, 474, -1000, 3749, 1842, 1857, - 1484, 2214, 1194, 2110, 61657, -1000, 2216, 201, -1000, -1000, - -1000, -341, -352, 2411, 1529, 1993, 2152, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 1414, 24712, -1000, -1000, 2782, - -1000, 32434, 861, 2781, 55505, -1000, 475, 475, 2151, 656, - 10, -1000, -1000, -1000, -1000, 1044, 40124, -1000, -1000, -1000, - -1000, -1000, 2045, 61657, -1000, -1000, 5383, 60119, -1000, 2288, - -1000, 2039, -1000, 2229, 24712, 474, 2030, -1000, -1000, -1000, - -1000, 1008, 1008, 1008, -1000, 404, 2727, 4447, 5249, -1000, - -1000, -1000, 54736, 2287, 60119, -1000, 2283, -1000, 1120, 900, - 897, 897, 60119, -1000, -1000, 60888, 60119, 1119, 1117, 60119, - 60119, 60119, 60119, -1000, 53967, -1000, 53198, 52429, 1445, 60119, - 51660, 50891, 50122, 49353, 48584, -1000, 2431, -1000, 2261, -1000, - -1000, -1000, 60888, 60119, 60119, 60888, 60119, 60888, 61657, 60119, - -1000, -1000, 414, -1000, -1000, 1437, 1433, 1429, 1008, 1008, - 1428, 1991, 1988, 1964, 1008, 1008, 1425, 1950, 43200, 1948, - 326, 1408, 1399, 1380, 1443, 1941, 246, 1926, 1407, 1356, - 1378, 60119, 2282, 61657, -1000, 313, 1088, 1005, -1000, -1000, - -1000, 1031, 2587, 2490, 2148, 504, 528, 60119, 483, 483, - 483, 60119, -1000, -1000, 17732, 61657, 284, -1000, 1900, 24712, - -1000, 1143, 1126, 1126, -1000, -1000, -1000, -1000, -1000, -1000, - 1157, 61657, 1143, -1000, -1000, -1000, 1126, 1157, 61657, 1157, - 1157, 1157, 1157, 1126, 1126, 1126, 1157, 61657, 61657, 61657, - 61657, 61657, 61657, 61657, 61657, 61657, 16955, 991, 1157, -438, - -1000, 1897, -1000, -1000, -1000, 2389, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 2193, -1000, -1000, -1000, + 62976, -1000, 2193, 272, 61438, 61438, 370, 1461, -1000, -1000, + 2745, 2144, -1000, 2821, 2862, 488, -1000, 3990, 2105, 1831, + 1504, 2144, 1073, 2140, 62976, -1000, 2219, 191, -1000, -1000, + -1000, -300, -324, 2416, 1703, 1935, 2169, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 2190, 26031, -1000, -1000, 2847, + 2844, 33753, 891, 2839, 2835, 56824, -1000, 487, 487, 2166, + 652, 75, -1000, -1000, -1000, -1000, 1111, 41443, -1000, -1000, + -1000, -1000, -1000, 2023, 62976, -1000, -1000, 7049, 61438, -1000, + 2296, -1000, 2021, -1000, 2238, 26031, 488, 1989, -1000, -1000, + -1000, -1000, 1055, 1055, 1055, -1000, 443, 2784, 4499, 5943, + -1000, -1000, -1000, 56055, 2292, 61438, -1000, 2282, -1000, 1213, + 900, 918, 918, 61438, -1000, -1000, 62207, 61438, 1211, 1210, + 61438, 61438, 61438, 61438, -1000, 55286, -1000, 54517, 53748, 1460, + 61438, 52979, 52210, 51441, 50672, 49903, -1000, 2413, -1000, 2167, + -1000, -1000, -1000, 62207, 61438, 61438, 62207, 61438, 62207, 62976, + 61438, -1000, -1000, 628, -1000, -1000, 1457, 1456, 1441, 1055, + 1055, 1440, 1934, 1933, 1932, 1055, 1055, 1435, 1931, 44519, + 1928, 324, 1430, 1426, 1418, 1480, 1917, 251, 1916, 1421, + 1374, 1413, 61438, 2281, 62976, -1000, 298, 1024, 1068, -1000, + -1000, -1000, 1106, 2663, 2546, 2156, 505, 792, 61438, 497, + 497, 497, 61438, -1000, -1000, 17501, 62976, 266, -1000, 1906, + 26031, -1000, 1150, 1134, 1134, -1000, -1000, -1000, -1000, -1000, + -1000, 1181, 62976, 1150, -1000, -1000, -1000, 1134, 1181, 62976, + 1181, 1181, 1181, 1181, 1134, 1134, 1134, 1181, 62976, 62976, + 62976, 62976, 62976, 62976, 62976, 62976, 62976, 16724, 1027, 1181, + -418, -1000, 1903, -1000, -1000, -1000, 2422, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, @@ -8194,355 +8324,357 @@ var yyPact = [...]int{ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 16955, 16955, - -1000, -1000, 2662, 2660, -1000, -1000, -1000, 2145, -1000, 245, - 5, 256, -1000, 47815, 534, 1030, -1000, 534, -1000, -1000, - -1000, -1000, -1000, 2143, 47046, -1000, -439, -443, -449, -451, - -1000, -1000, -1000, -452, -455, -1000, -1000, -1000, 24712, 24712, - 24712, 24712, -271, 962, 1635, 27037, 2548, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 24712, 1254, 1276, 27037, 27037, 27037, - 27037, 27037, 27037, 27037, 28587, 27812, 27037, 27037, 27037, 27037, - 27037, 27037, -1000, -1000, 37817, 6546, 6546, 934, 934, 934, - 934, -1000, -188, 2138, 60888, -1000, -1000, -1000, 859, 24712, - 24712, 934, -1000, 1464, 2661, 21612, 24712, 24712, 24712, 24712, - 1067, 1210, 60888, 24712, -1000, 1484, -1000, -1000, -1000, -1000, - 1265, -1000, -1000, 1133, 2533, 2533, 2533, 2533, 24712, 24712, - 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, 2533, 24712, - 750, 750, 910, 24712, 24712, 24712, 24712, 24712, 24712, 24712, - 24712, 20061, 24712, 24712, 27037, 24712, 24712, 24712, 1484, 24712, - 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, - 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, - 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, - 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, - 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, - 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, - 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, - 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, 1484, 24712, - 1489, 24712, 24712, 24712, 24712, 24712, 24712, 24712, 19286, 24712, - 24712, 24712, 24712, 24712, -1000, -1000, -1000, -1000, -1000, -1000, - 24712, 24712, 24712, 24712, 24712, 24712, 24712, 24712, 1484, 24712, - 24712, 24712, 24712, 24712, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 1715, 1735, 1718, 2184, 24712, -1000, - 2129, -1000, -159, 34741, 24712, 1882, 2779, 2313, 60119, -1000, - -1000, -1000, -1000, 2627, -1000, 2627, 1715, 3650, 2421, 23937, - -1000, -1000, 3650, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 1978, -1000, 316, 527, - 2258, 313, 60119, 523, 522, 520, 468, -1000, -68, 1029, - 61657, 2110, 2633, -1000, 2101, -1000, -1000, 2184, -1000, -312, - -1000, -317, 2409, 1853, 912, -1000, 1458, 24712, 24712, 2098, - -1000, 1205, 61657, -1000, -271, -1000, 46277, -1000, -1000, 16178, - 61657, 369, 61657, -1000, 33972, 45508, 336, -1000, 10, 2083, - -1000, 23, 0, 20836, 933, -1000, -1000, -1000, 1497, 29356, - 2011, 933, 150, -1000, -1000, -1000, 2229, -1000, 2229, 2229, - 2229, 2229, 2229, 912, 912, 912, 2229, -1000, -1000, -1000, - -1000, 2281, 2229, 2276, -1000, 2229, 2229, 2229, 2229, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 2270, 2270, 2270, 2268, - 2268, 2231, 2231, 439, -1000, 24712, 450, 44738, 2614, 1376, - 1290, -200, -1000, 60119, 1629, 1588, 1517, -1000, -551, 2095, - -1000, -1000, 2723, -1000, -1000, 1263, 1158, 1148, 1208, 60119, - 291, 364, -1000, 442, -1000, 44738, 60119, 1095, 897, 60119, - -1000, 60119, -1000, -1000, -1000, -1000, -1000, 60119, -1000, -1000, - 2094, -1000, 2105, 1249, 1139, 1214, 1136, 2094, -1000, -1000, - -199, 2094, -1000, 2094, -1000, 2094, -1000, 2094, -1000, 2094, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1065, - 283, -349, 60119, 291, 502, -1000, 501, 37817, -1000, -1000, - -1000, 37817, 37817, -1000, -1000, -1000, -1000, 1829, 1825, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 16724, + 16724, -1000, -1000, 2755, 2747, -1000, -1000, -1000, 2154, -1000, + 231, 70, 239, -1000, 49134, 484, 1097, -1000, 484, -1000, + -1000, -1000, -1000, -1000, 2152, 48365, -1000, -420, -421, -429, + -435, -1000, -1000, -1000, -440, -442, -1000, -1000, -1000, 26031, + 26031, 26031, 26031, -230, 970, 1417, 28356, 2639, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 26031, 1299, 1069, 28356, 28356, + 28356, 28356, 28356, 28356, 28356, 29906, 29131, 28356, 28356, 28356, + 28356, 28356, 28356, -1000, -1000, 39136, 8698, 8698, 948, 948, + 948, 948, -1000, -178, 2145, 62207, -1000, -1000, -1000, 890, + 26031, 26031, 948, -1000, 1483, 1924, 21381, 26031, 26031, 26031, + 26031, 1136, 1571, 62207, 26031, -1000, 1504, -1000, -1000, -1000, + -1000, 1334, -1000, -1000, 1117, 2586, 2586, 2586, 2586, 26031, + 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 2586, + 26031, 282, 282, 1179, 26031, 26031, 26031, 26031, 26031, 26031, + 26031, 26031, 19830, 26031, 26031, 28356, 26031, 26031, 26031, 1504, + 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, + 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, + 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, + 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, + 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, + 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, + 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, + 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 1504, + 26031, 1481, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 19055, + 26031, 26031, 26031, 26031, 26031, -1000, -1000, -1000, -1000, -1000, + -1000, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 1504, + 26031, 26031, 26031, 26031, 26031, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 1890, 1874, 1622, 2193, 26031, + -1000, 2141, -1000, -139, 36060, 26031, 1882, 2829, 2315, 61438, + -1000, -1000, -1000, -1000, 2745, -1000, 2745, 1890, 3765, 2449, + 23706, -1000, -1000, 3765, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1724, -1000, 390, + 790, 2220, 298, 61438, 779, 548, 536, 494, -1000, -66, + 1093, 62976, 2140, 2731, -1000, 2137, -1000, -1000, 2193, -1000, + -277, -1000, -279, 2445, 1880, 853, -1000, 1506, 26031, 26031, + 2131, -1000, 1921, 62976, 62976, -1000, -230, -1000, 47596, -1000, + -1000, 15947, 62976, 62976, 421, 62976, -1000, 35291, 46827, 290, + -1000, 75, 2097, -1000, 51, 65, 20605, 947, -1000, -1000, + -1000, 2192, 30675, 1948, 947, 145, -1000, -1000, -1000, 2238, + -1000, 2238, 2238, 2238, 2238, 2238, 853, 853, 853, 2238, + -1000, -1000, -1000, -1000, 2277, 2238, 2270, -1000, 2238, 2238, + 2238, 2238, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2268, + 2268, 2268, 2267, 2267, 2239, 2239, 478, -1000, 26031, 407, + 46057, 2686, 1408, 1669, -185, -1000, 61438, 1634, 1591, 1585, + -1000, -502, 2129, -1000, -1000, 2783, -1000, -1000, 984, 1229, + 1228, 1256, 61438, 283, 414, -1000, 469, -1000, 46057, 61438, + 1208, 918, 61438, -1000, 61438, -1000, -1000, -1000, -1000, -1000, + 61438, -1000, -1000, 2122, -1000, 2096, 1286, 1227, 1234, 1209, + 2122, -1000, -1000, -184, 2122, -1000, 2122, -1000, 2122, -1000, + 2122, -1000, 2122, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 1081, 337, -325, 61438, 283, 504, -1000, 502, + 39136, -1000, -1000, -1000, 39136, 39136, -1000, -1000, -1000, -1000, + 1877, 1852, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -508, 61657, - -1000, 305, 350, 386, 375, 61657, 427, 2541, 2523, 2522, - 2520, 2518, 2516, 2515, 301, 337, 61657, 61657, 483, 2348, - 61657, 2620, 61657, 61657, -1000, -1000, -1000, -1000, -1000, 1819, - 1817, -1000, 1210, 61657, -1000, -1000, 1157, 1157, -1000, -1000, - 61657, 1157, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 1157, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 61657, -1000, -1000, -1000, - -1000, 1806, -1000, 61657, -31, 238, -1000, -1000, 60119, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -74, -1000, - 341, 21, 448, -1000, -1000, -1000, -1000, -1000, 2657, -1000, - 1210, 1051, 1014, 962, 2184, -1000, -1000, 1340, -1000, -1000, - -1000, -1000, -1000, 2184, 2184, 2184, -1000, -1000, -1000, -1000, - -1000, 1254, 27037, 27037, 27037, 1760, 858, 1338, 1483, 1471, - 1312, 1312, 964, 27037, 964, 27037, 941, 941, 941, 941, - 941, -1000, -1000, -1000, -1000, -1000, -1000, 1792, -1000, 1790, - -1000, 2184, 60888, 2023, 19286, 1602, 2025, 1484, 957, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 3618, - 1484, 2014, 1484, 1594, 3608, 1064, -1000, 24712, 1484, 3591, - -1000, -1000, 1484, 1484, 24712, -1000, -1000, 24712, 24712, 24712, - 24712, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, - 1290, 24712, 1290, 2092, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -508, 62976, -1000, 297, 409, 399, 394, 62976, 367, + 2593, 2592, 2583, 2580, 2571, 2567, 2564, 334, 398, 62976, + 62976, 497, 2387, 62976, 2691, 62976, 62976, -1000, -1000, -1000, + -1000, -1000, 1836, 1833, -1000, 1571, 62976, -1000, -1000, 1181, + 1181, -1000, -1000, 62976, 1181, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 1181, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 62976, + -1000, -1000, -1000, -1000, 1804, -1000, 62976, -14, 225, -1000, + -1000, 61438, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -41, -1000, 348, 64, 408, -1000, -1000, -1000, -1000, + -1000, 2739, -1000, 1571, 1035, 1033, 970, 2193, -1000, -1000, + 1244, -1000, -1000, -1000, -1000, -1000, 2193, 2193, 2193, -1000, + -1000, -1000, -1000, -1000, 1299, 28356, 28356, 28356, 1755, 860, + 1961, 1996, 1870, 1283, 1283, 1232, 28356, 1232, 28356, 952, + 952, 952, 952, 952, -1000, -1000, -1000, -1000, -1000, -1000, + 1796, -1000, 1787, -1000, 2193, 62207, 1901, 19055, 1751, 1800, + 1504, 981, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 2090, 2777, 1598, 1290, 1290, 1290, 1290, 3577, - 1290, 1290, 24712, 1667, -1000, -1000, -1000, 1758, 3572, 1653, - 3511, 1290, 1290, -1000, 1290, 3507, 3503, 1484, 2851, 2784, - 1290, 1290, 1290, 1290, 1290, 2778, 2774, 1290, 1290, 2767, - 1290, 3490, 1290, 2763, 2742, 2738, 2713, 2677, 2652, 2648, - 2635, 2623, 2606, 2574, 2559, 2545, 2538, 2534, 2529, 2513, - 2441, 1290, 1290, 1290, 3486, 1290, 3478, 1290, 3470, 1290, - 1290, 3453, 2432, 2420, 1484, 2086, -1000, 3449, 1290, 3440, - 3434, 3422, 2413, 3415, 3388, 3384, 1290, 1290, 1290, 2392, - 3379, 3373, 3369, 3354, 3348, 3341, 3326, 3321, 3299, 1290, - 1718, 1718, 1718, 1718, 1718, 3293, -278, 1290, 1484, -1000, - -1000, -1000, -1000, 3287, 2388, 3260, 3255, 3199, 3113, 1484, - 2184, 857, -1000, -1000, 1718, 1484, 1484, 1718, 1718, 3108, - 3100, 3092, 3088, 3036, 3027, 1290, 1290, -1000, 1290, 3019, - 3011, 2379, 2342, 1484, -1000, 1718, 61657, -1000, -432, -1000, - 11, 1025, 2184, -1000, 43200, 1484, -1000, 5250, -1000, 1456, - -1000, -1000, -1000, -1000, -1000, 39355, 1864, -1000, -1000, -1000, - 468, 518, 293, 468, 313, 305, 2306, 60119, 60119, 60119, - 61657, 1072, -1000, 517, -1000, 2184, -475, 23162, -1000, -1000, - -1000, 912, 129, 38586, 923, 923, 165, -1000, 1210, 1210, - 24712, -1000, -1000, -1000, -1000, -1000, -1000, 855, 2748, 380, - 2184, -1000, 2093, 3291, -1000, -1000, -1000, 2631, 30126, -1000, - -1000, 2184, 2184, 61657, 2066, 2061, -1000, 847, -1000, 1465, - 2083, 10, 14, -1000, -1000, -1000, -1000, 1210, -1000, 1498, - 370, 1453, -1000, 467, -1000, -1000, -1000, -1000, 2504, 141, - -1000, -1000, -1000, 593, 912, -1000, -1000, 912, -1000, -1000, - -1000, -1000, 1781, -1000, 1781, -1000, -1000, -1000, -1000, -1000, - 1373, -1000, -1000, -1000, -1000, 1361, -1000, -1000, 1360, -1000, - -1000, 2021, 2320, 450, -1000, -1000, 1008, 1771, -1000, -1000, - 2510, 1008, 1008, 60119, -1000, -1000, 2006, 2614, -1000, -1, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -544, 169, 388, - -1000, -1000, -1000, 4665, 60119, 2009, -1000, 281, -1000, 1922, - -1000, 60119, -1000, 2005, 2267, 60119, 60119, -1000, -1000, -1000, - 60119, 2184, -1000, -1000, -1000, -1000, 519, 2585, 328, -1000, - -1000, -299, -1000, -1000, 291, 281, 60888, 60119, 933, -1000, - -1000, -1000, -1000, -1000, -504, 1974, 516, 61657, 61657, 61657, - 61657, 61657, 61657, 819, -1000, -1000, 34, -1000, -1000, 259, - -1000, -1000, 1765, -1000, -1000, -1000, -1000, 259, -1000, -1000, - -1000, -1000, -1000, 332, 500, -1000, 61657, 61657, 1009, -1000, - -1000, -1000, -1000, -1000, -1000, 1126, -1000, -1000, 1126, -1000, + -1000, -1000, 3597, 1504, 1953, 1504, 1503, 3581, 1197, -1000, + 26031, 1504, 3576, -1000, -1000, 1504, 1504, 26031, -1000, -1000, + 26031, 26031, 26031, 26031, 1669, 1669, 1669, 1669, 1669, 1669, + 1669, 1669, 1669, 1669, 26031, 1669, 2118, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 2567, 61657, 19, -472, -1000, -469, 24712, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 1494, 844, 1338, 27037, 27037, - 2661, 2661, 27037, -1000, -1000, -1000, 1068, 1068, 37817, -1000, - 27037, 24712, -1000, -1000, 24712, 24712, 24712, 1049, -1000, 24712, - 2253, -1000, 24712, -1000, -278, 1718, 1290, 1290, 1290, 1290, - -278, -278, -278, -278, -278, -278, -278, -278, -278, -278, - 2050, -1000, 24712, 24712, 24712, 1484, 376, -1000, -1000, -1000, - -278, 24712, -1000, -1000, 2766, -1000, 24712, -1000, 37817, 24712, - 24712, 24712, -1000, -1000, -1000, 24712, 24712, -1000, -1000, 24712, - -1000, 24712, -1000, -1000, -1000, -1000, -1000, -1000, 24712, -1000, - 24712, -1000, -1000, -1000, 24712, -1000, 24712, -1000, -1000, 24712, - -1000, 24712, -1000, 24712, -1000, 24712, -1000, 24712, -1000, 24712, - -1000, 24712, -1000, 24712, -1000, 24712, -1000, 24712, -1000, 24712, - -1000, 24712, -1000, 24712, -1000, 24712, -1000, 24712, -1000, 24712, - -1000, 24712, -1000, 24712, -1000, -1000, -1000, 24712, -1000, 24712, - -1000, 24712, -1000, -1000, 24712, -1000, 24712, -1000, 24712, -1000, - 24712, 24712, -1000, 24712, 24712, 24712, -1000, 24712, 24712, 24712, - 24712, -1000, -1000, -1000, -1000, 24712, 24712, 24712, 24712, 24712, - 24712, 24712, 24712, 24712, 24712, -1000, -1000, -1000, -1000, -1000, - -1000, 24712, -1000, 44738, 54, -278, 1489, 54, 1489, 26262, - 879, 845, 25487, -1000, 24712, 18509, -1000, -1000, -1000, -1000, - -1000, 24712, 24712, 24712, 24712, 24712, 24712, -1000, -1000, -1000, - 24712, 24712, -1000, 24712, -1000, 24712, -1000, -1000, -1000, -1000, - -1000, 1025, -1000, 877, 854, 897, 60119, -1000, -1000, -1000, - -1000, 2077, -1000, 2710, -1000, 2444, 2442, 2759, 2748, 23937, - -1000, 33972, 61657, 61657, 303, 61657, 305, 514, 2346, -1000, - 2306, 2306, 2306, -1000, 2619, -1000, 2266, 1459, -1000, -1000, - -1000, -1000, -1000, -417, -1000, 2478, 2440, 923, 923, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 15401, 2627, 24712, 2345, - 60888, 2184, -1000, 31665, 60119, 60888, 33972, 33972, 33972, 33972, - 33972, -1000, 2376, 2372, -1000, 2369, 2360, 2391, 61657, -1000, - 1715, 1972, -1000, 24712, 36279, 2059, 33972, -1000, -1000, 33972, - 61657, 14624, -1000, -1000, 18, -5, -1000, -1000, -1000, -1000, - 1497, -1000, -1000, 1081, 2629, 2502, -1000, -1000, -1000, -1000, - -1000, -1000, 1969, -1000, 1955, 2074, 1937, 1934, 283, -1000, - 2247, 2564, 1008, 1008, -1000, 1352, -1000, 1464, 1762, 1759, - -1000, -1000, -1000, 432, -1000, -1000, -549, 1343, 2248, 2199, - 24712, 2237, 2720, 2055, 60119, -1000, -1000, 60888, -1000, 302, - -1000, 450, 60119, -1000, -1000, -1000, 364, 61657, -1000, 9649, - -1000, -1000, -1000, 281, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 61657, 2198, -1000, -1000, -1000, -1000, -1000, 254, 243, - 1754, 260, 1747, -1000, 260, -1000, 61657, 985, 2320, 61657, - -1000, -1000, -1000, 1157, 1157, -1000, -1000, 2562, -1000, 1464, - 1290, 27037, 27037, -1000, 934, -1000, -1000, 503, -253, 2229, - 2229, -1000, 2229, 2231, -1000, 2229, 225, 2229, 199, 2229, - -1000, -1000, 1484, 1484, -1000, 1718, 2317, 1706, 2929, -1000, - 1210, 24712, 2864, -1000, -1000, -278, -278, -278, -278, -278, + -1000, -1000, -1000, -1000, -1000, 2104, 2828, 1257, 1669, 1669, + 1669, 1669, 3572, 1669, 1669, 26031, 2523, -1000, -1000, -1000, + 1661, 3559, 1657, 3547, 1669, 1669, -1000, 1669, 3532, 3520, + 1504, 3034, 2827, 1669, 1669, 1669, 1669, 1669, 2792, 2782, + 1669, 1669, 2743, 1669, 3510, 1669, 2708, 2703, 2696, 2675, + 2658, 2630, 2622, 2611, 2597, 2578, 2559, 2550, 2543, 2531, + 2513, 2498, 2482, 2470, 1669, 1669, 1669, 3495, 1669, 3483, + 1669, 3462, 1669, 1669, 3455, 2419, 2408, 1504, 2101, -1000, + 3442, 1669, 3434, 3421, 3414, 2381, 3404, 3394, 3387, 1669, + 1669, 1669, 2377, 3365, 3360, 3356, 3349, 3329, 3318, 3310, + 3302, 3298, 1669, 1622, 1622, 1622, 1622, 1622, 3291, -237, + 1669, 1504, -1000, -1000, -1000, -1000, 3271, 2373, 3252, 3236, + 3198, 3194, 1504, 2193, 887, -1000, -1000, 1622, 1504, 1504, + 1622, 1622, 3112, 3103, 3095, 3090, 3075, 3070, 1669, 1669, + -1000, 1669, 3063, 3054, 2368, 2364, 1504, -1000, 1622, 62976, + -1000, -407, -1000, -1, 983, 2193, -1000, 44519, 1504, -1000, + 7258, -1000, 1419, -1000, -1000, -1000, -1000, -1000, 40674, 2070, + -1000, -1000, -1000, -1000, 494, 530, 287, 494, 298, 297, + 2309, 61438, 61438, 61438, 62976, 1177, -1000, 496, -1000, 2193, + -465, 22931, -1000, -1000, -1000, 853, 116, 39905, 943, 943, + 160, -1000, 1571, 1571, 26031, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 886, 2810, 2810, 486, 2193, -1000, 2120, 3750, + -1000, -1000, -1000, 2730, 31445, -1000, -1000, 2193, 2193, 62976, + 1998, 1985, -1000, 885, -1000, 1488, 2097, 75, 59, -1000, + -1000, -1000, -1000, 1571, -1000, 1519, 422, 1508, -1000, 467, + -1000, -1000, -1000, -1000, 2555, 128, -1000, -1000, -1000, 361, + 853, -1000, -1000, 853, -1000, -1000, -1000, -1000, 1773, -1000, + 1773, -1000, -1000, -1000, -1000, -1000, 1404, -1000, -1000, -1000, + -1000, 1401, -1000, -1000, 1399, -1000, -1000, 2875, 2362, 407, + -1000, -1000, 1055, 1770, -1000, -1000, 2557, 1055, 1055, 61438, + -1000, -1000, 1946, 2686, -1000, 18, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -536, 170, 584, -1000, -1000, -1000, 4728, + 61438, 1897, -1000, 262, -1000, 1902, -1000, 61438, -1000, 1889, + 2265, 61438, 61438, -1000, -1000, -1000, 61438, 2193, -1000, -1000, + -1000, -1000, 789, 2661, 330, -1000, -1000, -266, -1000, -1000, + 283, 262, 62207, 61438, 947, -1000, -1000, -1000, -1000, -1000, + -496, 1887, 528, 62976, 62976, 62976, 62976, 62976, 62976, 873, + -1000, -1000, 79, -1000, -1000, 257, -1000, -1000, 1764, -1000, + -1000, -1000, -1000, 257, -1000, -1000, -1000, -1000, -1000, 349, + 490, -1000, 62976, 62976, 963, -1000, -1000, -1000, -1000, -1000, + -1000, 1134, -1000, -1000, 1134, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2652, 62976, 61, + -462, -1000, -459, 26031, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 1605, 855, 1961, 28356, 28356, 1924, 1924, 28356, -1000, + -1000, -1000, 1365, 1365, 39136, -1000, 28356, 26031, -1000, -1000, + 26031, 26031, 26031, 1122, -1000, 26031, 2068, -1000, 26031, -1000, + -237, 1622, 1669, 1669, 1669, 1669, -237, -237, -237, -237, + -237, -237, -237, -237, -237, -237, 2132, -1000, 26031, 26031, + 26031, 1504, 354, -1000, -1000, -1000, -237, 26031, -1000, -1000, + 2824, -1000, 26031, -1000, 39136, 26031, 26031, 26031, -1000, -1000, + -1000, 26031, 26031, -1000, -1000, 26031, -1000, 26031, -1000, -1000, + -1000, -1000, -1000, -1000, 26031, -1000, 26031, -1000, -1000, -1000, + 26031, -1000, 26031, -1000, -1000, 26031, -1000, 26031, -1000, 26031, + -1000, 26031, -1000, 26031, -1000, 26031, -1000, 26031, -1000, 26031, + -1000, 26031, -1000, 26031, -1000, 26031, -1000, 26031, -1000, 26031, + -1000, 26031, -1000, 26031, -1000, 26031, -1000, 26031, -1000, 26031, + -1000, -1000, -1000, 26031, -1000, 26031, -1000, 26031, -1000, -1000, + 26031, -1000, 26031, -1000, 26031, -1000, 26031, 26031, -1000, 26031, + 26031, 26031, -1000, 26031, 26031, 26031, 26031, -1000, -1000, -1000, + -1000, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, 26031, + 26031, -1000, -1000, -1000, -1000, -1000, -1000, 26031, -1000, 46057, + 98, -237, 1481, 98, 1481, 27581, 899, 854, 26806, -1000, + 26031, 18278, -1000, -1000, -1000, -1000, -1000, 26031, 26031, 26031, + 26031, 26031, 26031, -1000, -1000, -1000, 26031, 26031, -1000, 26031, + -1000, 26031, -1000, -1000, -1000, -1000, -1000, 983, -1000, 861, + 852, 918, 61438, -1000, -1000, -1000, -1000, 2095, -1000, 2744, + -1000, 2502, 2496, 2823, 2810, 26031, -1000, 35291, 62976, 62976, + 294, 62976, 297, 527, 2378, -1000, 2309, 2309, 2309, -1000, + 2682, -1000, 2262, 1466, -1000, -1000, -1000, -1000, -1000, -390, + -1000, 2541, 2500, 943, 943, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 15170, 2745, 26031, 2745, 2374, 62207, 2193, -1000, + 32984, 61438, 62207, 35291, 35291, 35291, 35291, 35291, -1000, 2415, + 2409, -1000, 2428, 2411, 2471, 62976, -1000, 1890, 1871, -1000, + 26031, 37598, 1987, 35291, -1000, -1000, 35291, 62976, 14393, -1000, + -1000, 60, 50, -1000, -1000, -1000, -1000, 2192, -1000, -1000, + 1164, 2709, 2553, -1000, -1000, -1000, -1000, -1000, -1000, 1869, + -1000, 1862, 2078, 1829, 1823, 337, -1000, 2216, 2637, 1055, + 1055, -1000, 1398, -1000, 1483, 1762, 1760, -1000, -1000, -1000, + 477, -1000, -1000, -553, 1395, 2256, 2204, 26031, 2241, 2779, + 2061, 61438, -1000, -1000, 62207, -1000, 278, -1000, 407, 61438, + -1000, -1000, -1000, 414, 62976, -1000, 7780, -1000, -1000, -1000, + 262, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 62976, 2212, + -1000, -1000, -1000, -1000, -1000, 252, 242, 1754, 260, 1753, + -1000, 260, -1000, 62976, 950, 2362, 62976, -1000, -1000, -1000, + 1181, 1181, -1000, -1000, 2635, -1000, 1483, 1669, 28356, 28356, + -1000, 948, -1000, -1000, 386, -210, 2238, 2238, -1000, 2238, + 2239, -1000, 2238, 199, 2238, 197, 2238, -1000, -1000, 1504, + 1504, -1000, 1622, 2332, 2300, 3042, -1000, 1571, 26031, 3024, + -1000, -1000, -237, -237, -237, -237, -237, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -75, 2986, 2880, + 1669, -1000, 2234, 2232, -1000, 1669, 26031, 1669, 1504, 2289, + 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, + 1669, 1669, 2283, 2278, 2228, 2215, 2211, 2203, 2199, 2194, + 2182, 2160, 2108, 2098, 2076, 2064, 2056, 1983, 1669, 1669, + 1914, 1669, 1910, 1821, -1000, 1571, 1622, 2838, 1622, 1669, + 1669, 2721, 249, 1669, 1819, 1819, 1819, 1819, 1819, 1622, + 1622, 1622, 1622, 1669, 61438, -1000, -237, -1000, -1000, -291, + -296, -1000, 1504, -237, 2071, 28356, 1669, 28356, 28356, 28356, + 1669, 1504, -1000, 1793, 1768, 2714, 1719, 1669, 2589, 1669, + 1669, 1669, 1652, -1000, 2737, 2193, 2737, 2193, 2737, 1783, + 1419, 62976, -1000, -1000, -1000, -1000, 2810, 2796, -1000, 2067, + 2193, -1000, -1000, -1000, -1000, -1000, 516, 62976, 62976, 2369, + 2366, 2358, -1000, 1898, -1000, -1000, 116, 615, -1000, 2515, + 2500, -1000, 2775, 2529, 2774, -1000, -1000, -1000, -1000, -1000, + 1571, -1000, -1000, 2667, 1979, -1000, 1075, 2093, -1000, -1000, + 22931, 1791, 2472, 883, 1783, 2114, 3750, 2314, 2356, 3771, + -1000, -1000, -1000, -1000, 2401, -1000, 2400, -1000, -1000, 2219, + -1000, 2568, 421, 35291, 2112, 2112, -1000, 877, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 1250, 7780, 2865, -1000, 1686, + -1000, 1515, 256, 1393, -1000, -1000, 1055, 1055, -1000, 1194, + 1193, -1000, 62976, 2227, -1000, 853, 1684, 853, 1388, -1000, + -1000, 1381, -1000, -1000, -1000, -1000, 2153, 2393, -1000, -1000, + -1000, -1000, 299, 2226, 2773, -1000, 26031, 2223, 1059, 2753, + 61438, 61438, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 829, 1055, -491, 382, 371, 1055, 1055, + 1055, -554, -1000, -1000, 1780, 1759, -1000, -198, -1000, 26031, + -1000, -1000, -1000, -1000, -1000, 1344, 1344, 1666, 1653, 1640, + -1000, 2219, -187, 61438, 61438, 61438, 61438, -1000, -1000, -1000, + 1353, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 948, 1504, 413, -191, 1504, -1000, -1000, + 853, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 26031, -1000, 26031, -1000, 26031, 1571, 26031, -1000, -1000, + -1000, -1000, -1000, 2745, 1638, 26031, 26031, -1000, 1378, 1377, + -237, 1669, -1000, -1000, -1000, 26031, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 26031, + -1000, 26031, -1000, 26031, -1000, 26031, -1000, 26031, -1000, 26031, + -1000, 26031, -1000, 26031, -1000, 26031, -1000, 26031, -1000, 26031, + -1000, 26031, -1000, 26031, -1000, 26031, -1000, 26031, -1000, 26031, + -1000, -1000, 26031, -1000, -1000, -1000, 26031, -1000, 26031, -1000, + 26031, -1000, -1000, -1000, 26031, 285, 1365, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1504, 419, + -1000, -1000, -1000, 2815, -1000, 1504, 26031, 1924, -1000, 1924, + 1924, 1924, -1000, -1000, -1000, 26031, -1000, 26031, 26031, -1000, + 26031, -1000, 26031, -1000, -1000, -1000, -1000, 26031, 2193, 2570, + 45288, 2193, 45288, 2193, 37598, -1000, -1000, 2796, 2794, 2768, + 268, 62976, -1000, -1000, 62976, 62976, 62976, -1000, 2514, 2519, + 2519, 2515, -1000, 2766, 2765, -1000, 1633, 2761, 1627, 1184, + -1000, 62207, 26031, -1000, 2193, 44519, -1000, 491, 61438, 2193, + 61438, -1000, 2790, -1000, -1000, 26031, 2214, -1000, 26031, -1000, + -1000, -1000, -1000, 8698, 2810, 2112, -1000, -1000, 958, -1000, + 26031, -1000, 12602, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 1614, 1586, -1000, -1000, 2208, 26031, -1000, -1000, + -1000, 1872, 1794, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 414, -547, 2748, 61438, 1373, -1000, 1736, + 2061, 357, 2193, 1559, 1055, 1055, 1055, 1372, 1371, 44519, + 1732, -1000, 61438, 459, -1000, 414, -1000, -204, -205, 1669, + -1000, -1000, 2707, -1000, 18278, -1000, -1000, 2206, 2237, -1000, + -1000, -1000, -1000, 2444, -181, -194, -1000, -1000, 1669, 1669, + 1669, 2339, 1504, -1000, 1669, 1669, 1769, 1752, -1000, -1000, + 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, + 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, 1669, + 1622, 1625, -1000, 285, 1504, 2347, -1000, -1000, 8698, -1000, + -1000, 2790, 2759, 98, -1000, -1000, 280, 98, 1571, 1049, + 1504, 1504, 1049, 1590, 1669, 1467, 1447, 1669, 1669, 38367, + -1000, 2756, 2751, 1721, -1000, -1000, 45288, 1721, 45288, 983, + 2794, -245, 26031, 26031, 1504, 2062, -1000, 61438, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 2509, 1303, -1000, -1000, -1000, + -1000, 1550, 1536, -1000, 1526, -1000, 2864, -1000, 1571, -1000, + 2193, 2193, -1000, 844, 2093, -1000, 2745, 1571, 61438, 1571, + 113, 2790, -1000, 1669, -1000, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, 2193, + 2193, 2193, 2193, 2193, 2193, 2193, -1000, -1000, 61438, 2402, + -1000, -1000, 1723, 169, -1000, 1670, 2061, -1000, -1000, 714, + -1000, 26031, -1000, 44519, 1518, 1512, -1000, -1000, -1000, -1000, + -554, -1000, -1000, -1000, -1000, -1000, -1000, 488, 1995, -1000, + 1054, 61438, 62976, -1000, 2425, -1000, -1000, -1000, -1000, 26031, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -76, 2860, 2615, 1290, -1000, 2228, 2227, -1000, 1290, 24712, - 1290, 1484, 2308, 1290, 1290, 1290, 1290, 1290, 1290, 1290, - 1290, 1290, 1290, 1290, 1290, 2304, 2300, 2273, 2263, 2233, - 2211, 2202, 2194, 2189, 2157, 2149, 2141, 2127, 2096, 2087, - 2052, 1290, 1290, 2043, 1290, 1959, 1925, -1000, 1210, 1718, - 2610, 1718, 1290, 1290, 2601, 272, 1290, 1932, 1932, 1932, - 1932, 1932, 1718, 1718, 1718, 1718, 1290, 60119, -1000, -278, - -1000, -1000, -321, -336, -1000, 1484, -278, 2067, 27037, 1290, - 27037, 27037, 27037, 1290, 1484, -1000, 1921, 1908, 2428, 1904, - 1290, 2219, 1290, 1290, 1290, 1888, -1000, 2655, 2184, 2655, - 2184, 2655, 1918, 1456, 61657, -1000, -1000, -1000, -1000, 2748, - 2744, -1000, 2065, 2184, -1000, -1000, -1000, -1000, -1000, 487, - 61657, 61657, 2340, 2339, 2338, -1000, 1824, -1000, -1000, 129, - 620, -1000, 2461, 2440, -1000, 2719, 2471, 2718, -1000, -1000, - -1000, -1000, -1000, 1210, -1000, 2591, 2058, -1000, 1017, 2136, - -1000, -1000, 23162, 1930, 2427, 841, 1918, 2113, 3291, 2309, - 2337, 3731, -1000, -1000, -1000, -1000, 2370, -1000, 2366, -1000, - -1000, 2216, -1000, 2114, 369, 33972, 2034, 2034, -1000, 833, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1216, 9649, 2797, - -1000, 1728, -1000, 1488, 261, 1332, -1000, -1000, 1008, 1008, - -1000, 1094, 1091, -1000, 61657, 2226, -1000, 912, 1726, 912, - 1329, -1000, -1000, 1324, -1000, -1000, -1000, -1000, 2242, 2424, - -1000, -1000, -1000, -1000, 309, 2224, 2714, -1000, 24712, 2222, - 1012, 2016, 60119, 60119, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 486, 1008, -492, 335, 334, - 1008, 1008, 1008, -550, -1000, -1000, 1916, 1910, -1000, -234, - -1000, 24712, -1000, -1000, -1000, -1000, -1000, 1315, 1315, 1723, - 1713, 1703, -1000, 2216, -205, 60119, 60119, 60119, 60119, -1000, - -1000, -1000, 1269, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 934, 1484, 378, -209, 1484, - -1000, -1000, 912, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 24712, -1000, 24712, -1000, 24712, 1210, 24712, - -1000, -1000, -1000, -1000, -1000, 2627, 1690, 24712, 24712, -1000, - 1311, 1310, -278, 1290, -1000, -1000, -1000, 24712, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 24712, -1000, 24712, -1000, 24712, -1000, 24712, -1000, 24712, - -1000, 24712, -1000, 24712, -1000, 24712, -1000, 24712, -1000, 24712, - -1000, 24712, -1000, 24712, -1000, 24712, -1000, 24712, -1000, 24712, - -1000, 24712, -1000, -1000, 24712, -1000, -1000, -1000, 24712, -1000, - 24712, -1000, 24712, -1000, -1000, -1000, 24712, 257, 1068, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 1484, 368, -1000, -1000, -1000, 2751, -1000, 1484, 24712, 2661, - -1000, 2661, 2661, 2661, -1000, -1000, -1000, 24712, -1000, 24712, - 24712, -1000, 24712, -1000, 24712, -1000, -1000, -1000, -1000, 24712, - 2184, 2479, 43969, 2184, 43969, 2184, 36279, -1000, -1000, 2744, - 2734, 2699, 249, 61657, -1000, -1000, 61657, 61657, 61657, -1000, - 2456, 2465, 2465, 2461, -1000, 2698, 2687, -1000, 1681, 2686, - 1677, 1086, -1000, 60888, 24712, -1000, 2184, 43200, -1000, 476, - 60119, 2184, 60119, -1000, 2711, -1000, -1000, 24712, 2206, -1000, - 24712, -1000, -1000, -1000, -1000, 6546, 2748, 2034, -1000, -1000, - 948, -1000, 24712, -1000, 12151, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 1658, 1650, -1000, -1000, 2205, 24712, - -1000, -1000, -1000, 1776, 1639, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 364, -548, 1894, 60119, 1286, - -1000, 1866, 2055, 356, 2184, 1644, 1008, 1008, 1008, 1280, - 1278, 43200, 1856, -1000, 60119, 421, -1000, 364, -1000, -247, - -248, 1290, -1000, -1000, 2625, -1000, 18509, -1000, -1000, 2197, - 2301, -1000, -1000, -1000, -1000, 2403, -197, -218, -1000, -1000, - 1290, 1290, 1290, 1731, 1484, -1000, 1290, 1290, 1636, 1628, - -1000, -1000, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, - 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, 1290, - 1290, 1290, 1718, 1841, -1000, 257, 1484, 2336, -1000, -1000, - 6546, -1000, -1000, 2711, 2681, 54, -1000, -1000, 287, 54, - 1210, 1041, 1484, 1484, 1041, 1837, 1290, 1823, 1722, 1290, - 1290, 37048, -1000, 2676, 2672, 1835, -1000, -1000, 43969, 1835, - 43969, 1025, 2734, -289, 24712, 24712, 1484, 2063, -1000, 60119, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2448, 1296, -1000, - -1000, -1000, -1000, 1608, 1589, -1000, 1537, -1000, 2790, -1000, - 1210, -1000, 2184, 2184, -1000, 768, 2136, -1000, 2627, 1210, - 60119, 1210, 73, 2711, -1000, 1290, -1000, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, - 2184, 2184, 2184, 2184, 2184, 2184, 2184, 2184, -1000, -1000, - 60119, 1712, -1000, -1000, 1839, 160, -1000, 1490, 2055, -1000, - -1000, 719, -1000, 24712, -1000, 43200, 1522, 1511, -1000, -1000, - -1000, -1000, -550, -1000, -1000, -1000, -1000, -1000, -1000, 474, - 2054, -1000, 1002, 60119, 61657, -1000, 2394, -1000, -1000, -1000, - -1000, 24712, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 24712, - -1000, 1484, 2335, -1000, -348, -1000, -509, 24712, -278, -1000, - -1000, -278, -1000, -1000, -1000, -1000, -1000, 24712, -1000, -1000, - 24712, -1000, 24712, -1000, -1000, 1835, -1000, -1000, -1000, 42431, - -1000, 1835, -1000, 1835, -1000, -289, -1000, 2048, -1000, 60119, - 1210, 354, 8032, 249, 5383, -1000, 1283, -1000, -1000, -1000, - -1000, -1000, 60888, 60119, 2136, 60119, -1000, -1000, 1803, 1484, - 2184, 2627, -1000, 1775, -1000, -1000, 2192, 2199, -1000, -1000, - -1000, 22387, -1000, -1000, -1000, -1000, -1000, 279, -200, 18509, - 13847, 1752, -1000, -203, 1290, 1718, -1000, -459, -1000, -1000, - -1000, -1000, 297, -1000, -1000, 2014, -1000, -1000, 1649, 1638, - 1634, -1000, -1000, -1000, -1000, -1000, -1000, -289, -1000, -1000, - 2624, -1000, -250, -1000, -567, -1000, -1000, 8032, 24712, 33203, - 41662, -1000, -1000, -1000, -1000, 1499, 1688, -1000, -1000, -1000, - 36279, 59350, -1000, -179, 322, 24712, 2186, 1484, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 571, -1000, - -1000, -1000, 2198, -216, -1000, -1000, -1000, 5852, -477, -319, - -320, 27037, -1000, 24712, -1000, 24712, -1000, 24712, -1000, 60119, - 2184, -1000, -1000, 1048, 8032, -1000, -567, 1400, 4501, 540, - 508, -1000, -1000, -1000, 2569, -1000, -1000, 2415, -1000, -1000, - -1000, 1625, -1000, 2942, -360, 2332, -1000, -95, -1000, -1000, - -1000, 1142, 1508, -1000, 1274, -1000, -1000, -1000, -1000, 1627, - 60119, -1000, 17732, -205, -225, 1085, -1000, -1000, -1000, -1000, - -1000, 2661, 1449, 1444, 1290, -1000, 60119, -1000, -1000, 8032, - 2517, 2641, 2639, -1000, 118, 118, 1493, -1000, -1000, 59350, - -354, 933, 6546, -1000, 2326, 2318, 2770, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -556, 1621, -1000, -1000, -1000, 5852, - -325, -1000, 24712, -1000, 24712, -1000, 1484, 6867, -1000, 9649, - 30895, 960, -1000, 993, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 2607, 73, -1000, 2780, -1000, 2764, 998, 998, -1000, 1273, - -556, -1000, -1000, -1000, 1290, 1290, -1000, 1059, 1053, -1000, - 24712, 24712, -1000, 6389, -1000, -1000, -1000, -1000, 542, -1000, - -1000, -1000, -1000, 8895, -362, -1000, -1000, -1000, -1000, -1000, - 428, 1314, -1000, -1000, -1000, -1000, -1000, 1010, 8032, -1000, - 1026, 1290, -1000, 30895, -1000, -1000, 6546, -1000, -1000, -1000, - 458, 8032, 8032, -1000, -1000, 251, -1000, 8032, 251, -1000, - -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 26031, -1000, 1504, + 2345, -1000, -340, -1000, -484, 26031, -237, -1000, -1000, -237, + -1000, -1000, -1000, -1000, -1000, 26031, -1000, -1000, 26031, -1000, + 26031, -1000, -1000, 1721, -1000, -1000, -1000, 43750, -1000, 1721, + -1000, 1721, -1000, -245, -1000, 1972, -1000, 61438, 1571, 352, + 6007, 268, 7049, -1000, 1296, -1000, -1000, -1000, -1000, -1000, + 62207, 61438, 2093, 61438, -1000, -1000, 1716, 1504, 2193, 2745, + -1000, 1679, -1000, -1000, 2198, 2204, -1000, -1000, -1000, 22156, + -1000, -1000, -1000, -1000, -1000, 273, -185, 18278, 13616, 1658, + -1000, -186, 1669, 1622, -1000, -449, -1000, -1000, -1000, -1000, + 254, -1000, -1000, 1953, -1000, -1000, 1415, 1400, 1346, -1000, + -1000, -1000, -1000, -1000, -1000, -245, -1000, -1000, 2704, -1000, + -207, -1000, -560, -1000, -1000, 6007, 26031, 34522, 42981, -1000, + -1000, -1000, -1000, 1592, 1564, -1000, -1000, -1000, 37598, 60669, + -1000, -176, 448, 26031, 2197, 1504, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 842, -1000, -1000, -1000, + 2212, -192, -1000, -1000, -1000, 4452, -468, -288, -290, 28356, + -1000, 26031, -1000, 26031, -1000, 26031, -1000, 61438, 2193, -1000, + -1000, 1066, 6007, -1000, -560, 1647, 2943, 820, 802, -1000, + -1000, -1000, 2654, -1000, -1000, 2430, -1000, -1000, -1000, 1555, + -1000, 4527, -312, 2321, -1000, -67, -1000, -1000, -1000, 1239, + 1500, -1000, 1357, -1000, -1000, -1000, -1000, 2043, 61438, -1000, + 17501, -187, -195, 1151, -1000, -1000, -1000, -1000, -1000, 1924, + 1301, 1173, 1669, -1000, 61438, -1000, -1000, 6007, 2657, 2735, + 2710, -1000, 174, 174, 1495, -1000, -1000, 60669, -303, 947, + 8698, -1000, 2319, 2318, 2818, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -556, 1531, -1000, -1000, -1000, 4452, -293, -1000, + 26031, -1000, 26031, -1000, 1504, 5292, -1000, 7780, 32214, 966, + -1000, 1037, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2680, 113, + -1000, 2850, -1000, 2819, 969, 969, -1000, 1354, -556, -1000, + -1000, -1000, 1669, 1669, -1000, 1135, 1131, -1000, 26031, 26031, + -1000, 1141, -1000, -1000, -1000, -1000, 824, -1000, -1000, -1000, + -1000, 8259, -314, -1000, -1000, -1000, -1000, -1000, 466, 1345, + -1000, -1000, -1000, -1000, -1000, 1050, 6007, -1000, 1032, 1669, + -1000, 32214, -1000, -1000, 8698, -1000, -1000, -1000, 489, 6007, + 6007, -1000, -1000, 296, -1000, 6007, 296, -1000, -1000, } var yyPgo = [...]int{ - 0, 3462, 3461, 41, 8, 60, 59, 3460, 2851, 3458, - 3456, 2828, 3455, 202, 3452, 3450, 3446, 3444, 3440, 3437, - 204, 203, 199, 3432, 3430, 3429, 3428, 3425, 3423, 3422, - 3417, 3411, 45, 107, 62, 117, 217, 226, 3404, 3402, - 42, 186, 216, 3399, 3398, 3397, 3396, 3395, 130, 213, - 99, 101, 214, 3390, 3386, 90, 3384, 3383, 3381, 3379, - 3378, 19, 18, 36, 33, 3374, 3370, 3363, 26, 3361, - 209, 205, 201, 1113, 3358, 208, 126, 52, 3357, 3356, - 3349, 3347, 12, 10, 3345, 11, 3343, 6, 3342, 3337, - 3331, 3330, 3320, 3318, 3303, 3293, 3292, 3290, 3287, 3285, - 3283, 3282, 3281, 3280, 3279, 297, 3277, 3276, 47, 3275, - 94, 3274, 3273, 3272, 3264, 3261, 20, 3259, 3258, 28, - 48, 75, 3257, 3256, 49, 3251, 3250, 3248, 3245, 3241, - 32, 3239, 39, 3238, 80, 3237, 3236, 136, 3228, 3226, - 3224, 57, 3223, 3218, 3217, 27, 193, 3216, 3213, 161, - 3212, 3211, 3209, 190, 221, 3207, 2426, 3206, 121, 3204, - 3201, 3198, 188, 187, 223, 3196, 115, 3194, 3193, 3192, - 3186, 145, 3185, 3184, 4599, 3178, 3177, 16, 21, 140, - 3176, 3175, 166, 14, 77, 3172, 9, 4, 3167, 3164, - 17, 88, 3143, 113, 3140, 3138, 116, 78, 3137, 108, - 111, 3136, 3134, 25, 15, 3132, 1, 3, 2, 81, - 3130, 3129, 124, 3127, 3125, 3124, 106, 3123, 3120, 4579, - 3119, 102, 146, 112, 92, 3117, 183, 72, 3116, 3115, - 3112, 3110, 3103, 3093, 63, 3092, 3090, 3089, 158, 191, - 118, 3087, 3086, 149, 366, 144, 64, 148, 3082, 173, - 3079, 147, 96, 3076, 194, 3071, 3068, 154, 156, 3067, - 3059, 71, 181, 206, 3044, 110, 141, 128, 143, 104, - 160, 3043, 3040, 3039, 73, 85, 3037, 3036, 3035, 3032, - 195, 3031, 3030, 83, 3028, 70, 3027, 192, 3025, 330, - 76, 3023, 189, 178, 3022, 86, 185, 3017, 3009, 3008, - 82, 133, 84, 69, 3001, 175, 182, 137, 179, 2999, - 2998, 66, 2997, 2986, 2985, 215, 336, 2983, 2981, 291, - 196, 163, 150, 100, 2980, 222, 2979, 2978, 2977, 29, - 5792, 8106, 211, 44, 184, 2974, 2972, 9925, 30, 46, - 43, 2971, 219, 2969, 142, 2968, 2966, 2965, 218, 224, - 120, 180, 74, 2964, 2963, 2961, 2960, 37, 2958, 2954, - 2953, 2951, 2950, 2949, 58, 56, 55, 89, 237, 79, - 24, 109, 177, 172, 87, 2948, 2944, 2943, 134, 103, - 2935, 174, 171, 138, 132, 2931, 198, 164, 127, 2927, - 65, 54, 2924, 2923, 2914, 2912, 105, 2909, 2908, 2907, - 2906, 169, 165, 131, 97, 2904, 98, 122, 170, 168, - 61, 2902, 50, 2901, 2900, 53, 212, 68, 2899, 2888, - 2887, 40, 2886, 31, 119, 125, 2885, 7762, 2883, 34, - 283, 167, 2882, 2881, 13, 23, 22, 2878, 2877, 2875, - 2872, 152, 2871, 2866, 2864, 2860, 38, 51, 35, 7, - 123, 159, 95, 2857, 2854, 162, 2852, 2827, 0, 1830, - 139, 2815, 227, + 0, 3563, 3561, 41, 9, 58, 57, 3560, 2889, 3553, + 3552, 2884, 3551, 197, 3547, 3545, 3544, 3540, 3536, 3535, + 204, 199, 198, 3533, 3532, 3531, 3530, 3528, 3526, 3525, + 3524, 3518, 47, 107, 74, 125, 223, 265, 3513, 3506, + 45, 179, 214, 3505, 3502, 3500, 3498, 3497, 127, 211, + 97, 99, 212, 3495, 3494, 88, 3490, 3486, 3485, 3479, + 3478, 12, 19, 36, 33, 3477, 3474, 3471, 25, 3468, + 210, 208, 206, 1138, 3467, 209, 124, 51, 3466, 3463, + 3458, 3448, 13, 10, 3447, 11, 3438, 6, 3436, 3435, + 3433, 3431, 3427, 3420, 3416, 3415, 3412, 3410, 3409, 3408, + 3402, 3395, 3383, 3382, 3380, 225, 3379, 3378, 46, 3377, + 90, 3375, 3374, 3371, 3370, 3369, 22, 3368, 3365, 27, + 147, 70, 3362, 3360, 49, 3359, 3358, 3357, 3356, 3355, + 28, 3351, 39, 3343, 101, 3338, 3332, 132, 3321, 3319, + 3304, 42, 3295, 3294, 3292, 30, 190, 3288, 3287, 159, + 3286, 3285, 3283, 189, 216, 3279, 2465, 3272, 113, 3271, + 3270, 3269, 187, 183, 220, 3265, 109, 3263, 3262, 3261, + 3259, 143, 3254, 3252, 4183, 3251, 3246, 17, 20, 140, + 3243, 3240, 166, 14, 75, 3239, 7, 8, 3238, 3228, + 18, 87, 3223, 111, 3219, 3214, 110, 80, 3213, 105, + 112, 3211, 3210, 26, 16, 3203, 1, 3, 2, 77, + 3200, 3199, 121, 3195, 3193, 3192, 104, 3191, 3187, 5254, + 3184, 102, 157, 115, 84, 3182, 184, 86, 3181, 3180, + 3177, 3175, 3172, 3171, 63, 3169, 3167, 3166, 156, 273, + 120, 3163, 3162, 149, 355, 144, 64, 145, 3161, 172, + 3160, 146, 92, 3159, 191, 3157, 3156, 152, 151, 3155, + 3150, 67, 182, 207, 3148, 106, 136, 128, 141, 103, + 155, 3145, 3143, 3142, 68, 82, 3132, 3131, 3126, 3124, + 193, 3123, 3122, 81, 3121, 66, 3118, 186, 3117, 331, + 71, 3106, 192, 175, 3103, 83, 180, 3100, 3096, 3095, + 76, 123, 78, 59, 3093, 178, 185, 133, 201, 3092, + 3090, 65, 3089, 3086, 3085, 213, 350, 3084, 3080, 297, + 195, 161, 148, 98, 3079, 215, 3078, 3076, 3067, 29, + 6093, 8449, 203, 40, 177, 3066, 3064, 9686, 31, 50, + 43, 3063, 219, 3061, 142, 3060, 3057, 3047, 217, 224, + 118, 181, 69, 3046, 3045, 3044, 3042, 37, 3041, 3040, + 3037, 3033, 3026, 3025, 56, 55, 54, 137, 243, 73, + 23, 108, 176, 170, 85, 3024, 3020, 3019, 131, 96, + 3018, 174, 173, 139, 119, 3015, 196, 162, 126, 3013, + 62, 53, 3012, 3003, 3002, 3000, 100, 2999, 2988, 2987, + 2986, 169, 163, 130, 94, 2985, 95, 116, 164, 168, + 60, 2984, 61, 2983, 2980, 48, 205, 72, 2973, 2972, + 2969, 44, 2963, 32, 117, 134, 2962, 7569, 2961, 34, + 238, 171, 2945, 2941, 15, 21, 24, 2940, 2939, 2938, + 2935, 154, 2929, 2925, 2920, 2918, 38, 52, 35, 4, + 122, 158, 89, 2917, 2913, 160, 2911, 2909, 0, 1835, + 135, 2906, 221, } -//line sql.y:9280 +//line sql.y:9288 type yySymType struct { union any empty struct{} @@ -9341,117 +9473,117 @@ var yyR1 = [...]int{ 39, 39, 42, 42, 41, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 32, 32, 32, 32, 33, 33, 33, 33, 33, - 38, 38, 18, 19, 37, 37, 37, 20, 20, 135, - 135, 21, 22, 22, 22, 22, 460, 460, 214, 214, - 212, 212, 213, 213, 300, 300, 23, 304, 304, 306, - 306, 306, 306, 294, 294, 294, 24, 24, 305, 305, - 307, 307, 307, 310, 310, 310, 310, 351, 351, 351, - 25, 25, 25, 25, 25, 25, 155, 429, 429, 428, - 423, 423, 422, 422, 421, 426, 426, 425, 425, 424, - 45, 44, 46, 46, 46, 47, 56, 56, 56, 56, - 57, 58, 430, 430, 392, 74, 74, 73, 73, 73, - 73, 73, 73, 75, 75, 71, 71, 70, 70, 72, - 72, 394, 394, 380, 380, 393, 393, 393, 393, 393, - 393, 393, 379, 379, 167, 167, 271, 271, 271, 271, + 38, 38, 18, 18, 19, 19, 37, 37, 37, 20, + 20, 135, 135, 21, 22, 22, 22, 22, 460, 460, + 214, 214, 212, 212, 213, 213, 300, 300, 23, 304, + 304, 306, 306, 306, 306, 294, 294, 294, 24, 24, + 305, 305, 307, 307, 307, 310, 310, 310, 310, 351, + 351, 351, 25, 25, 25, 25, 25, 25, 155, 429, + 429, 428, 423, 423, 422, 422, 421, 426, 426, 425, + 425, 424, 45, 44, 46, 46, 46, 47, 56, 56, + 56, 56, 57, 58, 430, 430, 392, 74, 74, 73, + 73, 73, 73, 73, 73, 75, 75, 71, 71, 70, + 70, 72, 72, 394, 394, 380, 380, 393, 393, 393, + 393, 393, 393, 393, 379, 379, 167, 167, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, - 271, 271, 271, 445, 445, 445, 445, 444, 444, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 178, 178, - 190, 190, 190, 190, 190, 190, 176, 176, 177, 175, - 175, 175, 183, 183, 183, 183, 183, 183, 183, 183, - 183, 183, 183, 183, 183, 183, 183, 183, 449, 449, + 271, 271, 271, 271, 271, 445, 445, 445, 445, 444, + 444, 272, 272, 272, 272, 272, 272, 272, 272, 272, + 178, 178, 190, 190, 190, 190, 190, 190, 176, 176, + 177, 175, 175, 175, 183, 183, 183, 183, 183, 183, + 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, - 189, 189, 184, 184, 184, 186, 186, 185, 185, 185, - 187, 187, 446, 446, 446, 446, 357, 357, 357, 357, - 360, 360, 358, 358, 358, 358, 358, 358, 358, 358, - 358, 359, 359, 359, 359, 359, 359, 359, 361, 361, - 361, 361, 361, 362, 362, 362, 362, 362, 362, 362, + 449, 449, 189, 189, 184, 184, 184, 186, 186, 185, + 185, 185, 187, 187, 446, 446, 446, 446, 357, 357, + 357, 357, 360, 360, 358, 358, 358, 358, 358, 358, + 358, 358, 358, 359, 359, 359, 359, 359, 359, 359, + 361, 361, 361, 361, 361, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, - 363, 363, 363, 363, 363, 363, 363, 363, 378, 378, - 367, 367, 372, 372, 373, 373, 374, 374, 374, 375, - 375, 375, 376, 376, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 371, 371, 370, 370, 370, 381, 406, - 406, 405, 405, 403, 403, 403, 403, 403, 403, 403, - 403, 390, 390, 400, 400, 400, 400, 400, 389, 389, - 385, 385, 385, 386, 386, 387, 387, 384, 384, 388, - 388, 402, 402, 401, 401, 382, 382, 383, 383, 408, - 447, 447, 447, 447, 447, 448, 448, 409, 437, 439, - 439, 439, 438, 438, 435, 436, 434, 434, 434, 434, - 434, 110, 110, 110, 323, 323, 324, 324, 398, 398, - 397, 397, 397, 399, 399, 396, 396, 396, 396, 396, + 362, 362, 363, 363, 363, 363, 363, 363, 363, 363, + 378, 378, 367, 367, 372, 372, 373, 373, 374, 374, + 374, 375, 375, 375, 376, 376, 369, 369, 369, 369, + 369, 369, 369, 369, 369, 371, 371, 370, 370, 370, + 381, 406, 406, 405, 405, 403, 403, 403, 403, 403, + 403, 403, 403, 390, 390, 400, 400, 400, 400, 400, + 389, 389, 385, 385, 385, 386, 386, 387, 387, 384, + 384, 388, 388, 402, 402, 401, 401, 382, 382, 383, + 383, 408, 447, 447, 447, 447, 447, 448, 448, 409, + 437, 439, 439, 439, 438, 438, 435, 436, 434, 434, + 434, 434, 434, 110, 110, 110, 323, 323, 324, 324, + 398, 398, 397, 397, 397, 399, 399, 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, 318, 318, 318, 433, - 433, 433, 433, 433, 433, 432, 432, 432, 395, 395, - 395, 395, 431, 431, 76, 76, 252, 252, 450, 450, - 452, 452, 452, 53, 53, 53, 53, 53, 53, 52, - 52, 52, 48, 48, 48, 48, 48, 48, 48, 48, + 396, 396, 396, 396, 396, 396, 396, 396, 318, 318, + 318, 433, 433, 433, 433, 433, 433, 432, 432, 432, + 395, 395, 395, 395, 431, 431, 76, 76, 252, 252, + 450, 450, 452, 452, 452, 53, 53, 53, 53, 53, + 53, 52, 52, 52, 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, 54, 54, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 26, 26, 26, 26, 26, + 48, 48, 48, 48, 48, 54, 54, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 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, 137, - 137, 138, 138, 138, 138, 140, 140, 140, 411, 411, - 77, 77, 3, 3, 202, 204, 205, 205, 203, 203, - 203, 203, 203, 203, 79, 79, 78, 78, 207, 206, - 208, 208, 208, 1, 1, 2, 2, 4, 4, 416, - 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 137, 137, 138, 138, 138, 138, 140, 140, 140, + 411, 411, 77, 77, 3, 3, 202, 204, 205, 205, + 203, 203, 203, 203, 203, 203, 79, 79, 78, 78, + 207, 206, 208, 208, 208, 1, 1, 2, 2, 4, + 4, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, - 416, 377, 377, 377, 410, 410, 412, 139, 139, 139, - 139, 139, 139, 139, 139, 139, 139, 143, 142, 142, - 141, 144, 144, 144, 144, 144, 144, 144, 144, 414, - 414, 414, 80, 80, 415, 364, 365, 366, 5, 6, - 391, 413, 151, 151, 27, 43, 43, 28, 28, 28, - 28, 28, 29, 29, 90, 93, 93, 91, 91, 91, + 416, 416, 416, 377, 377, 377, 410, 410, 412, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 143, + 142, 142, 141, 144, 144, 144, 144, 144, 144, 144, + 144, 414, 414, 414, 80, 80, 415, 364, 365, 366, + 5, 6, 391, 413, 151, 151, 27, 43, 43, 28, + 28, 28, 28, 28, 29, 29, 90, 93, 93, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, - 91, 91, 91, 328, 328, 317, 317, 326, 326, 316, - 316, 342, 342, 342, 319, 319, 319, 320, 320, 443, - 443, 443, 313, 313, 92, 92, 92, 343, 343, 343, - 343, 95, 95, 453, 453, 454, 454, 455, 455, 455, - 96, 97, 97, 346, 346, 347, 347, 98, 99, 111, - 111, 111, 111, 111, 112, 112, 112, 112, 112, 112, - 136, 136, 136, 13, 13, 13, 13, 107, 107, 107, - 12, 12, 14, 94, 94, 101, 440, 440, 441, 442, - 442, 442, 442, 102, 104, 30, 30, 30, 30, 30, - 30, 161, 161, 149, 149, 149, 149, 149, 149, 149, - 149, 149, 149, 149, 149, 156, 156, 156, 150, 150, - 461, 105, 106, 106, 154, 154, 154, 147, 147, 147, - 153, 153, 153, 15, 15, 16, 298, 298, 17, 17, - 160, 160, 159, 159, 162, 162, 162, 162, 162, 162, - 162, 162, 162, 162, 162, 157, 157, 158, 158, 158, - 158, 335, 335, 335, 334, 334, 196, 196, 198, 197, - 197, 199, 199, 200, 200, 200, 200, 250, 250, 222, - 222, 290, 290, 291, 291, 289, 289, 297, 297, 292, - 292, 292, 292, 301, 301, 201, 201, 201, 201, 209, - 209, 210, 210, 211, 211, 345, 345, 340, 340, 340, - 339, 339, 215, 215, 215, 217, 216, 216, 216, 216, - 218, 218, 220, 220, 219, 219, 221, 226, 226, 225, - 225, 223, 223, 223, 223, 223, 223, 224, 224, 224, - 224, 227, 227, 174, 174, 174, 174, 174, 174, 174, - 174, 451, 451, 188, 188, 188, 188, 188, 188, 188, - 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, - 191, 280, 280, 179, 179, 179, 179, 179, 179, 179, - 179, 179, 179, 179, 179, 179, 179, 179, 182, 182, + 91, 91, 91, 91, 91, 328, 328, 317, 317, 326, + 326, 316, 316, 342, 342, 342, 319, 319, 319, 320, + 320, 443, 443, 443, 313, 313, 92, 92, 92, 343, + 343, 343, 343, 95, 95, 453, 453, 454, 454, 455, + 455, 455, 96, 97, 97, 346, 346, 347, 347, 98, + 99, 111, 111, 111, 111, 111, 112, 112, 112, 112, + 112, 112, 136, 136, 136, 13, 13, 13, 13, 107, + 107, 107, 12, 12, 14, 94, 94, 101, 440, 440, + 441, 442, 442, 442, 442, 102, 104, 30, 30, 30, + 30, 30, 30, 161, 161, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 156, 156, 156, + 150, 150, 461, 105, 106, 106, 154, 154, 154, 147, + 147, 147, 153, 153, 153, 15, 15, 16, 298, 298, + 17, 17, 160, 160, 159, 159, 162, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 162, 157, 157, 157, + 158, 158, 158, 335, 335, 335, 334, 334, 196, 196, + 198, 197, 197, 199, 199, 200, 200, 200, 200, 250, + 250, 222, 222, 290, 290, 291, 291, 289, 289, 297, + 297, 292, 292, 292, 292, 301, 301, 201, 201, 201, + 201, 209, 209, 210, 210, 211, 211, 345, 345, 340, + 340, 340, 339, 339, 215, 215, 215, 217, 216, 216, + 216, 216, 218, 218, 220, 220, 219, 219, 221, 226, + 226, 225, 225, 223, 223, 223, 223, 223, 223, 224, + 224, 224, 224, 227, 227, 174, 174, 174, 174, 174, + 174, 174, 174, 451, 451, 188, 188, 188, 188, 188, + 188, 188, 191, 191, 191, 191, 191, 191, 191, 191, + 191, 191, 191, 280, 280, 179, 179, 179, 179, 179, + 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, - 182, 182, 182, 255, 255, 254, 254, 113, 113, 113, - 114, 114, 115, 115, 115, 115, 115, 116, 116, 116, - 116, 116, 116, 116, 118, 118, 117, 117, 241, 241, - 332, 332, 119, 120, 120, 121, 121, 124, 124, 123, - 122, 122, 128, 128, 125, 125, 127, 127, 126, 129, - 129, 130, 131, 131, 314, 314, 228, 228, 237, 237, - 237, 237, 229, 229, 230, 230, 230, 230, 230, 230, - 238, 238, 238, 249, 239, 239, 235, 235, 233, 233, - 233, 233, 233, 233, 233, 233, 233, 233, 233, 234, - 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, + 182, 182, 182, 182, 182, 255, 255, 254, 254, 113, + 113, 113, 114, 114, 115, 115, 115, 115, 115, 116, + 116, 116, 116, 116, 116, 116, 118, 118, 117, 117, + 241, 241, 332, 332, 119, 120, 120, 121, 121, 124, + 124, 123, 122, 122, 128, 128, 125, 125, 127, 127, + 126, 129, 129, 130, 131, 131, 314, 314, 228, 228, + 237, 237, 237, 237, 229, 229, 230, 230, 230, 230, + 230, 230, 238, 238, 238, 249, 239, 239, 235, 235, + 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, + 233, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, @@ -9470,38 +9602,38 @@ var yyR1 = [...]int{ 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, - 234, 234, 193, 193, 193, 193, 260, 260, 180, 180, + 234, 234, 234, 234, 193, 193, 193, 193, 260, 260, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, - 180, 180, 180, 181, 181, 194, 194, 194, 194, 195, - 195, 195, 195, 195, 195, 195, 353, 353, 145, 145, + 180, 180, 180, 180, 180, 181, 181, 194, 194, 194, + 194, 195, 195, 195, 195, 195, 195, 195, 353, 353, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, - 145, 145, 145, 145, 145, 145, 145, 145, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 462, 462, 368, 368, - 368, 236, 236, 236, 236, 236, 152, 152, 152, 152, - 152, 350, 350, 350, 354, 354, 354, 352, 352, 352, + 146, 146, 146, 146, 146, 146, 146, 146, 462, 462, + 368, 368, 368, 236, 236, 236, 236, 236, 152, 152, + 152, 152, 152, 350, 350, 350, 354, 354, 354, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 355, 355, 258, 258, 148, 148, 256, 256, - 257, 259, 259, 251, 251, 251, 251, 253, 253, 232, - 232, 232, 261, 261, 356, 356, 262, 262, 132, 133, - 133, 134, 134, 263, 263, 265, 264, 264, 266, 267, - 267, 267, 268, 268, 269, 269, 269, 55, 55, 55, - 55, 55, 50, 50, 50, 50, 51, 51, 51, 51, - 163, 163, 164, 164, 164, 166, 166, 165, 165, 108, - 108, 109, 109, 109, 420, 420, 419, 419, 417, 418, - 418, 418, 418, 171, 171, 172, 173, 173, 173, 168, - 168, 169, 169, 287, 287, 287, 287, 287, 287, 287, - 270, 270, 270, 270, 299, 299, 296, 296, 278, 278, - 278, 274, 274, 276, 276, 276, 277, 277, 277, 275, - 284, 284, 286, 286, 285, 285, 281, 281, 282, 282, - 283, 283, 283, 279, 279, 231, 231, 231, 231, 231, - 288, 288, 288, 288, 344, 344, 344, 302, 302, 242, - 242, 243, 243, 247, 247, 246, 246, 244, 245, 248, - 248, 192, 303, 303, 311, 308, 308, 309, 309, 336, - 336, 336, 312, 312, 325, 325, 321, 321, 322, 322, - 315, 315, 327, 327, 327, 103, 240, 240, 407, 407, - 404, 331, 331, 333, 333, 337, 337, 341, 341, 338, - 338, 10, 456, 456, 456, 329, 329, 329, 329, 329, + 352, 352, 352, 352, 355, 355, 258, 258, 148, 148, + 256, 256, 257, 259, 259, 251, 251, 251, 251, 253, + 253, 232, 232, 232, 261, 261, 356, 356, 262, 262, + 132, 133, 133, 134, 134, 263, 263, 265, 264, 264, + 266, 267, 267, 267, 268, 268, 269, 269, 269, 55, + 55, 55, 55, 55, 50, 50, 50, 50, 51, 51, + 51, 51, 163, 163, 164, 164, 164, 166, 166, 165, + 165, 108, 108, 109, 109, 109, 420, 420, 419, 419, + 417, 418, 418, 418, 418, 171, 171, 172, 173, 173, + 173, 168, 168, 169, 169, 287, 287, 287, 287, 287, + 287, 287, 270, 270, 270, 270, 299, 299, 296, 296, + 278, 278, 278, 274, 274, 276, 276, 276, 277, 277, + 277, 275, 284, 284, 286, 286, 285, 285, 281, 281, + 282, 282, 283, 283, 283, 279, 279, 231, 231, 231, + 231, 231, 288, 288, 288, 288, 344, 344, 344, 302, + 302, 242, 242, 243, 243, 247, 247, 246, 246, 244, + 245, 248, 248, 192, 303, 303, 311, 308, 308, 309, + 309, 336, 336, 336, 312, 312, 325, 325, 321, 321, + 322, 322, 315, 315, 327, 327, 327, 103, 240, 240, + 407, 407, 404, 331, 331, 333, 333, 337, 337, 341, + 341, 338, 338, 10, 456, 456, 456, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, @@ -9518,6 +9650,7 @@ var yyR1 = [...]int{ 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, + 329, 329, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, @@ -9567,8 +9700,7 @@ var yyR1 = [...]int{ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, - 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, - 330, 458, 459, 348, 349, 349, 349, + 330, 330, 330, 458, 459, 348, 349, 349, 349, } var yyR2 = [...]int{ @@ -9586,167 +9718,167 @@ var yyR2 = [...]int{ 0, 1, 3, 1, 4, 3, 3, 4, 3, 2, 3, 4, 3, 4, 2, 7, 1, 3, 3, 3, 3, 1, 2, 1, 1, 3, 2, 3, 3, 2, - 3, 3, 5, 7, 10, 9, 1, 7, 8, 1, - 1, 10, 11, 9, 8, 8, 1, 1, 1, 3, - 1, 3, 1, 3, 0, 4, 3, 1, 3, 3, - 3, 3, 3, 1, 1, 2, 5, 4, 1, 3, - 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, - 2, 2, 1, 6, 5, 2, 2, 0, 2, 1, - 0, 2, 1, 3, 3, 0, 1, 1, 3, 3, - 10, 6, 6, 8, 7, 4, 7, 8, 8, 8, - 5, 3, 1, 1, 5, 0, 1, 1, 1, 1, - 2, 2, 2, 0, 1, 4, 4, 4, 4, 4, - 4, 2, 4, 1, 3, 1, 1, 3, 4, 3, - 3, 3, 5, 10, 0, 2, 0, 2, 3, 5, - 3, 4, 2, 3, 2, 3, 3, 3, 3, 2, - 2, 4, 4, 1, 1, 1, 1, 1, 1, 0, - 2, 2, 3, 3, 2, 3, 2, 2, 1, 1, - 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, - 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, + 3, 3, 5, 5, 7, 7, 10, 9, 1, 7, + 8, 1, 1, 10, 11, 9, 8, 8, 1, 1, + 1, 3, 1, 3, 1, 3, 0, 4, 3, 1, + 3, 3, 3, 3, 3, 1, 1, 2, 5, 4, + 1, 3, 3, 2, 2, 2, 2, 2, 1, 1, + 1, 1, 2, 2, 1, 6, 5, 2, 2, 0, + 2, 1, 0, 2, 1, 3, 3, 0, 1, 1, + 3, 3, 10, 6, 6, 8, 7, 4, 7, 8, + 8, 8, 5, 3, 1, 1, 5, 0, 1, 1, + 1, 1, 2, 2, 2, 0, 1, 4, 4, 4, + 4, 4, 4, 2, 4, 1, 3, 1, 1, 3, + 4, 3, 3, 3, 5, 10, 0, 2, 0, 2, + 3, 5, 3, 4, 2, 3, 2, 3, 3, 3, + 3, 2, 2, 4, 4, 1, 1, 1, 1, 1, + 1, 0, 2, 2, 3, 3, 2, 3, 2, 2, + 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, + 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 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, 2, 1, 1, 2, - 1, 1, 2, 1, 2, 1, 3, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, + 1, 2, 1, 1, 2, 1, 2, 1, 3, 1, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, + 3, 2, 2, 2, 2, 1, 1, 1, 1, 5, + 2, 5, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 0, 3, 0, 5, 1, 3, 0, 3, + 5, 0, 1, 1, 0, 1, 0, 3, 3, 2, + 2, 2, 1, 2, 2, 0, 1, 0, 2, 2, + 5, 0, 1, 1, 2, 1, 3, 2, 1, 1, + 3, 3, 3, 0, 1, 4, 3, 3, 4, 2, + 0, 2, 1, 1, 1, 1, 1, 0, 1, 1, + 1, 0, 1, 1, 3, 3, 4, 3, 1, 3, + 1, 7, 6, 7, 7, 8, 8, 0, 1, 5, + 2, 1, 1, 1, 0, 1, 3, 3, 1, 1, + 2, 2, 2, 0, 1, 1, 1, 2, 0, 1, + 0, 1, 1, 3, 2, 1, 2, 3, 3, 3, + 4, 4, 3, 3, 3, 3, 4, 4, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 4, 5, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, - 2, 2, 2, 3, 3, 3, 2, 2, 3, 2, - 2, 2, 2, 1, 1, 1, 1, 5, 2, 5, + 3, 1, 1, 1, 0, 1, 0, 1, 0, 2, + 0, 2, 0, 2, 2, 0, 1, 5, 1, 3, + 7, 1, 3, 3, 1, 2, 2, 2, 5, 5, + 5, 6, 8, 5, 5, 4, 4, 4, 6, 5, + 5, 5, 2, 2, 2, 2, 3, 3, 3, 4, + 3, 3, 1, 3, 5, 1, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 2, 2, 3, 4, 4, + 2, 11, 3, 6, 8, 6, 6, 6, 13, 8, + 6, 6, 10, 7, 5, 5, 5, 5, 7, 5, + 5, 5, 5, 5, 7, 7, 5, 5, 5, 5, + 6, 0, 6, 5, 6, 4, 5, 0, 8, 9, + 0, 3, 0, 1, 0, 3, 8, 4, 1, 3, + 3, 6, 7, 7, 8, 4, 0, 1, 0, 1, + 3, 3, 1, 1, 2, 1, 1, 0, 2, 0, + 2, 5, 3, 7, 4, 4, 4, 4, 3, 3, + 3, 7, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 2, 0, 2, 2, 1, 3, 2, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, + 1, 3, 3, 0, 2, 2, 2, 2, 2, 2, + 2, 4, 4, 3, 0, 1, 4, 3, 4, 4, + 3, 3, 3, 2, 1, 3, 3, 3, 5, 7, + 7, 6, 5, 5, 3, 2, 4, 5, 5, 3, + 3, 7, 3, 3, 3, 3, 4, 7, 5, 2, + 4, 4, 4, 4, 4, 5, 5, 4, 4, 4, + 4, 4, 4, 4, 4, 2, 2, 4, 4, 4, + 4, 4, 2, 3, 3, 3, 3, 3, 5, 2, + 3, 3, 2, 3, 4, 4, 4, 3, 4, 4, + 5, 3, 5, 3, 5, 0, 1, 0, 1, 0, + 1, 1, 1, 0, 2, 2, 0, 2, 2, 0, + 2, 0, 1, 1, 1, 1, 2, 1, 3, 1, + 1, 1, 1, 1, 3, 0, 1, 1, 3, 3, + 2, 2, 1, 1, 5, 0, 1, 0, 1, 2, + 3, 0, 3, 3, 3, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 4, 4, 4, 2, 2, 3, 1, 3, + 2, 1, 2, 1, 2, 2, 4, 3, 3, 6, + 4, 7, 6, 1, 3, 2, 2, 2, 2, 1, + 1, 1, 3, 2, 1, 1, 1, 0, 1, 1, + 0, 3, 0, 2, 0, 2, 1, 2, 2, 0, + 1, 1, 0, 1, 1, 5, 5, 4, 0, 2, + 4, 4, 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, - 0, 3, 0, 5, 1, 3, 0, 3, 5, 0, - 1, 1, 0, 1, 0, 3, 3, 2, 2, 2, - 1, 2, 2, 0, 1, 0, 2, 2, 5, 0, - 1, 1, 2, 1, 3, 2, 1, 1, 3, 3, - 3, 0, 1, 4, 3, 3, 4, 2, 0, 2, - 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, - 1, 1, 3, 3, 4, 3, 1, 3, 1, 7, - 6, 7, 7, 8, 8, 0, 1, 5, 2, 1, - 1, 1, 0, 1, 3, 3, 1, 1, 2, 2, - 2, 0, 1, 1, 1, 2, 0, 1, 0, 1, - 1, 3, 2, 1, 2, 3, 3, 3, 4, 4, - 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 4, 5, 0, 2, 2, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, - 1, 1, 0, 1, 0, 1, 0, 2, 0, 2, - 0, 2, 2, 0, 1, 5, 1, 3, 7, 1, - 3, 3, 1, 2, 2, 2, 5, 5, 5, 6, - 8, 5, 5, 4, 4, 4, 6, 5, 5, 5, - 2, 2, 2, 2, 3, 3, 3, 4, 3, 3, - 1, 3, 5, 1, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 2, 2, 3, 4, 4, 2, 11, - 3, 6, 8, 6, 6, 6, 13, 8, 6, 6, - 10, 7, 5, 5, 5, 5, 7, 5, 5, 5, - 5, 5, 7, 7, 5, 5, 5, 5, 6, 0, - 6, 5, 6, 4, 5, 0, 8, 9, 0, 3, - 0, 1, 0, 3, 8, 4, 1, 3, 3, 6, - 7, 7, 8, 4, 0, 1, 0, 1, 3, 3, - 1, 1, 2, 1, 1, 0, 2, 0, 2, 5, - 3, 7, 4, 4, 4, 4, 3, 3, 3, 7, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 0, 2, 2, 1, 3, 2, 0, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 3, 1, 3, - 3, 0, 2, 2, 2, 2, 2, 2, 2, 4, - 4, 3, 0, 1, 4, 3, 4, 4, 3, 3, - 3, 2, 1, 3, 3, 3, 5, 7, 7, 6, - 5, 5, 3, 2, 4, 5, 5, 3, 3, 7, - 3, 3, 3, 3, 4, 7, 5, 2, 4, 4, - 4, 4, 4, 5, 5, 4, 4, 4, 4, 4, - 4, 4, 4, 2, 2, 4, 4, 4, 4, 4, - 2, 3, 3, 3, 3, 3, 5, 2, 3, 3, - 2, 3, 4, 4, 4, 3, 4, 4, 5, 3, - 5, 3, 5, 0, 1, 0, 1, 0, 1, 1, - 1, 0, 2, 2, 0, 2, 2, 0, 2, 0, - 1, 1, 1, 1, 2, 1, 3, 1, 1, 1, - 1, 1, 3, 0, 1, 1, 3, 3, 2, 2, - 1, 1, 5, 0, 1, 0, 1, 2, 3, 0, - 3, 3, 3, 1, 0, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, - 4, 4, 4, 2, 2, 3, 1, 3, 2, 1, - 2, 1, 2, 2, 4, 3, 3, 6, 4, 7, - 6, 1, 3, 2, 2, 2, 2, 1, 1, 1, - 3, 2, 1, 1, 1, 0, 1, 1, 0, 3, - 0, 2, 0, 2, 1, 2, 2, 0, 1, 1, - 0, 1, 1, 5, 5, 4, 0, 2, 4, 4, - 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 3, 1, 2, 3, - 5, 0, 1, 2, 1, 1, 0, 1, 2, 1, - 3, 1, 1, 1, 4, 3, 1, 1, 2, 3, - 7, 0, 3, 0, 1, 1, 3, 1, 3, 1, - 1, 3, 3, 1, 3, 4, 4, 4, 3, 2, - 4, 0, 1, 0, 2, 0, 1, 0, 1, 2, - 1, 1, 1, 2, 2, 1, 2, 3, 2, 3, - 2, 2, 2, 1, 1, 3, 3, 0, 1, 1, - 2, 6, 5, 6, 6, 5, 5, 0, 2, 3, - 3, 0, 2, 3, 3, 3, 2, 3, 1, 3, - 6, 1, 1, 3, 4, 3, 4, 4, 4, 1, - 3, 4, 5, 6, 3, 4, 5, 6, 3, 4, - 1, 1, 1, 3, 3, 3, 3, 3, 3, 5, - 5, 3, 3, 3, 3, 3, 3, 1, 1, 1, - 1, 1, 3, 1, 1, 1, 2, 2, 2, 2, - 1, 1, 2, 7, 7, 6, 6, 2, 2, 5, - 6, 3, 3, 1, 3, 1, 3, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, - 2, 4, 2, 4, 0, 1, 2, 5, 0, 3, - 0, 1, 4, 4, 2, 1, 0, 0, 1, 1, - 2, 2, 1, 1, 2, 2, 0, 1, 1, 1, - 1, 5, 1, 3, 0, 3, 1, 1, 1, 2, - 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 3, 4, 6, 4, 4, - 8, 8, 6, 8, 6, 5, 4, 10, 2, 2, - 1, 2, 2, 2, 2, 2, 5, 6, 6, 6, - 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 8, 4, 8, 8, 6, 5, 4, 4, - 4, 5, 7, 4, 4, 7, 4, 4, 6, 6, - 6, 8, 6, 6, 4, 4, 3, 4, 6, 6, - 4, 4, 6, 4, 6, 4, 4, 4, 4, 4, - 4, 6, 4, 6, 4, 4, 4, 6, 4, 6, - 4, 4, 6, 4, 6, 4, 6, 8, 4, 6, - 8, 4, 6, 8, 4, 6, 8, 4, 6, 8, + 2, 3, 5, 0, 1, 2, 1, 1, 0, 1, + 2, 1, 3, 1, 1, 1, 4, 3, 1, 1, + 2, 3, 7, 0, 3, 0, 1, 1, 3, 1, + 3, 1, 1, 3, 3, 1, 3, 4, 4, 4, + 3, 2, 4, 0, 1, 0, 2, 0, 1, 0, + 1, 2, 1, 1, 1, 2, 2, 1, 2, 3, + 2, 3, 2, 2, 2, 1, 1, 3, 3, 0, + 1, 1, 2, 6, 5, 6, 6, 5, 5, 0, + 2, 3, 3, 0, 2, 3, 3, 3, 2, 3, + 1, 3, 6, 1, 1, 3, 4, 3, 4, 4, + 4, 1, 3, 4, 5, 6, 3, 4, 5, 6, + 3, 4, 1, 1, 1, 3, 3, 3, 3, 3, + 3, 5, 5, 3, 3, 3, 3, 3, 3, 1, + 1, 1, 1, 1, 3, 1, 1, 1, 2, 2, + 2, 2, 1, 1, 2, 7, 7, 6, 6, 2, + 2, 5, 6, 3, 3, 1, 3, 1, 3, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 4, 2, 4, 0, 1, 2, 5, + 0, 3, 0, 1, 4, 4, 2, 1, 0, 0, + 1, 1, 2, 2, 1, 1, 2, 2, 0, 1, + 1, 1, 1, 5, 1, 3, 0, 3, 1, 1, + 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 3, 4, 6, + 4, 4, 8, 8, 6, 8, 6, 5, 4, 10, + 2, 2, 1, 2, 2, 2, 2, 2, 5, 6, + 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 8, 4, 8, 8, 6, 5, + 4, 4, 4, 5, 7, 4, 4, 7, 4, 4, + 6, 6, 6, 8, 6, 6, 4, 4, 3, 4, + 6, 6, 4, 4, 6, 4, 6, 4, 4, 4, + 4, 4, 4, 6, 4, 6, 4, 4, 4, 6, + 4, 6, 4, 4, 6, 4, 6, 4, 6, 8, 4, 6, 8, 4, 6, 8, 4, 6, 8, 4, 6, 8, 4, 6, 8, 4, 6, 8, 4, 6, 8, 4, 6, 8, 4, 6, 8, 4, 6, 8, - 4, 6, 8, 4, 4, 4, 6, 4, 6, 4, - 8, 6, 4, 4, 6, 4, 6, 8, 4, 6, - 8, 4, 4, 6, 8, 6, 4, 6, 6, 8, - 10, 7, 8, 8, 9, 4, 4, 4, 4, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, - 4, 4, 4, 4, 4, 6, 4, 6, 5, 9, - 6, 9, 8, 6, 8, 8, 8, 6, 1, 1, - 1, 1, 1, 1, 1, 1, 0, 2, 6, 8, - 10, 12, 14, 6, 8, 8, 10, 12, 14, 6, - 8, 10, 12, 6, 8, 4, 4, 3, 4, 6, - 6, 4, 6, 4, 6, 8, 0, 2, 1, 1, + 4, 6, 8, 4, 6, 8, 4, 6, 8, 4, + 6, 8, 4, 6, 8, 4, 4, 4, 6, 4, + 6, 4, 8, 6, 4, 4, 6, 4, 6, 8, + 4, 6, 8, 4, 4, 6, 8, 6, 4, 6, + 6, 8, 10, 7, 8, 8, 9, 4, 4, 4, + 4, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 4, 4, 4, 4, 4, 4, 6, 4, 6, + 5, 9, 6, 9, 8, 6, 8, 8, 8, 6, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, + 6, 8, 10, 12, 14, 6, 8, 8, 10, 12, + 14, 6, 8, 10, 12, 6, 8, 4, 4, 3, + 4, 6, 6, 4, 6, 4, 6, 8, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 0, 2, 0, 2, - 3, 4, 4, 4, 4, 4, 0, 3, 4, 7, - 3, 1, 1, 1, 0, 5, 5, 2, 3, 1, - 2, 2, 1, 2, 1, 2, 2, 1, 2, 2, - 1, 1, 0, 1, 0, 1, 0, 2, 1, 2, - 4, 0, 2, 1, 1, 3, 5, 1, 1, 1, - 2, 2, 0, 4, 0, 2, 0, 2, 2, 1, - 3, 0, 1, 0, 1, 3, 1, 3, 2, 0, - 1, 1, 0, 1, 2, 4, 4, 0, 2, 2, - 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, - 0, 1, 3, 3, 3, 0, 3, 1, 1, 0, - 4, 0, 1, 1, 0, 1, 1, 3, 3, 0, - 1, 1, 1, 0, 1, 3, 1, 3, 2, 1, - 1, 0, 1, 2, 3, 4, 2, 3, 4, 4, - 9, 3, 5, 2, 3, 1, 1, 1, 0, 3, - 3, 0, 1, 0, 2, 2, 0, 2, 2, 2, - 0, 2, 1, 2, 3, 3, 0, 2, 1, 2, - 3, 4, 3, 0, 1, 3, 1, 6, 5, 4, - 1, 3, 3, 5, 0, 2, 5, 0, 5, 1, - 3, 1, 3, 1, 3, 1, 2, 3, 4, 1, - 1, 1, 1, 3, 3, 1, 2, 1, 1, 1, - 1, 1, 1, 1, 0, 1, 0, 2, 0, 3, - 0, 1, 0, 1, 1, 5, 0, 1, 0, 1, - 2, 1, 1, 1, 1, 1, 1, 0, 1, 1, - 1, 3, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, + 0, 2, 3, 4, 4, 4, 4, 4, 0, 3, + 4, 7, 3, 1, 1, 1, 0, 5, 5, 2, + 3, 1, 2, 2, 1, 2, 1, 2, 2, 1, + 2, 2, 1, 1, 0, 1, 0, 1, 0, 2, + 1, 2, 4, 0, 2, 1, 1, 3, 5, 1, + 1, 1, 2, 2, 0, 4, 0, 2, 0, 2, + 2, 1, 3, 0, 1, 0, 1, 3, 1, 3, + 2, 0, 1, 1, 0, 1, 2, 4, 4, 0, + 2, 2, 1, 1, 3, 3, 3, 3, 3, 3, + 3, 3, 0, 1, 3, 3, 3, 0, 3, 1, + 1, 0, 4, 0, 1, 1, 0, 1, 1, 3, + 3, 0, 1, 1, 1, 0, 1, 3, 1, 3, + 2, 1, 1, 0, 1, 2, 3, 4, 2, 3, + 4, 4, 9, 3, 5, 2, 3, 1, 1, 1, + 0, 3, 3, 0, 1, 0, 2, 2, 0, 2, + 2, 2, 0, 2, 1, 2, 3, 3, 0, 2, + 1, 2, 3, 4, 3, 0, 1, 3, 1, 6, + 5, 4, 1, 3, 3, 5, 0, 2, 5, 0, + 5, 1, 3, 1, 3, 1, 3, 1, 2, 3, + 4, 1, 1, 1, 1, 3, 3, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 0, 1, 0, 2, + 0, 3, 0, 1, 0, 1, 1, 5, 0, 1, + 0, 1, 2, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 3, 0, 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, @@ -9813,7 +9945,7 @@ var yyR2 = [...]int{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 1, 1, } var yyChk = [...]int{ @@ -9927,58 +10059,57 @@ var yyChk = [...]int{ -263, -154, -265, -36, -34, -458, 11, -105, -34, -35, -33, -40, -105, -42, 649, -41, -337, -105, 108, -270, -287, 15, 66, 176, 47, 55, -299, -296, -295, 99, - 100, -268, -269, -37, -34, -174, 22, 40, 26, -158, - 184, -174, -337, -158, -315, 268, -105, -105, -304, -351, - 344, -306, 443, 741, 442, -294, -309, 99, -293, -308, - 441, 100, -393, 173, -379, -383, -331, 279, -409, 275, - -219, -402, -401, -331, -458, 27, -289, -331, -70, -71, - -72, -308, 192, 761, -137, 297, 301, 95, 95, -383, - -382, -381, -431, 301, 279, -408, -400, 271, 280, -389, - 272, 273, -384, 265, 150, -431, -384, 270, 280, 275, - 279, 301, 301, 138, 301, 138, 301, 301, 301, 301, - 301, 301, 301, 301, 301, 296, -390, 165, -390, 625, - 625, -396, -431, 275, 265, -431, -431, 271, -327, -384, - 267, 27, 267, 37, 37, -390, -390, -390, -308, 192, - -390, -390, -390, -390, 309, 309, -390, -390, -390, -390, + 100, -268, -269, -37, -34, -174, 22, 40, 26, 184, + -158, -174, -337, 184, -158, -315, 268, -105, -105, -304, + -351, 344, -306, 443, 741, 442, -294, -309, 99, -293, + -308, 441, 100, -393, 173, -379, -383, -331, 279, -409, + 275, -219, -402, -401, -331, -458, 27, -289, -331, -70, + -71, -72, -308, 192, 761, -137, 297, 301, 95, 95, + -383, -382, -381, -431, 301, 279, -408, -400, 271, 280, + -389, 272, 273, -384, 265, 150, -431, -384, 270, 280, + 275, 279, 301, 301, 138, 301, 138, 301, 301, 301, + 301, 301, 301, 301, 301, 301, 296, -390, 165, -390, + 625, 625, -396, -431, 275, 265, -431, -431, 271, -327, + -384, 267, 27, 267, 37, 37, -390, -390, -390, -308, + 192, -390, -390, -390, -390, 309, 309, -390, -390, -390, -390, -390, -390, -390, -390, -390, -390, -390, -390, -390, - -390, -390, -390, 264, -430, -163, 439, 329, 467, 263, - -164, 89, -73, 311, -43, -219, -325, 265, 266, -430, - 305, 298, 322, -219, 237, 264, 744, -319, 173, 18, - -319, -316, 428, 426, 413, 418, -319, -319, -319, -319, - 312, 411, -385, 265, 37, 276, 428, 312, 411, 312, - 313, 312, 313, 421, 431, 312, -342, 17, 176, 467, - 416, 420, 305, 264, 306, 266, 430, 313, -342, 97, - -320, 173, 312, 428, 422, 308, -319, -319, -349, -458, - -333, -331, -329, 246, 40, 155, 27, 29, 158, 193, - 141, 22, 159, 39, 248, 376, 275, 192, 271, 262, - 256, 512, 241, 80, 630, 468, 475, 466, 474, 478, - 514, 515, 467, 414, 253, 33, 16, 632, 30, 286, - 26, 43, 186, 243, 162, 163, 633, 289, 28, 257, - 287, 128, 132, 635, 25, 83, 280, 17, 273, 45, - 19, 636, 637, 20, 73, 269, 268, 176, 265, 78, - 725, 14, 236, 31, 172, 74, 638, 150, 144, 639, - 640, 641, 642, 142, 76, 173, 23, 781, 476, 477, - 35, 742, 617, 300, 188, 81, 64, 743, 156, 472, - 643, 644, 129, 645, 133, 84, 748, 152, 21, 724, - 79, 47, 646, 301, 647, 270, 782, 648, 446, 649, - 174, 244, 511, 77, 175, 755, 650, 756, 263, 427, - 11, 517, 34, 285, 284, 272, 72, 71, 259, 260, - 261, 140, 75, 482, 651, 264, 161, 267, 143, 131, - 258, 10, 149, 36, 15, 82, 85, 479, 480, 481, - 62, 139, 621, 160, 18, 652, 447, 154, -427, 744, - -349, -349, 312, 353, 34, 100, -453, -454, -455, 621, - 446, 267, -331, -219, -111, 734, 245, -112, 740, 40, - 252, 145, 37, -161, 428, -149, 193, 762, 745, 746, - 747, 744, 425, 752, 750, 748, 312, 749, 95, 152, - 154, 155, 178, -174, 172, -229, -230, 171, 165, 166, - 167, 168, 169, 170, 177, 176, 156, 158, 173, -280, - 153, 179, 180, 181, 182, 183, 184, 185, 187, 186, - 188, 189, 174, 175, 192, 239, 240, -182, -182, -182, - -182, -249, -255, -254, -458, -251, -427, -330, -337, -458, - -458, -182, -314, -458, -179, -458, -458, -458, -458, -458, - -258, -174, -458, -458, -462, -458, -462, -462, -462, -368, - -458, -368, -368, -458, -458, -458, -458, -458, -458, -458, - -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, + -390, -390, -390, -390, 264, -430, -163, 439, 329, 467, + 263, -164, 89, -73, 311, -43, -219, -325, 265, 266, + -430, 305, 298, 322, -219, 237, 264, 744, -319, 173, + 18, -319, -316, 428, 426, 413, 418, -319, -319, -319, + -319, 312, 411, -385, 265, 37, 276, 428, 312, 411, + 312, 313, 312, 313, 421, 431, 312, -342, 17, 176, + 467, 416, 420, 305, 264, 306, 266, 430, 313, -342, + 97, -320, 173, 312, 428, 422, 308, -319, -319, -349, + -458, -333, -331, -329, 246, 40, 155, 27, 29, 158, + 193, 141, 22, 159, 39, 248, 376, 275, 192, 271, + 262, 256, 512, 241, 80, 630, 468, 475, 466, 474, + 478, 514, 515, 467, 414, 253, 33, 16, 632, 30, + 286, 26, 43, 186, 243, 162, 163, 633, 289, 28, + 257, 287, 128, 132, 635, 25, 83, 280, 17, 273, + 45, 19, 636, 637, 20, 73, 269, 268, 176, 265, + 78, 725, 14, 236, 31, 172, 74, 638, 150, 144, + 639, 640, 641, 642, 142, 76, 173, 23, 781, 476, + 477, 35, 742, 617, 300, 188, 81, 64, 743, 156, + 472, 643, 644, 129, 645, 133, 84, 748, 152, 21, + 724, 79, 47, 646, 301, 647, 270, 782, 648, 446, + 649, 174, 244, 511, 77, 175, 755, 650, 756, 263, + 427, 11, 517, 34, 285, 284, 272, 72, 71, 259, + 260, 261, 140, 75, 482, 651, 264, 161, 267, 143, + 131, 258, 10, 149, 36, 15, 82, 85, 479, 480, + 481, 62, 139, 621, 160, 18, 652, 447, 154, -427, + 744, -349, -349, 312, 353, 34, 100, -453, -454, -455, + 621, 446, 267, -331, -219, -111, 734, 245, -112, 740, + 40, 252, 145, 37, -161, 428, -149, 193, 762, 745, + 746, 747, 744, 425, 752, 750, 748, 312, 749, 95, + 152, 154, 155, 178, -174, 172, -229, -230, 171, 165, + 166, 167, 168, 169, 170, 177, 176, 156, 158, 173, + -280, 153, 179, 180, 181, 182, 183, 184, 185, 187, + 186, 188, 189, 174, 175, 192, 239, 240, -182, -182, + -182, -182, -249, -255, -254, -458, -251, -427, -330, -337, + -458, -458, -182, -314, -458, -179, -458, -458, -458, -458, + -458, -258, -174, -458, -458, -462, -458, -462, -462, -462, + -368, -458, -368, -368, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, @@ -9989,725 +10120,726 @@ var yyChk = [...]int{ -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, - -458, -458, -458, -458, -458, -458, -458, -458, 237, -458, - -458, -458, -458, -458, -368, -368, -368, -368, -368, -368, -458, -458, -458, -458, -458, -458, -458, -458, -458, -458, - -458, -458, -458, -458, 97, 111, 107, 110, 102, 113, - 97, 97, 97, 97, -34, -35, -239, 62, -458, -348, - -440, -441, -222, -219, -458, 329, -331, -331, 298, 104, - -268, -37, -34, -263, -269, -265, -34, -105, -147, -160, - 68, 69, -159, -162, 26, 43, 73, 75, 98, 71, - 72, 70, 40, -459, 96, -459, -287, -459, -171, -325, - -155, -164, 265, 273, 272, 149, -430, -172, 152, 316, - 95, -42, -290, 114, -242, -247, -245, 755, 678, 708, - 678, 708, 66, 48, 97, 97, 95, 95, 24, -264, - -266, -174, 17, -335, 178, -334, 27, -331, 97, 237, - 17, -220, 31, -219, -315, -315, 95, 99, 344, -305, - -307, 444, 446, 165, -336, -331, 97, 33, 96, 95, - -219, -357, -360, -362, -361, -363, -358, -359, 373, 374, - 193, 377, 379, 380, 381, 382, 383, 384, 385, 386, - 387, 390, 402, 34, 288, 369, 370, 371, 372, 391, - 392, 393, 394, 396, 397, 398, 399, 354, 375, 619, - 355, 356, 357, 358, 359, 360, 362, 363, 366, 364, - 365, 367, 368, -332, -331, 94, 96, 95, -367, 94, - -174, -32, 96, 95, -390, -390, -390, 296, 22, -52, - -49, -416, 21, -48, -49, 246, 134, 135, 243, 94, - -379, 94, -388, -332, -331, 94, 150, 270, 149, -387, - -384, -387, -388, -331, -251, -331, 150, 150, -331, -331, - -301, -331, -301, -301, 40, -301, 40, -301, 40, 104, - -331, -301, 40, -301, 40, -301, 40, -301, 40, -301, - 40, 33, 86, 87, 88, 33, 90, 91, 92, -251, - -331, -331, -251, -379, -251, -219, -331, -308, 104, 104, - 104, -390, -390, 104, 97, 97, 97, -390, -390, 104, - 97, -339, -337, 97, 97, -432, 281, 326, 328, 104, - 104, 104, 104, 33, 97, -433, 33, 769, 768, 770, - 771, 772, 97, 104, 33, 104, 33, 104, -331, 94, - -219, -171, 241, 243, 246, 84, 97, 334, 332, 333, - 330, 335, 336, 337, 165, 49, 95, 267, 264, -331, - -321, 269, -321, -321, -331, -338, -337, -329, -219, 267, - 410, 97, -174, -386, 17, 176, -342, -342, -319, -219, - -386, -342, -319, -219, -319, -319, -319, -319, -342, -342, - -342, -319, -337, -337, -219, -219, -219, -219, -219, -219, - -219, -349, -320, -319, 744, 97, -313, 17, 84, -349, - -349, -328, 25, 25, 95, 350, 447, 448, -347, 347, - -107, -331, 97, -13, -32, -21, -20, -22, 165, -13, - 95, 621, -212, -219, 744, 744, 744, 744, 744, 744, - -174, -174, -174, -174, 645, -237, -451, 156, 131, 132, - 129, 130, -191, 41, 42, 40, -174, -238, -244, -249, - 114, 176, 158, 173, -280, -179, -182, -179, -179, -179, - -179, -179, -179, 236, -179, 236, -179, -179, -179, -179, - -179, -179, -350, -331, 97, 193, -187, -186, 113, -449, - -187, 618, 95, -254, 237, -174, -174, -427, -145, 484, - 485, 486, 487, 489, 490, 491, 494, 495, 499, 500, - 483, 501, 488, 493, 496, 497, 498, 492, 372, -174, - -240, -239, -240, -174, -174, -256, -257, 160, -251, -174, - -459, -459, 104, 184, -153, 26, 43, -153, -153, -153, - -153, -174, -174, -174, -174, -174, -174, -174, -174, -174, - -174, -153, -174, -146, 483, 501, 488, 493, 496, 497, - 498, 492, 372, 502, 503, 504, 505, 506, 507, 508, - 509, 510, -146, -145, -174, -174, -174, -174, -174, -174, - -174, -174, -113, -174, 141, 142, 143, -239, -174, -179, - -174, -174, -174, -459, -174, -174, -174, -240, -174, -174, + -458, -458, -458, -458, -458, -458, -458, -458, -458, 237, + -458, -458, -458, -458, -458, -368, -368, -368, -368, -368, + -368, -458, -458, -458, -458, -458, -458, -458, -458, -458, + -458, -458, -458, -458, -458, 97, 111, 107, 110, 102, + 113, 97, 97, 97, 97, -34, -35, -239, 62, -458, + -348, -440, -441, -222, -219, -458, 329, -331, -331, 298, + 104, -268, -37, -34, -263, -269, -265, -34, -105, -147, + -160, 68, 69, -159, -162, 26, 43, 73, 75, 98, + 71, 72, 70, 40, -459, 96, -459, -287, -459, -171, + -325, -155, -164, 265, 273, 272, 149, -430, -172, 152, + 316, 95, -42, -290, 114, -242, -247, -245, 755, 678, + 708, 678, 708, 66, 48, 97, 97, 95, 95, 24, + -264, -266, -174, 17, 17, -335, 178, -334, 27, -331, + 97, 237, 17, 17, -220, 31, -219, -315, -315, 95, + 99, 344, -305, -307, 444, 446, 165, -336, -331, 97, + 33, 96, 95, -219, -357, -360, -362, -361, -363, -358, + -359, 373, 374, 193, 377, 379, 380, 381, 382, 383, + 384, 385, 386, 387, 390, 402, 34, 288, 369, 370, + 371, 372, 391, 392, 393, 394, 396, 397, 398, 399, + 354, 375, 619, 355, 356, 357, 358, 359, 360, 362, + 363, 366, 364, 365, 367, 368, -332, -331, 94, 96, + 95, -367, 94, -174, -32, 96, 95, -390, -390, -390, + 296, 22, -52, -49, -416, 21, -48, -49, 246, 134, + 135, 243, 94, -379, 94, -388, -332, -331, 94, 150, + 270, 149, -387, -384, -387, -388, -331, -251, -331, 150, + 150, -331, -331, -301, -331, -301, -301, 40, -301, 40, + -301, 40, 104, -331, -301, 40, -301, 40, -301, 40, + -301, 40, -301, 40, 33, 86, 87, 88, 33, 90, + 91, 92, -251, -331, -331, -251, -379, -251, -219, -331, + -308, 104, 104, 104, -390, -390, 104, 97, 97, 97, + -390, -390, 104, 97, -339, -337, 97, 97, -432, 281, + 326, 328, 104, 104, 104, 104, 33, 97, -433, 33, + 769, 768, 770, 771, 772, 97, 104, 33, 104, 33, + 104, -331, 94, -219, -171, 241, 243, 246, 84, 97, + 334, 332, 333, 330, 335, 336, 337, 165, 49, 95, + 267, 264, -331, -321, 269, -321, -321, -331, -338, -337, + -329, -219, 267, 410, 97, -174, -386, 17, 176, -342, + -342, -319, -219, -386, -342, -319, -219, -319, -319, -319, + -319, -342, -342, -342, -319, -337, -337, -219, -219, -219, + -219, -219, -219, -219, -349, -320, -319, 744, 97, -313, + 17, 84, -349, -349, -328, 25, 25, 95, 350, 447, + 448, -347, 347, -107, -331, 97, -13, -32, -21, -20, + -22, 165, -13, 95, 621, -212, -219, 744, 744, 744, + 744, 744, 744, -174, -174, -174, -174, 645, -237, -451, + 156, 131, 132, 129, 130, -191, 41, 42, 40, -174, + -238, -244, -249, 114, 176, 158, 173, -280, -179, -182, + -179, -179, -179, -179, -179, -179, 236, -179, 236, -179, + -179, -179, -179, -179, -179, -350, -331, 97, 193, -187, + -186, 113, -449, -187, 618, 95, -254, 237, -174, -174, + -427, -145, 484, 485, 486, 487, 489, 490, 491, 494, + 495, 499, 500, 483, 501, 488, 493, 496, 497, 498, + 492, 372, -174, -240, -239, -240, -174, -174, -256, -257, + 160, -251, -174, -459, -459, 104, 184, -153, 26, 43, + -153, -153, -153, -153, -174, -174, -174, -174, -174, -174, + -174, -174, -174, -174, -153, -174, -146, 483, 501, 488, + 493, 496, 497, 498, 492, 372, 502, 503, 504, 505, + 506, 507, 508, 509, 510, -146, -145, -174, -174, -174, + -174, -174, -174, -174, -174, -113, -174, 141, 142, 143, + -239, -174, -179, -174, -174, -174, -459, -174, -174, -174, + -240, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, + -174, -174, -174, -174, -174, -174, -174, -426, -425, -424, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, - -174, -174, -174, -174, -426, -425, -424, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, - -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, - -239, -239, -239, -239, -239, -174, -459, -174, -193, -177, - 104, -295, 113, -174, -174, -174, -174, -174, -174, -240, - -333, -338, -329, -330, -239, -240, -240, -239, -239, -174, - -174, -174, -174, -174, -174, -174, -174, -459, -174, -174, - -174, -174, -174, -287, -459, -239, 95, -442, 446, 447, - 742, -340, 301, -339, 27, -240, 97, 17, -298, 85, - -331, -268, -268, 68, 69, 64, -157, -158, -162, -459, - 305, -166, 318, 264, -163, -171, -331, 265, 265, 265, - -322, 269, 511, 165, -41, 27, 95, -458, 671, 671, - 67, 97, -369, -308, 400, 401, 193, -296, -174, -174, - 95, -267, 29, 30, -219, -334, 184, -338, -219, -300, - 301, -219, -197, -199, -200, -201, -222, -250, -458, -202, - -34, 641, 638, 17, -212, -213, -221, -337, -306, -351, - -305, 95, 445, 447, 448, 84, 133, -174, -370, 192, - -398, -397, -396, -379, -381, -382, -383, 96, -370, -375, - 407, 406, -367, -367, -367, -367, -367, -367, -369, -369, - -369, -367, 94, -367, 94, -367, -367, -367, -367, -372, - 94, -372, -372, -373, -372, 94, -373, -374, 94, -374, - -409, -174, -406, -405, -403, -404, 274, 109, 718, 670, - 621, 662, 704, 85, -401, -267, 104, -459, -108, 621, - -331, 99, 97, 99, 97, 99, 97, -138, -77, -1, - 781, 782, 783, 95, 22, -380, -379, -76, 326, -412, - -413, 301, -408, -402, -388, 150, -387, -388, -388, -331, - 95, 31, 138, 138, 138, 138, 621, 243, 34, -323, - 661, 156, 718, 670, -379, -76, 267, 267, -350, -350, - -350, 97, 97, -318, 777, -212, -166, 307, 307, 264, - 320, 264, 320, -219, 331, 334, 332, 333, 330, 335, - 336, 337, 338, 40, 40, 40, 40, 40, 40, 40, - 319, 321, 323, 309, -219, -219, -321, 84, -214, -219, - 28, -337, -219, 97, 97, -219, -319, -319, -219, -319, - -319, -219, 97, -337, -455, 351, -331, 387, 735, 737, - -149, 446, 95, 621, 25, -150, 25, -458, -451, 131, - 132, -249, -249, -249, -238, -179, -182, -179, 155, 289, - -179, -179, -458, -251, -459, -333, 27, 95, 85, -459, - 182, 95, -459, -459, 95, 17, 95, -259, -257, 162, - -174, -459, 95, -459, -459, -239, -174, -174, -174, -174, - -459, -459, -459, -459, -459, -459, -459, -459, -459, -459, - -239, -459, 95, 95, 17, -354, 27, -459, -459, -459, - -459, 95, -459, -459, -258, -459, 17, -459, 85, 95, - 176, 95, -459, -459, -459, 95, 95, -459, -459, 95, - -459, 95, -459, -459, -459, -459, -459, -459, 95, -459, - 95, -459, -459, -459, 95, -459, 95, -459, -459, 95, + -174, -174, -174, -239, -239, -239, -239, -239, -174, -459, + -174, -193, -177, 104, -295, 113, -174, -174, -174, -174, + -174, -174, -240, -333, -338, -329, -330, -239, -240, -240, + -239, -239, -174, -174, -174, -174, -174, -174, -174, -174, + -459, -174, -174, -174, -174, -174, -287, -459, -239, 95, + -442, 446, 447, 742, -340, 301, -339, 27, -240, 97, + 17, -298, 85, -331, -268, -268, 68, 69, 64, -157, + 184, -158, -162, -459, 305, -166, 318, 264, -163, -171, + -331, 265, 265, 265, -322, 269, 511, 165, -41, 27, + 95, -458, 671, 671, 67, 97, -369, -308, 400, 401, + 193, -296, -174, -174, 95, -267, 29, 30, -219, -219, + -334, 184, -338, -219, -219, -300, 301, -219, -197, -199, + -200, -201, -222, -250, -458, -202, -34, 641, 638, 17, + -212, -213, -221, -337, -306, -351, -305, 95, 445, 447, + 448, 84, 133, -174, -370, 192, -398, -397, -396, -379, + -381, -382, -383, 96, -370, -375, 407, 406, -367, -367, + -367, -367, -367, -367, -369, -369, -369, -367, 94, -367, + 94, -367, -367, -367, -367, -372, 94, -372, -372, -373, + -372, 94, -373, -374, 94, -374, -409, -174, -406, -405, + -403, -404, 274, 109, 718, 670, 621, 662, 704, 85, + -401, -267, 104, -459, -108, 621, -331, 99, 97, 99, + 97, 99, 97, -138, -77, -1, 781, 782, 783, 95, + 22, -380, -379, -76, 326, -412, -413, 301, -408, -402, + -388, 150, -387, -388, -388, -331, 95, 31, 138, 138, + 138, 138, 621, 243, 34, -323, 661, 156, 718, 670, + -379, -76, 267, 267, -350, -350, -350, 97, 97, -318, + 777, -212, -166, 307, 307, 264, 320, 264, 320, -219, + 331, 334, 332, 333, 330, 335, 336, 337, 338, 40, + 40, 40, 40, 40, 40, 40, 319, 321, 323, 309, + -219, -219, -321, 84, -214, -219, 28, -337, -219, 97, + 97, -219, -319, -319, -219, -319, -319, -219, 97, -337, + -455, 351, -331, 387, 735, 737, -149, 446, 95, 621, + 25, -150, 25, -458, -451, 131, 132, -249, -249, -249, + -238, -179, -182, -179, 155, 289, -179, -179, -458, -251, + -459, -333, 27, 95, 85, -459, 182, 95, -459, -459, + 95, 17, 95, -259, -257, 162, -174, -459, 95, -459, + -459, -239, -174, -174, -174, -174, -459, -459, -459, -459, + -459, -459, -459, -459, -459, -459, -239, -459, 95, 95, + 17, -354, 27, -459, -459, -459, -459, 95, -459, -459, + -258, -459, 17, -459, 85, 95, 176, 95, -459, -459, + -459, 95, 95, -459, -459, 95, -459, 95, -459, -459, + -459, -459, -459, -459, 95, -459, 95, -459, -459, -459, + 95, -459, 95, -459, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, - -459, 95, -459, 95, -459, -459, -459, 95, -459, 95, - -459, 95, -459, -459, 95, -459, 95, -459, 95, -459, - 95, 95, -459, 95, 95, 95, -459, 95, 95, 95, - 95, -459, -459, -459, -459, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, -459, -459, -459, -459, -459, - -459, 95, -120, 646, -459, -459, 95, -459, 95, 95, - 95, 95, 95, -459, -458, 237, -459, -459, -459, -459, - -459, 95, 95, 95, 95, 95, 95, -459, -459, -459, - 95, 95, -459, 95, -459, 95, -459, -441, 741, 447, - -226, -225, -223, 82, 268, 83, -458, -339, -459, -187, - -295, -297, -295, -232, -331, 104, 113, -270, -196, 95, - -198, 17, -322, 266, 325, -322, -171, -166, -407, -404, - -331, -331, -331, -337, 156, -173, 478, -168, 97, 99, - -249, -247, -459, -369, -275, -281, -316, -331, 97, 193, - -371, 193, -371, 400, 401, -266, 237, -227, 18, -231, - 34, 62, -32, -458, -458, 34, 95, -215, -217, -216, - -218, 74, 78, 80, 75, 76, 77, 81, -345, 27, - -34, -197, -34, -458, -219, -212, -460, 17, 85, -460, - 95, 237, -307, -310, 449, 446, 452, -427, 97, -137, - 95, -396, -383, -271, -167, 45, -376, 408, -369, 629, - -369, -369, -378, 97, -378, 104, 104, 104, 96, -55, - -50, -51, 35, 89, -403, -390, 97, 44, -390, -390, - -331, 96, -267, -109, 315, 741, -2, 780, 786, 150, - 94, 413, 21, -289, 95, 96, -252, 327, 96, -139, - -331, 96, 94, -388, -388, -331, -458, 264, 33, 33, - 718, 670, 661, -76, -252, -251, -331, -370, 779, 778, - 96, 266, -219, -219, -219, -219, -219, -219, 246, 243, - 436, -450, 339, 97, -450, 310, 267, -212, -219, 95, - -110, 283, 278, -342, -342, 35, -219, 446, 753, 751, - -174, 155, 289, -191, -182, -145, -145, -179, -352, 193, - 373, 288, 371, 367, 387, 378, 406, 369, 407, 364, - 363, 362, -352, -350, -179, -239, -174, -174, -174, 164, - -174, 161, -174, -121, -120, -459, -459, -459, -459, -459, - -121, -121, -121, -121, -121, -121, -121, -121, -121, -121, - -263, -174, -174, -174, -459, 193, 373, -121, -174, 17, - -174, -350, -174, -174, -174, -174, -174, -174, -174, -174, + -459, -459, -459, 95, -459, 95, -459, 95, -459, -459, + 95, -459, 95, -459, 95, -459, 95, 95, -459, 95, + 95, 95, -459, 95, 95, 95, 95, -459, -459, -459, + -459, 95, 95, 95, 95, 95, 95, 95, 95, 95, + 95, -459, -459, -459, -459, -459, -459, 95, -120, 646, + -459, -459, 95, -459, 95, 95, 95, 95, 95, -459, + -458, 237, -459, -459, -459, -459, -459, 95, 95, 95, + 95, 95, 95, -459, -459, -459, 95, 95, -459, 95, + -459, 95, -459, -441, 741, 447, -226, -225, -223, 82, + 268, 83, -458, -339, -459, -187, -295, -297, -295, -232, + -331, 104, 113, -270, -196, 95, -198, 17, -322, 266, + 325, -322, -171, -166, -407, -404, -331, -331, -331, -337, + 156, -173, 478, -168, 97, 99, -249, -247, -459, -369, + -275, -281, -316, -331, 97, 193, -371, 193, -371, 400, + 401, -266, 237, -227, 18, -227, -231, 34, 62, -32, + -458, -458, 34, 95, -215, -217, -216, -218, 74, 78, + 80, 75, 76, 77, 81, -345, 27, -34, -197, -34, + -458, -219, -212, -460, 17, 85, -460, 95, 237, -307, + -310, 449, 446, 452, -427, 97, -137, 95, -396, -383, + -271, -167, 45, -376, 408, -369, 629, -369, -369, -378, + 97, -378, 104, 104, 104, 96, -55, -50, -51, 35, + 89, -403, -390, 97, 44, -390, -390, -331, 96, -267, + -109, 315, 741, -2, 780, 786, 150, 94, 413, 21, + -289, 95, 96, -252, 327, 96, -139, -331, 96, 94, + -388, -388, -331, -458, 264, 33, 33, 718, 670, 661, + -76, -252, -251, -331, -370, 779, 778, 96, 266, -219, + -219, -219, -219, -219, -219, 246, 243, 436, -450, 339, + 97, -450, 310, 267, -212, -219, 95, -110, 283, 278, + -342, -342, 35, -219, 446, 753, 751, -174, 155, 289, + -191, -182, -145, -145, -179, -352, 193, 373, 288, 371, + 367, 387, 378, 406, 369, 407, 364, 363, 362, -352, + -350, -179, -239, -174, -174, -174, 164, -174, 161, -174, + -121, -120, -459, -459, -459, -459, -459, -121, -121, -121, + -121, -121, -121, -121, -121, -121, -121, -263, -174, -174, + -174, -459, 193, 373, -121, -174, 17, -174, -350, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, - -174, -174, -174, -174, -174, -174, -174, -424, -174, -239, - -174, -239, -174, -174, -174, -174, -174, -425, -425, -425, - -425, -425, -239, -239, -239, -239, -174, -458, -331, -124, - -123, -122, 697, 268, -120, -193, -124, -193, 236, -174, - 236, 236, 236, -174, -240, -333, -174, -174, -174, -174, - -174, -174, -174, -174, -174, -174, -223, -384, 307, -384, - 307, -384, -301, 95, -312, 25, 17, 62, 62, -196, - -227, -158, -197, -219, -219, -165, 316, 324, -219, -166, - 266, 84, -407, -407, -407, 28, 94, -169, 100, -278, - 734, -284, 51, -282, -283, 52, -279, 53, 61, -371, - -371, 184, -268, -174, -302, 84, -303, -311, -251, -243, - -246, -244, -458, -288, -459, -331, -301, -303, -199, -200, - -200, -199, -200, 74, 74, 74, 79, 74, 79, 74, - -216, -337, -459, -174, -340, 85, -197, -197, -221, -337, - 184, 446, 450, 451, -396, -448, 129, 156, 33, 84, - 404, 109, -446, 192, 658, 713, 718, 670, 662, 704, - -447, 270, 149, 150, 282, 27, 46, 96, 95, 96, - 95, 96, 96, 95, -324, -323, -51, -50, -390, -390, - 104, -427, 97, 97, 275, -140, 784, 104, 94, -3, - 89, -174, 94, 22, -379, -251, -414, -364, -415, -365, - -366, -5, -6, -391, -143, 62, 109, -80, 49, 265, - 764, 765, 138, -458, 777, -406, -289, -410, -412, -219, - -178, -458, -190, -176, -175, -177, -183, 182, 183, 288, - 369, 370, -252, -219, -429, 85, 307, 404, 307, 404, - 97, -452, 340, 97, -452, -219, -110, -55, -219, -319, - -319, 35, -427, -459, -191, -182, -152, 176, 621, -355, - 628, -367, -367, -367, -374, -367, 359, -367, 359, -367, - -459, -459, -459, 95, -459, 25, -459, 95, -174, 95, - -121, -121, -121, -121, -121, -148, 517, 95, 95, -459, - 94, 94, -459, -174, -459, -459, -459, 95, -459, -459, - -459, -459, -459, -459, -459, -459, -459, -459, -459, -459, + -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, + -174, -174, -174, -174, -424, -174, -239, -174, -239, -174, + -174, -174, -174, -174, -425, -425, -425, -425, -425, -239, + -239, -239, -239, -174, -458, -331, -124, -123, -122, 697, + 268, -120, -193, -124, -193, 236, -174, 236, 236, 236, + -174, -240, -333, -174, -174, -174, -174, -174, -174, -174, + -174, -174, -174, -223, -384, 307, -384, 307, -384, -301, + 95, -312, 25, 17, 62, 62, -196, -227, -158, -197, + -219, -219, -165, 316, 324, -219, -166, 266, 84, -407, + -407, -407, 28, 94, -169, 100, -278, 734, -284, 51, + -282, -283, 52, -279, 53, 61, -371, -371, 184, -268, + -174, -268, -302, 84, -303, -311, -251, -243, -246, -244, + -458, -288, -459, -331, -301, -303, -199, -200, -200, -199, + -200, 74, 74, 74, 79, 74, 79, 74, -216, -337, + -459, -174, -340, 85, -197, -197, -221, -337, 184, 446, + 450, 451, -396, -448, 129, 156, 33, 84, 404, 109, + -446, 192, 658, 713, 718, 670, 662, 704, -447, 270, + 149, 150, 282, 27, 46, 96, 95, 96, 95, 96, + 96, 95, -324, -323, -51, -50, -390, -390, 104, -427, + 97, 97, 275, -140, 784, 104, 94, -3, 89, -174, + 94, 22, -379, -251, -414, -364, -415, -365, -366, -5, + -6, -391, -143, 62, 109, -80, 49, 265, 764, 765, + 138, -458, 777, -406, -289, -410, -412, -219, -178, -458, + -190, -176, -175, -177, -183, 182, 183, 288, 369, 370, + -252, -219, -429, 85, 307, 404, 307, 404, 97, -452, + 340, 97, -452, -219, -110, -55, -219, -319, -319, 35, + -427, -459, -191, -182, -152, 176, 621, -355, 628, -367, + -367, -367, -374, -367, 359, -367, 359, -367, -459, -459, + -459, 95, -459, 25, -459, 95, -174, 95, -121, -121, + -121, -121, -121, -148, 517, 95, 95, -459, 94, 94, + -459, -174, -459, -459, -459, 95, -459, -459, -459, -459, + -459, -459, -459, -459, -459, -459, -459, -459, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, -459, 95, - -459, 95, -459, -459, 95, -459, -459, -459, 95, -459, - 95, -459, 95, -459, -459, -459, 95, -353, 719, -459, - -459, -459, -459, -459, -459, -459, -459, -459, -459, -459, - -119, -332, -120, 679, 679, -459, -120, -260, 95, -179, - -459, -179, -179, -179, -459, -459, -459, 95, -459, 95, - 95, -459, 95, -459, 95, -459, -459, -459, -459, 95, - -224, 25, -458, -224, -458, -224, -459, -295, -219, -227, - -261, 19, -458, 266, -219, -219, 84, 84, 84, 96, - -275, 56, 379, -286, -285, 60, 52, -283, 22, 54, - 22, 32, -302, 95, 165, -344, 95, 27, -459, -459, - 95, 62, 237, -459, -227, -210, -209, 84, 85, -211, - 84, -209, 74, 74, -290, 95, -300, -197, -227, -227, - 237, 129, -458, -178, 15, 97, 97, -427, -445, 768, - 769, 33, 770, 104, -390, -390, 150, 150, -219, 94, - -369, 97, -369, 104, 104, 33, 90, 91, 92, 33, - 86, 87, 88, 317, -411, 94, 22, -174, 94, 165, - 96, -289, -289, 303, 176, -390, 762, 309, 309, -390, - -390, -390, -142, -141, 784, 96, -459, 95, -377, 621, - 624, -174, -184, -184, -290, -423, 621, -428, -331, -331, - -331, -331, 104, 106, -459, 619, 81, 622, -459, -369, - -174, -174, -174, -174, -268, 97, -174, -174, 104, 104, - -121, -459, -174, -174, -174, -174, -174, -174, -174, -174, + -459, -459, 95, -459, -459, -459, 95, -459, 95, -459, + 95, -459, -459, -459, 95, -353, 719, -459, -459, -459, + -459, -459, -459, -459, -459, -459, -459, -459, -119, -332, + -120, 679, 679, -459, -120, -260, 95, -179, -459, -179, + -179, -179, -459, -459, -459, 95, -459, 95, 95, -459, + 95, -459, 95, -459, -459, -459, -459, 95, -224, 25, + -458, -224, -458, -224, -459, -295, -219, -227, -261, 19, + -458, 266, -219, -219, 84, 84, 84, 96, -275, 56, + 379, -286, -285, 60, 52, -283, 22, 54, 22, 32, + -302, 95, 165, -344, 95, 27, -459, -459, 95, 62, + 237, -459, -227, -210, -209, 84, 85, -211, 84, -209, + 74, 74, -290, 95, -300, -197, -227, -227, 237, 129, + -458, -178, 15, 97, 97, -427, -445, 768, 769, 33, + 770, 104, -390, -390, 150, 150, -219, 94, -369, 97, + -369, 104, 104, 33, 90, 91, 92, 33, 86, 87, + 88, 317, -411, 94, 22, -174, 94, 165, 96, -289, + -289, 303, 176, -390, 762, 309, 309, -390, -390, -390, + -142, -141, 784, 96, -459, 95, -377, 621, 624, -174, + -184, -184, -290, -423, 621, -428, -331, -331, -331, -331, + 104, 106, -459, 619, 81, 622, -459, -369, -174, -174, + -174, -174, -268, 97, -174, -174, 104, 104, -121, -459, -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, - -174, -174, -239, -174, -459, -207, -206, -208, 745, 129, - 33, -352, -459, -241, 301, -127, -126, -125, 17, -459, - -174, -145, -145, -145, -145, -174, -174, -174, -174, -174, - -174, -458, 74, 21, 19, -292, -331, 270, -458, -292, - -458, -340, -261, -262, 20, 22, -420, -419, -417, -418, - 176, 725, 724, -219, -219, -219, -219, -276, 58, -274, - 57, -274, -285, 22, 22, 97, 22, 97, 150, -311, - -174, -246, -339, 62, -32, -331, -243, -331, -263, -174, - 94, -174, -187, -227, -227, -174, -234, 541, 543, 544, - 545, 542, 547, 548, 549, 550, 551, 552, 553, 554, - 555, 556, 546, 557, 518, 519, 520, 116, 118, 117, - 126, 127, 521, 522, 523, 373, 569, 570, 564, 567, - 568, 566, 565, 388, 389, 524, 587, 588, 592, 591, - 589, 590, 593, 596, 597, 598, 599, 600, 601, 603, - 602, 594, 595, 572, 571, 573, 574, 575, 576, 577, - 578, 580, 579, 581, 582, 583, 584, 585, 586, 604, - 605, 606, 607, 608, 610, 609, 614, 613, 611, 612, - 616, 615, 525, 526, 119, 120, 121, 122, 123, 124, - 125, 527, 530, 528, 531, 532, 533, 538, 539, 534, - 535, 536, 537, 540, 399, 397, 398, 394, 393, 392, - 465, 470, 471, 473, 558, 559, 560, 561, 562, 563, - 726, 727, 728, 729, 730, 731, 732, 733, 97, 97, - 94, -174, 96, 96, -410, -77, 96, -291, -289, 104, - 96, 304, -244, -458, 97, -390, -390, -390, 104, 104, - -339, -459, 95, -331, -447, -412, 625, 625, -459, 27, - -422, -421, -333, 94, 85, 67, 620, 623, -459, -459, - -459, 95, -459, -459, -459, 96, 96, -459, -459, -459, + -174, -174, -174, -174, -174, -174, -174, -174, -174, -174, + -239, -174, -459, -207, -206, -208, 745, 129, 33, -352, + -459, -241, 301, -127, -126, -125, 17, -459, -174, -145, + -145, -145, -145, -174, -174, -174, -174, -174, -174, -458, + 74, 21, 19, -292, -331, 270, -458, -292, -458, -340, + -261, -262, 20, 22, -420, -419, -417, -418, 176, 725, + 724, -219, -219, -219, -219, -276, 58, -274, 57, -274, + -285, 22, 22, 97, 22, 97, 150, -311, -174, -246, + -339, 62, -32, -331, -243, -331, -263, -174, 94, -174, + -187, -227, -227, -174, -234, 541, 543, 544, 545, 542, + 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, + 546, 557, 518, 519, 520, 116, 118, 117, 126, 127, + 521, 522, 523, 373, 569, 570, 564, 567, 568, 566, + 565, 388, 389, 524, 587, 588, 592, 591, 589, 590, + 593, 596, 597, 598, 599, 600, 601, 603, 602, 594, + 595, 572, 571, 573, 574, 575, 576, 577, 578, 580, + 579, 581, 582, 583, 584, 585, 586, 604, 605, 606, + 607, 608, 610, 609, 614, 613, 611, 612, 616, 615, + 525, 526, 119, 120, 121, 122, 123, 124, 125, 527, + 530, 528, 531, 532, 533, 538, 539, 534, 535, 536, + 537, 540, 399, 397, 398, 394, 393, 392, 465, 470, + 471, 473, 558, 559, 560, 561, 562, 563, 726, 727, + 728, 729, 730, 731, 732, 733, 97, 97, 94, -174, + 96, 96, -410, -77, 96, -291, -289, 104, 96, 304, + -244, -458, 97, -390, -390, -390, 104, 104, -339, -459, + 95, -331, -447, -412, 625, 625, -459, 27, -422, -421, + -333, 94, 85, 67, 620, 623, -459, -459, -459, 95, + -459, -459, -459, 96, 96, -459, -459, -459, -459, -459, -459, -459, -459, -459, -459, -459, -459, -459, -459, -459, - -459, -459, -459, -459, -459, -459, -459, -459, -459, 95, - -459, -206, -208, -459, 84, -187, -263, 22, -124, 326, - 328, -124, -459, -459, -459, -459, -459, 95, -459, -459, - 95, -459, 95, -459, -459, -292, -459, 22, 22, 95, - -459, -292, -459, -292, -226, -262, -134, -133, -132, 652, - -174, -239, -459, 95, -331, -277, 59, 84, 133, 97, - 97, 97, 15, -458, -243, 237, -344, -268, -289, -204, - 413, -263, -459, -289, 96, 96, 786, 150, 96, -244, - -151, -458, 300, -339, 97, 97, -141, -144, -32, 95, - 165, -289, -219, 67, -174, -239, -459, 84, 633, 745, - -118, -117, -114, 756, 782, -239, -120, -120, -174, -174, - -174, -459, -331, 270, -459, -459, -134, 95, -131, -130, - -331, -356, 621, -81, -82, -83, -8, 342, 269, 253, - 284, -417, -357, 84, 133, -303, -289, -344, -331, 96, - -459, -458, -268, 96, -272, 94, -3, 300, -364, -415, - -365, -366, -5, -6, -391, -108, -421, -395, -337, -333, - 97, 104, 96, 621, -459, -459, -116, 158, 754, 716, - -183, 236, -459, 95, -459, 95, -459, 95, -132, 95, - 27, 626, 787, -84, -85, -83, -82, -174, -289, -59, - -331, 256, 257, 258, -65, -63, -64, 260, -331, -459, - -340, -205, -203, -331, 676, -438, -437, 617, -448, -444, - 129, 156, 109, -446, 713, 718, 670, 139, 140, -174, - 94, -459, 237, -429, 622, -116, 755, 690, 664, 690, - 664, -179, -174, -174, -174, -130, -458, 164, -83, 161, - -357, 255, 262, -66, -67, 34, -170, 65, -459, 95, - 25, -357, -79, 687, -435, -436, 84, -439, 419, 686, - 707, 129, 97, 104, 96, -289, -338, -423, 623, 155, - -145, -459, 95, -459, 95, -459, -119, -85, -273, 33, - 25, 25, -68, -69, 453, 454, 455, 456, 457, 458, - 459, 460, 461, 462, 463, 464, -68, 97, -203, 683, - -370, -187, -436, 84, -435, 84, 16, 15, -4, 785, - 96, -116, 690, 664, -174, -174, -459, -89, -88, -87, - 163, -458, -178, -60, -61, -62, -64, 261, 156, 259, - 104, -63, -62, 165, -78, 28, -204, -434, 283, 278, - 281, 34, -434, 104, -4, -459, -459, -86, 162, -87, - -174, -174, -82, 95, 254, -183, 687, 277, 33, 129, - 164, -85, 161, -459, -61, -187, 269, -85, -207, -206, - -206, + -459, -459, -459, -459, -459, -459, -459, 95, -459, -206, + -208, -459, 84, -187, -263, 22, -124, 326, 328, -124, + -459, -459, -459, -459, -459, 95, -459, -459, 95, -459, + 95, -459, -459, -292, -459, 22, 22, 95, -459, -292, + -459, -292, -226, -262, -134, -133, -132, 652, -174, -239, + -459, 95, -331, -277, 59, 84, 133, 97, 97, 97, + 15, -458, -243, 237, -344, -268, -289, -204, 413, -263, + -459, -289, 96, 96, 786, 150, 96, -244, -151, -458, + 300, -339, 97, 97, -141, -144, -32, 95, 165, -289, + -219, 67, -174, -239, -459, 84, 633, 745, -118, -117, + -114, 756, 782, -239, -120, -120, -174, -174, -174, -459, + -331, 270, -459, -459, -134, 95, -131, -130, -331, -356, + 621, -81, -82, -83, -8, 342, 269, 253, 284, -417, + -357, 84, 133, -303, -289, -344, -331, 96, -459, -458, + -268, 96, -272, 94, -3, 300, -364, -415, -365, -366, + -5, -6, -391, -108, -421, -395, -337, -333, 97, 104, + 96, 621, -459, -459, -116, 158, 754, 716, -183, 236, + -459, 95, -459, 95, -459, 95, -132, 95, 27, 626, + 787, -84, -85, -83, -82, -174, -289, -59, -331, 256, + 257, 258, -65, -63, -64, 260, -331, -459, -340, -205, + -203, -331, 676, -438, -437, 617, -448, -444, 129, 156, + 109, -446, 713, 718, 670, 139, 140, -174, 94, -459, + 237, -429, 622, -116, 755, 690, 664, 690, 664, -179, + -174, -174, -174, -130, -458, 164, -83, 161, -357, 255, + 262, -66, -67, 34, -170, 65, -459, 95, 25, -357, + -79, 687, -435, -436, 84, -439, 419, 686, 707, 129, + 97, 104, 96, -289, -338, -423, 623, 155, -145, -459, + 95, -459, 95, -459, -119, -85, -273, 33, 25, 25, + -68, -69, 453, 454, 455, 456, 457, 458, 459, 460, + 461, 462, 463, 464, -68, 97, -203, 683, -370, -187, + -436, 84, -435, 84, 16, 15, -4, 785, 96, -116, + 690, 664, -174, -174, -459, -89, -88, -87, 163, -458, + -178, -60, -61, -62, -64, 261, 156, 259, 104, -63, + -62, 165, -78, 28, -204, -434, 283, 278, 281, 34, + -434, 104, -4, -459, -459, -86, 162, -87, -174, -174, + -82, 95, 254, -183, 687, 277, 33, 129, 164, -85, + 161, -459, -61, -187, 269, -85, -207, -206, -206, } var yyDef = [...]int{ - 960, -2, 1, 2, -2, 962, 960, 4, 5, 7, + 962, -2, 1, 2, -2, 964, 962, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 131, 133, 134, 960, 960, - 960, 0, 960, 0, 192, 0, 1021, -2, -2, 960, - 1737, 0, 960, 0, 955, 0, -2, 875, 881, 0, - 890, -2, 0, 0, 960, 960, 2413, 2413, 955, 0, - 0, 0, 0, 0, 960, 960, 960, 960, 1742, 1573, - 111, 960, 0, 149, 150, 960, 910, 911, 912, 126, - 0, 2411, 146, 960, 961, 3, 132, 136, 0, 0, - 0, 119, 1582, 0, 139, 0, 0, 964, 0, 0, - 1720, 960, 960, 0, 190, 191, 0, 0, 0, 0, - 0, 195, -2, 227, 228, 229, 0, 234, 679, 596, - 648, 594, 633, -2, 582, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 599, 471, 471, - 0, 0, -2, 582, 582, 582, 1722, 0, 0, 0, - 630, 533, 471, 471, 471, 0, 471, 471, 471, 471, - 0, 0, 471, 471, 471, 471, 471, 471, 471, 471, - 471, 471, 471, 471, 471, 471, 471, 471, 471, 1600, - 233, 1738, 1735, 1736, 1910, 1911, 1912, 1913, 1914, 1915, - 1916, 1917, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, - 1926, 1927, 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, - 1936, 1937, 1938, 1939, 1940, 1941, 1942, 1943, 1944, 1945, - 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, - 1956, 1957, 1958, 1959, 1960, 1961, 1962, 1963, 1964, 1965, - 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, - 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, - 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, - 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, - 2026, 2027, 2028, 2029, 2030, 2031, 2032, 2033, 2034, 2035, - 2036, 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045, - 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, - 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, - 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, - 2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085, - 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, - 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, - 2106, 2107, 2108, 2109, 2110, 2111, 2112, 2113, 2114, 2115, - 2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, - 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, - 2136, 2137, 2138, 2139, 2140, 2141, 2142, 2143, 2144, 2145, - 2146, 2147, 2148, 2149, 2150, 2151, 2152, 2153, 2154, 2155, - 2156, 2157, 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165, - 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, - 2176, 2177, 2178, 2179, 2180, 2181, 2182, 2183, 2184, 2185, - 2186, 2187, 2188, 2189, 2190, 2191, 2192, 2193, 2194, 2195, - 2196, 2197, 2198, 2199, 2200, 2201, 2202, 2203, 2204, 2205, - 2206, 2207, 2208, 2209, 2210, 2211, 2212, 2213, 2214, 2215, - 2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224, 2225, - 2226, 2227, 2228, 2229, 2230, 2231, 2232, 2233, 2234, 2235, - 2236, 2237, 2238, 2239, 2240, 2241, 2242, 2243, 2244, 2245, - 2246, 2247, 2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, - 2256, 2257, 2258, 2259, 2260, 2261, 2262, 2263, 2264, 2265, - 2266, 2267, 2268, 2269, 2270, 2271, 2272, 2273, 2274, 2275, - 2276, 2277, 2278, 2279, 2280, 2281, 2282, 2283, 2284, 2285, - 2286, 2287, 2288, 2289, 2290, 2291, 2292, 2293, 2294, 2295, - 2296, 2297, 2298, 2299, 2300, 2301, 2302, 2303, 2304, 2305, - 2306, 2307, 2308, 2309, 2310, 2311, 2312, 2313, 2314, 2315, - 2316, 2317, 2318, 2319, 2320, 2321, 2322, 2323, 2324, 2325, - 2326, 2327, 2328, 2329, 2330, 2331, 2332, 2333, 2334, 2335, - 2336, 2337, 2338, 2339, 2340, 2341, 2342, 2343, 2344, 2345, - 2346, 2347, 2348, 2349, 2350, 2351, 2352, 2353, 2354, 2355, - 2356, 2357, 2358, 2359, 2360, 2361, 2362, 2363, 2364, 2365, - 2366, 2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, - 2376, 2377, 2378, 2379, 2380, 2381, 2382, 2383, 2384, 2385, - 2386, 2387, 2388, 2389, 2390, 2391, 2392, 2393, 2394, 2395, - 2396, 2397, 2398, 2399, 2400, 2401, 2402, 2403, 2404, 2405, - 2406, 2407, 2408, 2409, 2410, 0, 1714, 0, 793, 1064, - 0, 956, 957, 0, 864, 864, 0, 864, 864, 864, - 864, 0, 0, 0, 807, 0, 0, 0, 0, 861, - 0, 823, 824, 0, 861, 0, 830, 867, 0, 0, - 837, 864, 864, 840, 2414, 0, 2414, 2414, 0, 0, - 1705, 0, 858, 856, 870, 871, 103, 874, 877, 878, - 879, 880, 883, 0, 894, 897, 1731, 1732, 0, 899, - 904, 923, 924, 0, 106, 1224, 0, 1088, 0, 1099, - -2, 1110, 1127, 1128, 1129, 1130, 1131, 1133, 1134, 1135, - 0, 0, 0, 0, 1140, 1141, 0, 0, 0, 0, - 0, 1204, 0, 0, 0, 0, 2125, 1544, 0, 0, - 1506, 1506, 1240, 1506, 1506, 1508, 1508, 1508, 1969, 2116, - 2126, 2314, 1924, 1930, 1931, 1932, 2259, 2260, 2261, 2262, - 2357, 2358, 2362, 2036, 1919, 2329, 2330, 0, 2410, 2076, - 2084, 2085, 2061, 2070, 2109, 2216, 2341, 1943, 2104, 2178, - 2032, 2056, 2057, 2197, 2198, 2080, 2081, 2060, 2265, 2267, - 2283, 2284, 2269, 2271, 2280, 2286, 2291, 2270, 2282, 2287, - 2300, 2304, 2307, 2308, 2309, 2277, 2275, 2288, 2292, 2294, - 2296, 2302, 2305, 2278, 2276, 2289, 2293, 2295, 2297, 2303, - 2306, 2264, 2268, 2272, 2281, 2299, 2279, 2298, 2273, 2285, - 2290, 2301, 2274, 2266, 2074, 2077, 2064, 2065, 2067, 2069, - 2075, 2082, 2088, 2066, 2087, 2086, 0, 2062, 2063, 2068, - 2079, 2083, 2071, 2072, 2073, 2078, 2089, 2132, 2131, 2130, - 2177, 2100, 2176, 0, 0, 0, 0, 0, 1913, 1976, - 1977, 2311, 1428, 1429, 1430, 1431, 0, 0, 0, 0, - 0, 0, 0, 360, 361, 1557, 1558, 105, 1223, 1701, - 1508, 1508, 1508, 1508, 1508, 1508, 1162, 1163, 1164, 1165, - 1166, 1192, 1193, 1199, 1200, 2192, 2193, 2194, 2195, 2014, - 2352, 2023, 2024, 2173, 2174, 2038, 2039, 2384, 2385, -2, - -2, -2, 302, 303, 304, 305, 306, 307, 308, 309, - 0, 1975, 2327, 2328, 298, 0, 1699, 1700, 365, 362, - 363, 364, 1206, 1207, 318, 319, 320, 321, 322, 323, - 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, - 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, - 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 0, 367, 368, 2413, - 0, 933, 0, 0, 0, 0, 0, 0, 1743, 1744, - 1582, 0, 1574, 1573, 124, 0, 960, -2, 0, 0, - 0, 0, -2, 108, 0, 113, 1021, 0, 963, 138, - 137, 1633, 1636, 0, 0, 0, 1643, 1645, 1646, 1647, - 102, 120, 1583, 128, 130, 1584, 0, 965, 966, 0, - 997, 1001, 0, 0, 0, 1721, 1720, 1720, 166, 0, - 0, 167, 187, 188, 189, 0, 0, 173, 174, 1707, - 1708, 104, 0, 0, 245, 246, 0, 1180, 498, 0, - 241, 0, 491, 430, 0, 0, 0, 1025, 230, 231, - 232, 471, 471, 471, 645, 0, 0, 233, 233, 603, - 604, 605, 0, 0, -2, 496, 0, 583, 0, 0, - 485, 485, 489, 487, 488, 0, 0, 0, 0, 0, - 0, 0, 0, 622, 0, 623, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 740, 0, 472, 0, 643, - 644, 534, 0, 0, 0, 0, 0, 0, 0, 0, - 1723, 1724, 0, 620, 621, 0, 0, 0, 471, 471, - 0, 0, 0, 0, 471, 471, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 221, 1623, 0, 0, 222, 223, - 1601, 0, -2, 0, 784, 0, 0, 0, 1716, 1716, - 1716, 0, 1715, 792, 0, 0, 0, 797, 0, 0, - 798, 0, 861, 861, 859, 860, 800, 801, 802, 803, - 864, 0, 0, 480, 481, 482, 861, 864, 0, 864, - 864, 864, 864, 861, 861, 861, 864, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 2414, 867, 864, 0, - 831, 0, 832, 833, 834, 835, 838, 839, 841, 2415, - 2416, 1733, 1734, 1745, 1746, 1747, 1748, 1749, 1750, 1751, - 1752, 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, - 1762, 1763, 1764, 1765, 1766, 1767, 1768, 1769, 1770, 1771, - 1772, 1773, 1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, - 1782, 1783, 1784, 1785, 1786, 1787, 1788, 1789, 1790, 1791, - 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800, 1801, - 1802, 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, 1811, - 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819, 1820, 1821, - 1822, 1823, 1824, 1825, 1826, 1827, 1828, 1829, 1830, 1831, - 1832, 1833, 1834, 1835, 1836, 1837, 1838, 1839, 1840, 1841, - 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, 1851, - 1852, 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, 1861, - 1862, 1863, 1864, 1865, 1866, 1867, 1868, 1869, 1870, 1871, - 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881, - 1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 1891, - 1892, 1893, 1894, 1895, 1896, 1897, 1898, 1899, 1900, 1901, - 1902, 1903, 1904, 1905, 1906, 1907, 1908, 1909, 2414, 2414, - 845, 849, 853, 851, 1706, 876, 882, 884, 885, 0, - 0, 895, 898, 917, 110, 2022, 903, 110, 905, 906, - 907, 908, 909, 935, 936, 941, 0, 0, 0, 0, - 947, 948, 949, 0, 0, 952, 953, 954, 0, 0, - 0, 0, 0, 1086, 0, 0, 1212, 1213, 1214, 1215, - 1216, 1217, 1218, 1219, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1111, 1112, 0, 0, 0, 1136, 1137, 1138, - 1139, 1142, 0, 1153, 0, 1155, 1553, -2, 0, 0, - 0, 1147, 1148, 0, 0, 0, 1726, 1726, 0, 0, - 0, 1545, 0, 0, 1238, 0, 1239, 1241, 1242, 1243, - 0, 1244, 1245, 970, 970, 970, 970, 970, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 970, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1726, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1726, 0, 0, - 1726, 1726, 0, 0, 290, 291, 292, 293, 294, 295, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 366, 310, 311, 312, 313, 314, - 369, 315, 316, 317, 1223, 0, 0, 960, 0, 107, - 925, 926, 0, 1047, 1726, 0, 0, 976, 0, 1741, - 118, 127, 129, 1582, 122, 1582, 0, 980, 0, 0, - -2, -2, 981, 982, 986, 987, 988, 989, 990, 991, - 992, 993, 994, 115, 2412, 116, 0, 135, 1605, 0, - 1600, 1623, 0, 0, 0, 0, 1718, 1624, 0, 0, - 0, 109, 0, 140, 141, 1689, 1693, 0, 1634, 0, - 1637, 0, 0, 0, 444, 1641, 0, 0, 0, 1575, - 1576, 1579, 0, 998, 2122, 1002, 0, 1004, 1005, 0, - 0, 164, 0, 1063, 0, 0, 0, 175, 0, 177, - 178, 0, 0, 0, 455, 1709, 1710, 1711, -2, 478, - 0, 455, 439, 377, 378, 379, 430, 381, 430, 430, - 430, 430, 430, 444, 444, 444, 430, 413, 414, 415, - 416, 0, 430, 0, 398, 430, 430, 430, 430, 420, - 421, 422, 423, 424, 425, 426, 427, 382, 383, 384, - 385, 386, 387, 388, 389, 390, 432, 432, 432, 432, - 432, 436, 436, 0, 1181, 0, 459, 0, 1579, 0, - 0, 1609, 1022, 0, 0, 0, 0, 646, 690, 597, - 634, 647, 0, 600, 601, -2, 0, 0, 582, 0, - 584, 0, 479, 0, -2, 0, 489, 0, 485, 489, - 486, 489, 477, 490, 624, 625, 626, 0, 628, 629, - 720, 1033, 0, 0, 0, 0, 0, 726, 727, 728, - 0, 730, 731, 732, 733, 734, 735, 736, 737, 738, - 739, 635, 636, 637, 638, 639, 640, 641, 642, 0, - 0, 0, 0, 584, 0, 631, 0, 0, 535, 536, - 537, 0, 0, 540, 541, 542, 543, 0, 0, 546, - 547, 548, 1050, 1051, 549, 550, 575, 576, 577, 551, - 552, 553, 554, 555, 556, 557, 569, 570, 571, 572, - 573, 574, 558, 559, 560, 561, 562, 563, 566, 0, - 215, 1605, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1716, 0, - 0, 0, 0, 0, 979, 1065, 1739, 1740, 794, 0, - 0, 865, 866, 0, 483, 484, 864, 864, 804, 846, - 0, 864, 808, 847, 809, 811, 810, 812, 825, 826, - 864, 815, 862, 863, 816, 817, 818, 819, 820, 821, - 822, 842, 827, 828, 829, 868, 0, 872, 873, 843, - 844, 0, 854, 0, 0, 0, 888, 889, 0, 896, - 920, 918, 919, 921, 913, 914, 915, 916, 0, 922, - 0, 0, 938, 160, 943, 944, 945, 946, 958, 951, - 1225, 1083, 1084, 1085, 0, 1087, 1093, 0, 1208, 1210, - 1091, 1092, 1095, 0, 0, 0, 1089, 1100, 1220, 1221, - 1222, 0, 0, 0, 0, 0, 1104, 1108, 1113, 1114, - 1115, 1116, 1117, 0, 1118, 0, 1121, 1122, 1123, 1124, - 1125, 1126, 1132, 1521, 1522, 1523, 1151, 370, 371, 0, - 1152, 0, 0, 0, 0, 0, 0, 0, 0, 1468, - 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, 1478, - 1479, 1480, 1481, 1482, 1483, 1484, 1485, 1486, 1487, 1224, - 0, 1727, 0, 0, 0, 1551, 1548, 0, 0, 0, - 1507, 1509, 0, 0, 0, 971, 972, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1488, 1489, 1490, 1491, 1492, 1493, - 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, - 1504, 1505, 0, 0, 1524, 0, 0, 0, 0, 0, - 0, 0, 1544, 0, 1157, 1158, 1159, 0, 0, 0, - 0, 0, 0, 1286, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 206, 207, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1432, - 1433, 1434, 1435, 0, 0, 0, 0, 0, 0, 0, - 1555, 0, -2, -2, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1457, 0, 0, - 0, 0, 0, 0, 1697, 0, 0, 928, 929, 931, - 0, 1067, 0, 1048, 0, 0, 934, 0, 975, 0, - 978, 121, 123, 984, 985, 0, 1006, 995, 983, 117, - 1718, 0, 0, 1718, 1623, 1605, 1728, 0, 0, 0, - 0, 0, 196, 0, 112, 0, 0, 0, 1635, 1638, - 1639, 444, 1666, 0, 453, 453, 450, 1644, 1585, 1586, - 0, 1578, 1580, 1581, 142, 1003, 999, 0, 1081, 0, - 0, 1062, 0, 1009, 1011, 1012, 1013, 1045, 0, 1016, - 1017, 0, 0, 0, 0, 0, 162, 1064, 168, 0, - 176, 0, 0, 181, 182, 169, 170, 171, 172, 0, - 679, -2, 530, 247, 249, 250, 251, 242, -2, 442, - 440, 441, 380, 444, 444, 406, 407, 444, 409, 410, - 411, 412, 0, 418, 0, 399, 400, 401, 402, 391, - 0, 392, 393, 394, 434, 0, 395, 396, 0, 397, - 497, 0, 1587, 460, 461, 463, 471, 0, 466, 467, - 0, 471, 471, 0, 492, 493, 0, 1579, 194, 1611, - 1026, 235, 236, 237, 238, 239, 240, 715, 0, 0, - 691, 713, 714, 233, 0, 0, 243, 586, 585, 0, - 747, 0, 495, 0, 0, 489, 489, 474, 475, 627, - 0, 0, 722, 723, 724, 725, 0, 0, 0, 613, - 524, 0, 614, 615, 584, 586, 0, 0, 455, 538, - 539, 544, 545, 564, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 662, 663, 665, 668, 670, 588, - 674, 676, 0, 664, 667, 669, 671, 588, 675, 677, - 1602, 1603, 1604, 0, 0, 785, 0, 0, 521, 158, - 1717, 790, 791, 795, 796, 861, 814, 848, 861, 806, - 813, 836, 850, 852, 886, 887, 892, 900, 901, 902, - 942, 0, 0, 0, 0, 950, 0, 0, 1094, 1209, - 1211, 1096, 1097, 1098, 1101, 0, 1105, 1109, 0, 0, - 0, 0, 0, 1156, 1154, 1555, 0, 0, 0, 1205, - 0, 0, 1228, 1229, 0, 0, 0, 0, 1549, 0, - 0, 1236, 0, 1510, 1186, 0, 0, 0, 0, 0, - 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, - 1573, 1263, 0, 0, 0, 0, 0, 1268, 1269, 1270, - 1186, 0, 1273, 1274, 0, 1276, 0, 1277, 0, 0, - 0, 0, 1284, 1285, 1287, 0, 0, 1290, 1291, 0, - 1293, 0, 1295, 1296, 1297, 1298, 1299, 1300, 0, 1302, - 0, 1304, 1305, 1306, 0, 1308, 0, 1310, 1311, 0, - 1313, 0, 1315, 0, 1318, 0, 1321, 0, 1324, 0, - 1327, 0, 1330, 0, 1333, 0, 1336, 0, 1339, 0, - 1342, 0, 1345, 0, 1348, 0, 1351, 0, 1354, 0, - 1357, 0, 1360, 0, 1363, 1364, 1365, 0, 1367, 0, - 1369, 0, 1372, 1373, 0, 1375, 0, 1378, 0, 1381, - 0, 0, 1382, 0, 0, 0, 1386, 0, 0, 0, - 0, 1395, 1396, 1397, 1398, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1409, 1410, 1411, 1412, 1413, - 1414, 0, 1416, 0, 1187, 0, 0, 1187, 0, 0, - 0, 0, 0, 1226, 1726, 0, 1511, 1512, 1513, 1514, - 1515, 0, 0, 0, 0, 0, 0, 1455, 1456, 1458, - 0, 0, 1461, 0, 1463, 0, 1698, 927, 930, 932, - 1019, 1068, 1069, 0, 0, 0, 0, 1049, 1725, 973, - 974, 977, 1027, 0, 1559, 0, 0, 1006, 1081, 0, - 1007, 0, 0, 0, 0, 0, 1605, 0, 0, 1729, - 1728, 1728, 1728, 220, 0, 1625, 1626, 1631, 1629, 1630, - 114, 1690, 1694, 1648, 1642, 1660, 1673, 453, 453, 447, - 448, 454, 449, 451, 452, 1577, 0, 1582, 0, 1687, - 0, 960, 1676, 0, 0, 0, 0, 0, 0, 0, - 0, 1052, 0, 0, 1055, 0, 0, 0, 0, 1046, - 1017, 0, 1018, 0, -2, 0, 0, 156, 157, 0, - 0, 0, 179, 180, 0, 0, 186, 456, 457, 224, - 233, 532, 248, 505, 0, 0, 376, 443, 403, 404, - 405, 408, 0, 428, 0, 0, 0, 0, 526, 193, - 1591, 1590, 471, 471, 462, 0, 465, 0, 0, 0, - 1730, 431, 494, 0, 1612, 1613, 685, 0, 0, 692, - 0, 0, 0, 595, 0, 606, 607, 0, 719, -2, - 781, 459, 0, 473, 476, 1034, 0, 0, 608, 0, - 611, 612, 525, 586, 617, 618, 632, 619, 567, 568, - 565, 0, 197, 653, 655, 659, 654, 658, 0, 0, - 0, 590, 0, 678, 590, 651, 0, 521, 1587, 0, - 789, 522, 523, 864, 864, 937, 161, 0, 940, 0, - 0, 0, 0, 1102, 1106, 1119, 1120, 1516, 1542, 430, - 430, 1529, 430, 436, 1532, 430, 1534, 430, 1537, 430, - 1540, 1541, 0, 0, 1149, 0, 0, 0, 0, 1235, - 1552, 0, 0, 1246, 1185, 1186, 1186, 1186, 1186, 1186, - 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, - 1546, 0, 0, 0, 1267, 0, 0, 1271, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 208, 209, 0, - 0, 0, 0, 0, 0, 1466, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1180, 1184, 0, - 1188, 1189, 0, 0, 1418, 0, 0, 1436, 0, 0, - 0, 0, 0, 0, 0, 1556, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1070, 1077, 0, 1077, - 0, 1077, 0, 0, 0, 1712, 1713, 1560, 1561, 1081, - 1562, 996, 1008, 0, 212, 1606, 1607, 1608, 211, 0, - 0, 0, 0, 0, 0, 1719, 0, 1628, 1632, 1666, - 0, 1659, 0, -2, 1668, 0, 0, 0, 1674, 445, - 446, 1000, 143, 1082, 147, 0, 1687, 1702, 0, 1684, - 1691, 1695, 0, 0, 0, 1680, 0, 1081, 1010, 1041, - 1043, 0, 1038, 1053, 1054, 1056, 0, 1058, 0, 1060, - 1061, 1021, 1015, 0, 164, 0, 1081, 1081, 163, 0, - 1066, 183, 184, 185, 531, 252, 257, 0, 0, 0, - 262, 0, 264, 0, 0, 0, 269, 270, 471, 471, - 506, 0, 373, 375, 0, 0, 255, 444, 0, 444, - 0, 435, 437, 0, 507, 527, 1588, 1589, 0, 0, - 464, 468, 469, 470, 0, 688, 0, 716, 0, 0, - 0, 0, 0, 0, 244, 587, 748, 749, 750, 751, - 752, 753, 754, 755, 756, 0, 471, 0, 0, 0, - 471, 471, 471, 0, 773, 458, 0, 0, 744, 741, - 609, 0, 288, 289, 296, 297, 299, 0, 0, 0, - 0, 0, 616, 1021, 200, 0, 0, 0, 0, 661, - 666, 672, 0, 589, 673, 786, 787, 788, 159, 799, - 805, 939, 959, 1090, 1103, 1107, 0, 0, 0, 0, - 1543, 1527, 444, 1530, 1531, 1533, 1535, 1536, 1538, 1539, - 1145, 1146, 1150, 0, 1232, 0, 1234, 0, 1550, 0, - 1247, 1248, 1249, 1250, 1251, 1582, 0, 0, 0, 1266, - 0, 0, 1186, 0, 1279, 1278, 1280, 0, 1282, 1283, - 1288, 1289, 1292, 1294, 1301, 1303, 1307, 1309, 1312, 1314, - 1316, 0, 1319, 0, 1322, 0, 1325, 0, 1328, 0, - 1331, 0, 1334, 0, 1337, 0, 1340, 0, 1343, 0, - 1346, 0, 1349, 0, 1352, 0, 1355, 0, 1358, 0, - 1361, 0, 1366, 1368, 0, 1371, 1374, 1376, 0, 1379, - 0, 1383, 0, 1385, 1387, 1388, 0, 0, 0, 1399, - 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1415, - 0, 1178, 1417, 1190, 1191, 1196, 1420, 0, 0, 0, - 1423, 0, 0, 0, 1427, 1227, 1438, 0, 1443, 0, - 0, 1449, 0, 1453, 0, 1459, 1460, 1462, 1464, 0, - 0, 0, 0, 0, 0, 0, 1047, 1028, 125, 1562, - 1566, 0, -2, 0, 214, 216, 0, 0, 0, 1627, - 1653, 1651, 1651, 1661, 1662, 0, 0, 1669, 0, 0, - 0, 0, 148, 0, 0, 1675, 0, 0, 1696, 0, - 0, 0, 0, 165, 1573, 1035, 1042, 0, 0, 1036, - 0, 1037, 1057, 1059, 1014, 0, 1081, 1081, 154, 155, - 0, 258, 0, 260, 0, 263, 265, 266, 267, 273, - 274, 275, 276, 268, 0, 0, 372, 374, 0, 0, - 417, 429, 419, 0, 0, 1592, 1593, 1594, 1595, 1596, - 1597, 1598, 1599, 1610, 680, 0, 690, 0, 1023, 0, - 683, 0, 598, 0, 0, 0, 471, 471, 471, 0, - 0, 0, 0, 758, 0, 0, 721, 0, 729, 0, - 0, 0, 300, 301, 0, 652, 0, 198, 199, 0, - 0, 657, 591, 592, 1143, 0, 0, 0, 1144, 1528, - 0, 0, 0, 0, 0, 1547, 0, 0, 0, 0, - 1272, 1275, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1391, 0, 0, 0, 710, 711, - 0, 1467, 1183, 1573, 0, 1187, 1197, 1198, 0, 1187, - 1437, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1078, 0, 0, 0, 1029, 1030, 0, 0, - 0, 1067, 1566, 1571, 0, 0, 0, 1615, 1616, 0, - 1620, 1621, 1622, 213, 217, 218, 219, 1656, 0, 1649, - 1652, 1650, 1663, 0, 0, 1670, 0, 1672, 0, 1703, - 1704, 1692, 1685, 960, 1679, 1682, 1684, 1681, 1582, 1039, - 0, 1044, 0, 1573, 153, 0, 261, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 271, 272, - 0, 0, 433, 438, 0, 0, 681, 0, 1024, 693, - 684, 0, 771, 0, 775, 0, 0, 0, 778, 779, - 780, 757, 0, 761, 499, 745, 742, 743, 610, 0, - 201, 202, 0, 0, 0, 1517, 0, 1520, 1230, 1233, - 1231, 0, 1262, 1264, 1265, 1525, 1526, 1281, 1317, 1320, - 1323, 1326, 1329, 1332, 1335, 1338, 1341, 1344, 1347, 1350, - 1353, 1356, 1359, 1362, 1370, 1377, 1380, 1384, 1389, 0, - 1392, 0, 0, 1393, 0, 712, 1174, 0, 0, 1194, - 1195, 0, 1422, 1424, 1425, 1426, 1439, 0, 1444, 1445, - 0, 1450, 0, 1454, 1465, 0, 1072, 1079, 1080, 0, - 1075, 0, 1076, 0, 1020, 1571, 145, 1572, 1569, 0, - 1567, 1564, 110, 1619, 0, 1640, 0, 1654, 1655, 1664, - 1665, 1671, 0, 0, 1684, 0, 1678, 151, 0, 0, - 0, 1582, 259, 0, 279, 689, 0, 692, 682, 769, - 770, 0, 782, 774, 776, 777, 759, -2, 1609, 0, - 0, 0, 660, 1518, 0, 0, 1394, 0, 708, 709, - 1182, 1175, 0, 1160, 1161, 1179, 1419, 1421, 0, 0, - 0, 1071, 1031, 1032, 1073, 1074, 144, 0, 1568, 1202, - 0, 1563, 0, 210, 89, 90, 43, -2, 0, 0, - 0, 1617, 1618, 1657, 1658, 1688, 0, 1677, 1683, 1040, - 1047, 0, 152, 512, 505, 0, 0, 0, 762, 763, - 764, 765, 766, 767, 768, 649, 203, 204, 0, 579, - 580, 581, 197, 0, 1237, 1390, 1176, 0, 0, 0, - 0, 0, 1440, 0, 1446, 0, 1451, 0, 1570, 0, - 0, 1565, 88, 0, -2, 93, 0, 0, 0, 0, - 1025, 67, 68, 69, 50, 74, 75, 83, 77, 1686, - 694, 0, 696, 0, -2, 500, 513, 0, 253, 280, - 281, 0, 0, 284, 0, 286, 287, 277, 278, 0, - 0, 783, 0, 200, 0, 0, 1167, 1168, 1169, 1170, - 1172, 0, 0, 0, 0, 1203, 1180, 44, 94, 110, - 85, 0, 0, 49, 51, 0, 0, 84, 695, 0, - 0, 455, 0, 705, 501, 502, 0, 508, 509, 510, - 511, 282, 283, 285, 717, 0, 578, 656, 1519, 0, - 0, 1441, 0, 1447, 0, 1452, 0, -2, 46, 0, - 0, 0, 52, 0, 55, 56, 57, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 53, 76, 697, 698, - 706, 0, 503, 0, 504, 0, 0, 0, 686, 0, - 717, 1177, 1171, 1173, 0, 0, 1201, 95, 98, 100, - 0, 0, 87, 110, 71, 78, 79, 80, 0, 82, - 72, 73, 48, 0, 0, 707, 703, 514, 516, 517, - 0, 0, 515, 718, 687, 1442, 1448, 0, 110, 99, - 0, 0, 47, 0, 81, 54, 0, 518, 519, 520, - 0, -2, 110, 86, 70, 699, 45, -2, 700, 701, - 702, + 38, 39, 40, 41, 42, 131, 133, 134, 962, 962, + 962, 0, 962, 0, 194, 0, 1023, -2, -2, 962, + 1739, 0, 962, 0, 957, 0, -2, 877, 883, 0, + 892, -2, 0, 0, 962, 962, 2415, 2415, 957, 0, + 0, 0, 0, 0, 962, 962, 962, 962, 1744, 1575, + 111, 962, 0, 151, 152, 962, 912, 913, 914, 126, + 0, 2413, 148, 962, 963, 3, 132, 136, 0, 0, + 0, 119, 1584, 0, 139, 0, 0, 966, 0, 0, + 1722, 962, 962, 0, 192, 193, 0, 0, 0, 0, + 0, 197, -2, 229, 230, 231, 0, 236, 681, 598, + 650, 596, 635, -2, 584, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 601, 473, 473, + 0, 0, -2, 584, 584, 584, 1724, 0, 0, 0, + 632, 535, 473, 473, 473, 0, 473, 473, 473, 473, + 0, 0, 473, 473, 473, 473, 473, 473, 473, 473, + 473, 473, 473, 473, 473, 473, 473, 473, 473, 1602, + 235, 1740, 1737, 1738, 1912, 1913, 1914, 1915, 1916, 1917, + 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927, + 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, + 1938, 1939, 1940, 1941, 1942, 1943, 1944, 1945, 1946, 1947, + 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, + 1958, 1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, + 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, + 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, + 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, + 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, + 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, + 2028, 2029, 2030, 2031, 2032, 2033, 2034, 2035, 2036, 2037, + 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045, 2046, 2047, + 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, + 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, + 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2077, + 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, + 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, + 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107, + 2108, 2109, 2110, 2111, 2112, 2113, 2114, 2115, 2116, 2117, + 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, + 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, 2137, + 2138, 2139, 2140, 2141, 2142, 2143, 2144, 2145, 2146, 2147, + 2148, 2149, 2150, 2151, 2152, 2153, 2154, 2155, 2156, 2157, + 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165, 2166, 2167, + 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176, 2177, + 2178, 2179, 2180, 2181, 2182, 2183, 2184, 2185, 2186, 2187, + 2188, 2189, 2190, 2191, 2192, 2193, 2194, 2195, 2196, 2197, + 2198, 2199, 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, + 2208, 2209, 2210, 2211, 2212, 2213, 2214, 2215, 2216, 2217, + 2218, 2219, 2220, 2221, 2222, 2223, 2224, 2225, 2226, 2227, + 2228, 2229, 2230, 2231, 2232, 2233, 2234, 2235, 2236, 2237, + 2238, 2239, 2240, 2241, 2242, 2243, 2244, 2245, 2246, 2247, + 2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, 2256, 2257, + 2258, 2259, 2260, 2261, 2262, 2263, 2264, 2265, 2266, 2267, + 2268, 2269, 2270, 2271, 2272, 2273, 2274, 2275, 2276, 2277, + 2278, 2279, 2280, 2281, 2282, 2283, 2284, 2285, 2286, 2287, + 2288, 2289, 2290, 2291, 2292, 2293, 2294, 2295, 2296, 2297, + 2298, 2299, 2300, 2301, 2302, 2303, 2304, 2305, 2306, 2307, + 2308, 2309, 2310, 2311, 2312, 2313, 2314, 2315, 2316, 2317, + 2318, 2319, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, + 2328, 2329, 2330, 2331, 2332, 2333, 2334, 2335, 2336, 2337, + 2338, 2339, 2340, 2341, 2342, 2343, 2344, 2345, 2346, 2347, + 2348, 2349, 2350, 2351, 2352, 2353, 2354, 2355, 2356, 2357, + 2358, 2359, 2360, 2361, 2362, 2363, 2364, 2365, 2366, 2367, + 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376, 2377, + 2378, 2379, 2380, 2381, 2382, 2383, 2384, 2385, 2386, 2387, + 2388, 2389, 2390, 2391, 2392, 2393, 2394, 2395, 2396, 2397, + 2398, 2399, 2400, 2401, 2402, 2403, 2404, 2405, 2406, 2407, + 2408, 2409, 2410, 2411, 2412, 0, 1716, 0, 795, 1066, + 0, 958, 959, 0, 866, 866, 0, 866, 866, 866, + 866, 0, 0, 0, 809, 0, 0, 0, 0, 863, + 0, 825, 826, 0, 863, 0, 832, 869, 0, 0, + 839, 866, 866, 842, 2416, 0, 2416, 2416, 0, 0, + 1707, 0, 860, 858, 872, 873, 103, 876, 879, 880, + 881, 882, 885, 0, 896, 899, 1733, 1734, 0, 901, + 906, 925, 926, 0, 106, 1226, 0, 1090, 0, 1101, + -2, 1112, 1129, 1130, 1131, 1132, 1133, 1135, 1136, 1137, + 0, 0, 0, 0, 1142, 1143, 0, 0, 0, 0, + 0, 1206, 0, 0, 0, 0, 2127, 1546, 0, 0, + 1508, 1508, 1242, 1508, 1508, 1510, 1510, 1510, 1971, 2118, + 2128, 2316, 1926, 1932, 1933, 1934, 2261, 2262, 2263, 2264, + 2359, 2360, 2364, 2038, 1921, 2331, 2332, 0, 2412, 2078, + 2086, 2087, 2063, 2072, 2111, 2218, 2343, 1945, 2106, 2180, + 2034, 2058, 2059, 2199, 2200, 2082, 2083, 2062, 2267, 2269, + 2285, 2286, 2271, 2273, 2282, 2288, 2293, 2272, 2284, 2289, + 2302, 2306, 2309, 2310, 2311, 2279, 2277, 2290, 2294, 2296, + 2298, 2304, 2307, 2280, 2278, 2291, 2295, 2297, 2299, 2305, + 2308, 2266, 2270, 2274, 2283, 2301, 2281, 2300, 2275, 2287, + 2292, 2303, 2276, 2268, 2076, 2079, 2066, 2067, 2069, 2071, + 2077, 2084, 2090, 2068, 2089, 2088, 0, 2064, 2065, 2070, + 2081, 2085, 2073, 2074, 2075, 2080, 2091, 2134, 2133, 2132, + 2179, 2102, 2178, 0, 0, 0, 0, 0, 1915, 1978, + 1979, 2313, 1430, 1431, 1432, 1433, 0, 0, 0, 0, + 0, 0, 0, 362, 363, 1559, 1560, 105, 1225, 1703, + 1510, 1510, 1510, 1510, 1510, 1510, 1164, 1165, 1166, 1167, + 1168, 1194, 1195, 1201, 1202, 2194, 2195, 2196, 2197, 2016, + 2354, 2025, 2026, 2175, 2176, 2040, 2041, 2386, 2387, -2, + -2, -2, 304, 305, 306, 307, 308, 309, 310, 311, + 0, 1977, 2329, 2330, 300, 0, 1701, 1702, 367, 364, + 365, 366, 1208, 1209, 320, 321, 322, 323, 324, 325, + 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, + 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, 361, 0, 369, 370, 2415, + 0, 935, 0, 0, 0, 0, 0, 0, 1745, 1746, + 1584, 0, 1576, 1575, 124, 0, 962, -2, 0, 0, + 0, 0, -2, 108, 0, 113, 1023, 0, 965, 138, + 137, 1635, 1638, 0, 0, 0, 1645, 1647, 1648, 1649, + 102, 120, 1585, 128, 130, 1586, 0, 967, 968, 0, + 0, 1003, 0, 0, 0, 0, 1723, 1722, 1722, 168, + 0, 0, 169, 189, 190, 191, 0, 0, 175, 176, + 1709, 1710, 104, 0, 0, 247, 248, 0, 1182, 500, + 0, 243, 0, 493, 432, 0, 0, 0, 1027, 232, + 233, 234, 473, 473, 473, 647, 0, 0, 235, 235, + 605, 606, 607, 0, 0, -2, 498, 0, 585, 0, + 0, 487, 487, 491, 489, 490, 0, 0, 0, 0, + 0, 0, 0, 0, 624, 0, 625, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 742, 0, 474, 0, + 645, 646, 536, 0, 0, 0, 0, 0, 0, 0, + 0, 1725, 1726, 0, 622, 623, 0, 0, 0, 473, + 473, 0, 0, 0, 0, 473, 473, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 223, 1625, 0, 0, 224, + 225, 1603, 0, -2, 0, 786, 0, 0, 0, 1718, + 1718, 1718, 0, 1717, 794, 0, 0, 0, 799, 0, + 0, 800, 0, 863, 863, 861, 862, 802, 803, 804, + 805, 866, 0, 0, 482, 483, 484, 863, 866, 0, + 866, 866, 866, 866, 863, 863, 863, 866, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2416, 869, 866, + 0, 833, 0, 834, 835, 836, 837, 840, 841, 843, + 2417, 2418, 1735, 1736, 1747, 1748, 1749, 1750, 1751, 1752, + 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, 1762, + 1763, 1764, 1765, 1766, 1767, 1768, 1769, 1770, 1771, 1772, + 1773, 1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, 1782, + 1783, 1784, 1785, 1786, 1787, 1788, 1789, 1790, 1791, 1792, + 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800, 1801, 1802, + 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, 1811, 1812, + 1813, 1814, 1815, 1816, 1817, 1818, 1819, 1820, 1821, 1822, + 1823, 1824, 1825, 1826, 1827, 1828, 1829, 1830, 1831, 1832, + 1833, 1834, 1835, 1836, 1837, 1838, 1839, 1840, 1841, 1842, + 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, 1851, 1852, + 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, 1861, 1862, + 1863, 1864, 1865, 1866, 1867, 1868, 1869, 1870, 1871, 1872, + 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881, 1882, + 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 1891, 1892, + 1893, 1894, 1895, 1896, 1897, 1898, 1899, 1900, 1901, 1902, + 1903, 1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, 2416, + 2416, 847, 851, 855, 853, 1708, 878, 884, 886, 887, + 0, 0, 897, 900, 919, 110, 2024, 905, 110, 907, + 908, 909, 910, 911, 937, 938, 943, 0, 0, 0, + 0, 949, 950, 951, 0, 0, 954, 955, 956, 0, + 0, 0, 0, 0, 1088, 0, 0, 1214, 1215, 1216, + 1217, 1218, 1219, 1220, 1221, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1113, 1114, 0, 0, 0, 1138, 1139, + 1140, 1141, 1144, 0, 1155, 0, 1157, 1555, -2, 0, + 0, 0, 1149, 1150, 0, 0, 0, 1728, 1728, 0, + 0, 0, 1547, 0, 0, 1240, 0, 1241, 1243, 1244, + 1245, 0, 1246, 1247, 972, 972, 972, 972, 972, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 972, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1728, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 207, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1728, 0, + 0, 1728, 1728, 0, 0, 292, 293, 294, 295, 296, + 297, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 368, 312, 313, 314, 315, + 316, 371, 317, 318, 319, 1225, 0, 0, 962, 0, + 107, 927, 928, 0, 1049, 1728, 0, 0, 978, 0, + 1743, 118, 127, 129, 1584, 122, 1584, 0, 982, 0, + 0, -2, -2, 983, 984, 988, 989, 990, 991, 992, + 993, 994, 995, 996, 115, 2414, 116, 0, 135, 1607, + 0, 1602, 1625, 0, 0, 0, 0, 1720, 1626, 0, + 0, 0, 109, 0, 140, 141, 1691, 1695, 0, 1636, + 0, 1639, 0, 0, 0, 446, 1643, 0, 0, 0, + 1577, 1578, 1581, 0, 0, 1000, 2124, 1004, 0, 1006, + 1007, 0, 0, 0, 166, 0, 1065, 0, 0, 0, + 177, 0, 179, 180, 0, 0, 0, 457, 1711, 1712, + 1713, -2, 480, 0, 457, 441, 379, 380, 381, 432, + 383, 432, 432, 432, 432, 432, 446, 446, 446, 432, + 415, 416, 417, 418, 0, 432, 0, 400, 432, 432, + 432, 432, 422, 423, 424, 425, 426, 427, 428, 429, + 384, 385, 386, 387, 388, 389, 390, 391, 392, 434, + 434, 434, 434, 434, 438, 438, 0, 1183, 0, 461, + 0, 1581, 0, 0, 1611, 1024, 0, 0, 0, 0, + 648, 692, 599, 636, 649, 0, 602, 603, -2, 0, + 0, 584, 0, 586, 0, 481, 0, -2, 0, 491, + 0, 487, 491, 488, 491, 479, 492, 626, 627, 628, + 0, 630, 631, 722, 1035, 0, 0, 0, 0, 0, + 728, 729, 730, 0, 732, 733, 734, 735, 736, 737, + 738, 739, 740, 741, 637, 638, 639, 640, 641, 642, + 643, 644, 0, 0, 0, 0, 586, 0, 633, 0, + 0, 537, 538, 539, 0, 0, 542, 543, 544, 545, + 0, 0, 548, 549, 550, 1052, 1053, 551, 552, 577, + 578, 579, 553, 554, 555, 556, 557, 558, 559, 571, + 572, 573, 574, 575, 576, 560, 561, 562, 563, 564, + 565, 568, 0, 217, 1607, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1718, 0, 0, 0, 0, 0, 981, 1067, 1741, + 1742, 796, 0, 0, 867, 868, 0, 485, 486, 866, + 866, 806, 848, 0, 866, 810, 849, 811, 813, 812, + 814, 827, 828, 866, 817, 864, 865, 818, 819, 820, + 821, 822, 823, 824, 844, 829, 830, 831, 870, 0, + 874, 875, 845, 846, 0, 856, 0, 0, 0, 890, + 891, 0, 898, 922, 920, 921, 923, 915, 916, 917, + 918, 0, 924, 0, 0, 940, 162, 945, 946, 947, + 948, 960, 953, 1227, 1085, 1086, 1087, 0, 1089, 1095, + 0, 1210, 1212, 1093, 1094, 1097, 0, 0, 0, 1091, + 1102, 1222, 1223, 1224, 0, 0, 0, 0, 0, 1106, + 1110, 1115, 1116, 1117, 1118, 1119, 0, 1120, 0, 1123, + 1124, 1125, 1126, 1127, 1128, 1134, 1523, 1524, 1525, 1153, + 372, 373, 0, 1154, 0, 0, 0, 0, 0, 0, + 0, 0, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, + 1478, 1479, 1480, 1481, 1482, 1483, 1484, 1485, 1486, 1487, + 1488, 1489, 1226, 0, 1729, 0, 0, 0, 1553, 1550, + 0, 0, 0, 1509, 1511, 0, 0, 0, 973, 974, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1490, 1491, 1492, + 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, + 1503, 1504, 1505, 1506, 1507, 0, 0, 1526, 0, 0, + 0, 0, 0, 0, 0, 1546, 0, 1159, 1160, 1161, + 0, 0, 0, 0, 0, 0, 1288, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 208, 209, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1434, 1435, 1436, 1437, 0, 0, 0, 0, + 0, 0, 0, 1557, 0, -2, -2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1459, 0, 0, 0, 0, 0, 0, 1699, 0, 0, + 930, 931, 933, 0, 1069, 0, 1050, 0, 0, 936, + 0, 977, 0, 980, 121, 123, 986, 987, 0, 1008, + 997, 998, 985, 117, 1720, 0, 0, 1720, 1625, 1607, + 1730, 0, 0, 0, 0, 0, 198, 0, 112, 0, + 0, 0, 1637, 1640, 1641, 446, 1668, 0, 455, 455, + 452, 1646, 1587, 1588, 0, 1580, 1582, 1583, 142, 143, + 1005, 1001, 0, 1083, 1083, 0, 0, 1064, 0, 1011, + 1013, 1014, 1015, 1047, 0, 1018, 1019, 0, 0, 0, + 0, 0, 164, 1066, 170, 0, 178, 0, 0, 183, + 184, 171, 172, 173, 174, 0, 681, -2, 532, 249, + 251, 252, 253, 244, -2, 444, 442, 443, 382, 446, + 446, 408, 409, 446, 411, 412, 413, 414, 0, 420, + 0, 401, 402, 403, 404, 393, 0, 394, 395, 396, + 436, 0, 397, 398, 0, 399, 499, 0, 1589, 462, + 463, 465, 473, 0, 468, 469, 0, 473, 473, 0, + 494, 495, 0, 1581, 196, 1613, 1028, 237, 238, 239, + 240, 241, 242, 717, 0, 0, 693, 715, 716, 235, + 0, 0, 245, 588, 587, 0, 749, 0, 497, 0, + 0, 491, 491, 476, 477, 629, 0, 0, 724, 725, + 726, 727, 0, 0, 0, 615, 526, 0, 616, 617, + 586, 588, 0, 0, 457, 540, 541, 546, 547, 566, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 664, 665, 667, 670, 672, 590, 676, 678, 0, 666, + 669, 671, 673, 590, 677, 679, 1604, 1605, 1606, 0, + 0, 787, 0, 0, 523, 160, 1719, 792, 793, 797, + 798, 863, 816, 850, 863, 808, 815, 838, 852, 854, + 888, 889, 894, 902, 903, 904, 944, 0, 0, 0, + 0, 952, 0, 0, 1096, 1211, 1213, 1098, 1099, 1100, + 1103, 0, 1107, 1111, 0, 0, 0, 0, 0, 1158, + 1156, 1557, 0, 0, 0, 1207, 0, 0, 1230, 1231, + 0, 0, 0, 0, 1551, 0, 0, 1238, 0, 1512, + 1188, 0, 0, 0, 0, 0, 1188, 1188, 1188, 1188, + 1188, 1188, 1188, 1188, 1188, 1188, 1575, 1265, 0, 0, + 0, 0, 0, 1270, 1271, 1272, 1188, 0, 1275, 1276, + 0, 1278, 0, 1279, 0, 0, 0, 0, 1286, 1287, + 1289, 0, 0, 1292, 1293, 0, 1295, 0, 1297, 1298, + 1299, 1300, 1301, 1302, 0, 1304, 0, 1306, 1307, 1308, + 0, 1310, 0, 1312, 1313, 0, 1315, 0, 1317, 0, + 1320, 0, 1323, 0, 1326, 0, 1329, 0, 1332, 0, + 1335, 0, 1338, 0, 1341, 0, 1344, 0, 1347, 0, + 1350, 0, 1353, 0, 1356, 0, 1359, 0, 1362, 0, + 1365, 1366, 1367, 0, 1369, 0, 1371, 0, 1374, 1375, + 0, 1377, 0, 1380, 0, 1383, 0, 0, 1384, 0, + 0, 0, 1388, 0, 0, 0, 0, 1397, 1398, 1399, + 1400, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1411, 1412, 1413, 1414, 1415, 1416, 0, 1418, 0, + 1189, 0, 0, 1189, 0, 0, 0, 0, 0, 1228, + 1728, 0, 1513, 1514, 1515, 1516, 1517, 0, 0, 0, + 0, 0, 0, 1457, 1458, 1460, 0, 0, 1463, 0, + 1465, 0, 1700, 929, 932, 934, 1021, 1070, 1071, 0, + 0, 0, 0, 1051, 1727, 975, 976, 979, 1029, 0, + 1561, 0, 0, 1008, 1083, 0, 1009, 0, 0, 0, + 0, 0, 1607, 0, 0, 1731, 1730, 1730, 1730, 222, + 0, 1627, 1628, 1633, 1631, 1632, 114, 1692, 1696, 1650, + 1644, 1662, 1675, 455, 455, 449, 450, 456, 451, 453, + 454, 1579, 0, 1584, 0, 1584, 1689, 0, 962, 1678, + 0, 0, 0, 0, 0, 0, 0, 0, 1054, 0, + 0, 1057, 0, 0, 0, 0, 1048, 1019, 0, 1020, + 0, -2, 0, 0, 158, 159, 0, 0, 0, 181, + 182, 0, 0, 188, 458, 459, 226, 235, 534, 250, + 507, 0, 0, 378, 445, 405, 406, 407, 410, 0, + 430, 0, 0, 0, 0, 528, 195, 1593, 1592, 473, + 473, 464, 0, 467, 0, 0, 0, 1732, 433, 496, + 0, 1614, 1615, 687, 0, 0, 694, 0, 0, 0, + 597, 0, 608, 609, 0, 721, -2, 783, 461, 0, + 475, 478, 1036, 0, 0, 610, 0, 613, 614, 527, + 588, 619, 620, 634, 621, 569, 570, 567, 0, 199, + 655, 657, 661, 656, 660, 0, 0, 0, 592, 0, + 680, 592, 653, 0, 523, 1589, 0, 791, 524, 525, + 866, 866, 939, 163, 0, 942, 0, 0, 0, 0, + 1104, 1108, 1121, 1122, 1518, 1544, 432, 432, 1531, 432, + 438, 1534, 432, 1536, 432, 1539, 432, 1542, 1543, 0, + 0, 1151, 0, 0, 0, 0, 1237, 1554, 0, 0, + 1248, 1187, 1188, 1188, 1188, 1188, 1188, 1254, 1255, 1256, + 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1548, 0, 0, + 0, 1269, 0, 0, 1273, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 210, 211, 0, 0, 0, 0, + 0, 0, 1468, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1182, 1186, 0, 1190, 1191, 0, + 0, 1420, 0, 0, 1438, 0, 0, 0, 0, 0, + 0, 0, 1558, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1072, 1079, 0, 1079, 0, 1079, 0, + 0, 0, 1714, 1715, 1562, 1563, 1083, 1564, 999, 1010, + 0, 214, 1608, 1609, 1610, 213, 0, 0, 0, 0, + 0, 0, 1721, 0, 1630, 1634, 1668, 0, 1661, 0, + -2, 1670, 0, 0, 0, 1676, 447, 448, 1002, 144, + 1084, 145, 149, 0, 1689, 1704, 0, 1686, 1693, 1697, + 0, 0, 0, 1682, 0, 1083, 1012, 1043, 1045, 0, + 1040, 1055, 1056, 1058, 0, 1060, 0, 1062, 1063, 1023, + 1017, 0, 166, 0, 1083, 1083, 165, 0, 1068, 185, + 186, 187, 533, 254, 259, 0, 0, 0, 264, 0, + 266, 0, 0, 0, 271, 272, 473, 473, 508, 0, + 375, 377, 0, 0, 257, 446, 0, 446, 0, 437, + 439, 0, 509, 529, 1590, 1591, 0, 0, 466, 470, + 471, 472, 0, 690, 0, 718, 0, 0, 0, 0, + 0, 0, 246, 589, 750, 751, 752, 753, 754, 755, + 756, 757, 758, 0, 473, 0, 0, 0, 473, 473, + 473, 0, 775, 460, 0, 0, 746, 743, 611, 0, + 290, 291, 298, 299, 301, 0, 0, 0, 0, 0, + 618, 1023, 202, 0, 0, 0, 0, 663, 668, 674, + 0, 591, 675, 788, 789, 790, 161, 801, 807, 941, + 961, 1092, 1105, 1109, 0, 0, 0, 0, 1545, 1529, + 446, 1532, 1533, 1535, 1537, 1538, 1540, 1541, 1147, 1148, + 1152, 0, 1234, 0, 1236, 0, 1552, 0, 1249, 1250, + 1251, 1252, 1253, 1584, 0, 0, 0, 1268, 0, 0, + 1188, 0, 1281, 1280, 1282, 0, 1284, 1285, 1290, 1291, + 1294, 1296, 1303, 1305, 1309, 1311, 1314, 1316, 1318, 0, + 1321, 0, 1324, 0, 1327, 0, 1330, 0, 1333, 0, + 1336, 0, 1339, 0, 1342, 0, 1345, 0, 1348, 0, + 1351, 0, 1354, 0, 1357, 0, 1360, 0, 1363, 0, + 1368, 1370, 0, 1373, 1376, 1378, 0, 1381, 0, 1385, + 0, 1387, 1389, 1390, 0, 0, 0, 1401, 1402, 1403, + 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1417, 0, 1180, + 1419, 1192, 1193, 1198, 1422, 0, 0, 0, 1425, 0, + 0, 0, 1429, 1229, 1440, 0, 1445, 0, 0, 1451, + 0, 1455, 0, 1461, 1462, 1464, 1466, 0, 0, 0, + 0, 0, 0, 0, 1049, 1030, 125, 1564, 1568, 0, + -2, 0, 216, 218, 0, 0, 0, 1629, 1655, 1653, + 1653, 1663, 1664, 0, 0, 1671, 0, 0, 0, 0, + 150, 0, 0, 1677, 0, 0, 1698, 0, 0, 0, + 0, 167, 1575, 1037, 1044, 0, 0, 1038, 0, 1039, + 1059, 1061, 1016, 0, 1083, 1083, 156, 157, 0, 260, + 0, 262, 0, 265, 267, 268, 269, 275, 276, 277, + 278, 270, 0, 0, 374, 376, 0, 0, 419, 431, + 421, 0, 0, 1594, 1595, 1596, 1597, 1598, 1599, 1600, + 1601, 1612, 682, 0, 692, 0, 1025, 0, 685, 0, + 600, 0, 0, 0, 473, 473, 473, 0, 0, 0, + 0, 760, 0, 0, 723, 0, 731, 0, 0, 0, + 302, 303, 0, 654, 0, 200, 201, 0, 0, 659, + 593, 594, 1145, 0, 0, 0, 1146, 1530, 0, 0, + 0, 0, 0, 1549, 0, 0, 0, 0, 1274, 1277, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1393, 0, 0, 0, 712, 713, 0, 1469, + 1185, 1575, 0, 1189, 1199, 1200, 0, 1189, 1439, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1080, 0, 0, 0, 1031, 1032, 0, 0, 0, 1069, + 1568, 1573, 0, 0, 0, 1617, 1618, 0, 1622, 1623, + 1624, 215, 219, 220, 221, 1658, 0, 1651, 1654, 1652, + 1665, 0, 0, 1672, 0, 1674, 0, 1705, 1706, 1694, + 1687, 962, 1681, 1684, 1686, 1683, 1584, 1041, 0, 1046, + 0, 1575, 155, 0, 263, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 273, 274, 0, 0, + 435, 440, 0, 0, 683, 0, 1026, 695, 686, 0, + 773, 0, 777, 0, 0, 0, 780, 781, 782, 759, + 0, 763, 501, 747, 744, 745, 612, 0, 203, 204, + 0, 0, 0, 1519, 0, 1522, 1232, 1235, 1233, 0, + 1264, 1266, 1267, 1527, 1528, 1283, 1319, 1322, 1325, 1328, + 1331, 1334, 1337, 1340, 1343, 1346, 1349, 1352, 1355, 1358, + 1361, 1364, 1372, 1379, 1382, 1386, 1391, 0, 1394, 0, + 0, 1395, 0, 714, 1176, 0, 0, 1196, 1197, 0, + 1424, 1426, 1427, 1428, 1441, 0, 1446, 1447, 0, 1452, + 0, 1456, 1467, 0, 1074, 1081, 1082, 0, 1077, 0, + 1078, 0, 1022, 1573, 147, 1574, 1571, 0, 1569, 1566, + 110, 1621, 0, 1642, 0, 1656, 1657, 1666, 1667, 1673, + 0, 0, 1686, 0, 1680, 153, 0, 0, 0, 1584, + 261, 0, 281, 691, 0, 694, 684, 771, 772, 0, + 784, 776, 778, 779, 761, -2, 1611, 0, 0, 0, + 662, 1520, 0, 0, 1396, 0, 710, 711, 1184, 1177, + 0, 1162, 1163, 1181, 1421, 1423, 0, 0, 0, 1073, + 1033, 1034, 1075, 1076, 146, 0, 1570, 1204, 0, 1565, + 0, 212, 89, 90, 43, -2, 0, 0, 0, 1619, + 1620, 1659, 1660, 1690, 0, 1679, 1685, 1042, 1049, 0, + 154, 514, 507, 0, 0, 0, 764, 765, 766, 767, + 768, 769, 770, 651, 205, 206, 0, 581, 582, 583, + 199, 0, 1239, 1392, 1178, 0, 0, 0, 0, 0, + 1442, 0, 1448, 0, 1453, 0, 1572, 0, 0, 1567, + 88, 0, -2, 93, 0, 0, 0, 0, 1027, 67, + 68, 69, 50, 74, 75, 83, 77, 1688, 696, 0, + 698, 0, -2, 502, 515, 0, 255, 282, 283, 0, + 0, 286, 0, 288, 289, 279, 280, 0, 0, 785, + 0, 202, 0, 0, 1169, 1170, 1171, 1172, 1174, 0, + 0, 0, 0, 1205, 1182, 44, 94, 110, 85, 0, + 0, 49, 51, 0, 0, 84, 697, 0, 0, 457, + 0, 707, 503, 504, 0, 510, 511, 512, 513, 284, + 285, 287, 719, 0, 580, 658, 1521, 0, 0, 1443, + 0, 1449, 0, 1454, 0, -2, 46, 0, 0, 0, + 52, 0, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 53, 76, 699, 700, 708, 0, + 505, 0, 506, 0, 0, 0, 688, 0, 719, 1179, + 1173, 1175, 0, 0, 1203, 95, 98, 100, 0, 0, + 87, 110, 71, 78, 79, 80, 0, 82, 72, 73, + 48, 0, 0, 709, 705, 516, 518, 519, 0, 0, + 517, 720, 689, 1444, 1450, 0, 110, 99, 0, 0, + 47, 0, 81, 54, 0, 520, 521, 522, 0, -2, + 110, 86, 70, 701, 45, -2, 702, 703, 704, } var yyTok1 = [...]int{ @@ -12029,45 +12161,61 @@ yydefault: var yyLOCAL Statement //line sql.y:1239 { - yyLOCAL = &Stream{Comments: Comments(yyDollar[2].strs).Parsed(), SelectExpr: yyDollar[3].selectExprUnion(), Table: yyDollar[5].tableName} + yyLOCAL = &Stream{Comments: Comments(yyDollar[2].strs).Parsed(), SelectExpr: &StarExpr{}, Table: yyDollar[5].tableName} } yyVAL.union = yyLOCAL case 143: + yyDollar = yyS[yypt-5 : yypt+1] + var yyLOCAL Statement +//line sql.y:1243 + { + yyLOCAL = &Stream{Comments: Comments(yyDollar[2].strs).Parsed(), SelectExpr: yyDollar[3].selectExprUnion(), Table: yyDollar[5].tableName} + } + yyVAL.union = yyLOCAL + case 144: + yyDollar = yyS[yypt-7 : yypt+1] + var yyLOCAL Statement +//line sql.y:1249 + { + yyLOCAL = &VStream{Comments: Comments(yyDollar[2].strs).Parsed(), SelectExpr: &StarExpr{}, Table: yyDollar[5].tableName, Where: NewWhere(WhereClause, yyDollar[6].exprUnion()), Limit: yyDollar[7].limitUnion()} + } + yyVAL.union = yyLOCAL + case 145: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:1245 +//line sql.y:1253 { yyLOCAL = &VStream{Comments: Comments(yyDollar[2].strs).Parsed(), SelectExpr: yyDollar[3].selectExprUnion(), Table: yyDollar[5].tableName, Where: NewWhere(WhereClause, yyDollar[6].exprUnion()), Limit: yyDollar[7].limitUnion()} } yyVAL.union = yyLOCAL - case 144: + case 146: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL TableStatement -//line sql.y:1253 +//line sql.y:1261 { yyLOCAL = NewSelect(Comments(yyDollar[2].strs), yyDollar[4].selectExprsUnion() /*SelectExprs*/, yyDollar[3].strs /*options*/, yyDollar[5].selectIntoUnion() /*into*/, yyDollar[6].tableExprsUnion() /*from*/, NewWhere(WhereClause, yyDollar[7].exprUnion()), yyDollar[8].groupByUnion(), NewWhere(HavingClause, yyDollar[9].exprUnion()), yyDollar[10].namedWindowsUnion()) } yyVAL.union = yyLOCAL - case 145: + case 147: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL TableStatement -//line sql.y:1257 +//line sql.y:1265 { yyLOCAL = NewSelect(Comments(yyDollar[2].strs), yyDollar[4].selectExprsUnion() /*SelectExprs*/, yyDollar[3].strs /*options*/, nil, yyDollar[5].tableExprsUnion() /*from*/, NewWhere(WhereClause, yyDollar[6].exprUnion()), yyDollar[7].groupByUnion(), NewWhere(HavingClause, yyDollar[8].exprUnion()), yyDollar[9].namedWindowsUnion()) } yyVAL.union = yyLOCAL - case 146: + case 148: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableStatement -//line sql.y:1261 +//line sql.y:1269 { yyLOCAL = yyDollar[1].tableStmtUnion() } yyVAL.union = yyLOCAL - case 147: + case 149: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:1267 +//line sql.y:1275 { // insert_data returns a *Insert pre-filled with Columns & Values ins := yyDollar[6].insUnion() @@ -12080,10 +12228,10 @@ yydefault: yyLOCAL = ins } yyVAL.union = yyLOCAL - case 148: + case 150: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Statement -//line sql.y:1279 +//line sql.y:1287 { cols := make(Columns, 0, len(yyDollar[7].updateExprsUnion())) vals := make(ValTuple, 0, len(yyDollar[8].updateExprsUnion())) @@ -12094,329 +12242,329 @@ yydefault: yyLOCAL = &Insert{Action: yyDollar[1].insertActionUnion(), Comments: Comments(yyDollar[2].strs).Parsed(), Ignore: yyDollar[3].ignoreUnion(), Table: getAliasedTableExprFromTableName(yyDollar[4].tableName), Partitions: yyDollar[5].partitionsUnion(), Columns: cols, Rows: Values{vals}, OnDup: OnDup(yyDollar[8].updateExprsUnion())} } yyVAL.union = yyLOCAL - case 149: + case 151: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL InsertAction -//line sql.y:1291 +//line sql.y:1299 { yyLOCAL = InsertAct } yyVAL.union = yyLOCAL - case 150: + case 152: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL InsertAction -//line sql.y:1295 +//line sql.y:1303 { yyLOCAL = ReplaceAct } yyVAL.union = yyLOCAL - case 151: + case 153: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL Statement -//line sql.y:1301 +//line sql.y:1309 { yyLOCAL = &Update{With: yyDollar[1].withUnion(), Comments: Comments(yyDollar[3].strs).Parsed(), Ignore: yyDollar[4].ignoreUnion(), TableExprs: yyDollar[5].tableExprsUnion(), Exprs: yyDollar[7].updateExprsUnion(), Where: NewWhere(WhereClause, yyDollar[8].exprUnion()), OrderBy: yyDollar[9].orderByUnion(), Limit: yyDollar[10].limitUnion()} } yyVAL.union = yyLOCAL - case 152: + case 154: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL Statement -//line sql.y:1307 +//line sql.y:1315 { yyLOCAL = &Delete{With: yyDollar[1].withUnion(), Comments: Comments(yyDollar[3].strs).Parsed(), Ignore: yyDollar[4].ignoreUnion(), TableExprs: TableExprs{&AliasedTableExpr{Expr: yyDollar[6].tableName, As: yyDollar[7].identifierCS}}, Partitions: yyDollar[8].partitionsUnion(), Where: NewWhere(WhereClause, yyDollar[9].exprUnion()), OrderBy: yyDollar[10].orderByUnion(), Limit: yyDollar[11].limitUnion()} } yyVAL.union = yyLOCAL - case 153: + case 155: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL Statement -//line sql.y:1311 +//line sql.y:1319 { yyLOCAL = &Delete{With: yyDollar[1].withUnion(), Comments: Comments(yyDollar[3].strs).Parsed(), Ignore: yyDollar[4].ignoreUnion(), Targets: yyDollar[6].tableNamesUnion(), TableExprs: yyDollar[8].tableExprsUnion(), Where: NewWhere(WhereClause, yyDollar[9].exprUnion())} } yyVAL.union = yyLOCAL - case 154: + case 156: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Statement -//line sql.y:1315 +//line sql.y:1323 { yyLOCAL = &Delete{With: yyDollar[1].withUnion(), Comments: Comments(yyDollar[3].strs).Parsed(), Ignore: yyDollar[4].ignoreUnion(), Targets: yyDollar[5].tableNamesUnion(), TableExprs: yyDollar[7].tableExprsUnion(), Where: NewWhere(WhereClause, yyDollar[8].exprUnion())} } yyVAL.union = yyLOCAL - case 155: + case 157: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Statement -//line sql.y:1319 +//line sql.y:1327 { yyLOCAL = &Delete{With: yyDollar[1].withUnion(), Comments: Comments(yyDollar[3].strs).Parsed(), Ignore: yyDollar[4].ignoreUnion(), Targets: yyDollar[5].tableNamesUnion(), TableExprs: yyDollar[7].tableExprsUnion(), Where: NewWhere(WhereClause, yyDollar[8].exprUnion())} } yyVAL.union = yyLOCAL - case 156: + case 158: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1324 +//line sql.y:1332 { } - case 157: + case 159: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1325 +//line sql.y:1333 { } - case 158: + case 160: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableNames -//line sql.y:1329 +//line sql.y:1337 { yyLOCAL = TableNames{yyDollar[1].tableName} } yyVAL.union = yyLOCAL - case 159: + case 161: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1333 +//line sql.y:1341 { yySLICE := (*TableNames)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].tableName) } - case 160: + case 162: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableNames -//line sql.y:1339 +//line sql.y:1347 { yyLOCAL = TableNames{yyDollar[1].tableName} } yyVAL.union = yyLOCAL - case 161: + case 163: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1343 +//line sql.y:1351 { yySLICE := (*TableNames)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].tableName) } - case 162: + case 164: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableNames -//line sql.y:1349 +//line sql.y:1357 { yyLOCAL = TableNames{yyDollar[1].tableName} } yyVAL.union = yyLOCAL - case 163: + case 165: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1353 +//line sql.y:1361 { yySLICE := (*TableNames)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].tableName) } - case 164: + case 166: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Partitions -//line sql.y:1358 +//line sql.y:1366 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 165: + case 167: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Partitions -//line sql.y:1362 +//line sql.y:1370 { yyLOCAL = yyDollar[3].partitionsUnion() } yyVAL.union = yyLOCAL - case 166: + case 168: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:1368 +//line sql.y:1376 { yyLOCAL = NewSetStatement(Comments(yyDollar[2].strs).Parsed(), yyDollar[3].setExprsUnion()) } yyVAL.union = yyLOCAL - case 167: + case 169: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL SetExprs -//line sql.y:1374 +//line sql.y:1382 { yyLOCAL = SetExprs{yyDollar[1].setExprUnion()} } yyVAL.union = yyLOCAL - case 168: + case 170: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1378 +//line sql.y:1386 { yySLICE := (*SetExprs)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].setExprUnion()) } - case 169: + case 171: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *SetExpr -//line sql.y:1384 +//line sql.y:1392 { yyLOCAL = &SetExpr{Var: yyDollar[1].variableUnion(), Expr: NewStrLiteral("on")} } yyVAL.union = yyLOCAL - case 170: + case 172: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *SetExpr -//line sql.y:1388 +//line sql.y:1396 { yyLOCAL = &SetExpr{Var: yyDollar[1].variableUnion(), Expr: NewStrLiteral("off")} } yyVAL.union = yyLOCAL - case 171: + case 173: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *SetExpr -//line sql.y:1392 +//line sql.y:1400 { yyLOCAL = &SetExpr{Var: yyDollar[1].variableUnion(), Expr: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 172: + case 174: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *SetExpr -//line sql.y:1396 +//line sql.y:1404 { yyLOCAL = &SetExpr{Var: NewSetVariable(string(yyDollar[1].str), SessionScope), Expr: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 173: + case 175: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Variable -//line sql.y:1402 +//line sql.y:1410 { yyLOCAL = NewSetVariable(string(yyDollar[1].str), NoScope) } yyVAL.union = yyLOCAL - case 174: + case 176: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Variable -//line sql.y:1406 +//line sql.y:1414 { yyLOCAL = yyDollar[1].variableUnion() } yyVAL.union = yyLOCAL - case 175: + case 177: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *Variable -//line sql.y:1410 +//line sql.y:1418 { yyLOCAL = NewSetVariable(string(yyDollar[2].str), yyDollar[1].scopeUnion()) } yyVAL.union = yyLOCAL - case 176: + case 178: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:1416 +//line sql.y:1424 { yyLOCAL = NewSetStatement(Comments(yyDollar[2].strs).Parsed(), UpdateSetExprsScope(yyDollar[5].setExprsUnion(), yyDollar[3].scopeUnion())) } yyVAL.union = yyLOCAL - case 177: + case 179: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:1420 +//line sql.y:1428 { yyLOCAL = NewSetStatement(Comments(yyDollar[2].strs).Parsed(), yyDollar[4].setExprsUnion()) } yyVAL.union = yyLOCAL - case 178: + case 180: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL SetExprs -//line sql.y:1426 +//line sql.y:1434 { yyLOCAL = SetExprs{yyDollar[1].setExprUnion()} } yyVAL.union = yyLOCAL - case 179: + case 181: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1430 +//line sql.y:1438 { yySLICE := (*SetExprs)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].setExprUnion()) } - case 180: + case 182: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *SetExpr -//line sql.y:1436 +//line sql.y:1444 { yyLOCAL = &SetExpr{Var: NewSetVariable(TransactionIsolationStr, NextTxScope), Expr: NewStrLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 181: + case 183: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *SetExpr -//line sql.y:1440 +//line sql.y:1448 { yyLOCAL = &SetExpr{Var: NewSetVariable(TransactionReadOnlyStr, NextTxScope), Expr: NewStrLiteral("off")} } yyVAL.union = yyLOCAL - case 182: + case 184: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *SetExpr -//line sql.y:1444 +//line sql.y:1452 { yyLOCAL = &SetExpr{Var: NewSetVariable(TransactionReadOnlyStr, NextTxScope), Expr: NewStrLiteral("on")} } yyVAL.union = yyLOCAL - case 183: + case 185: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1450 +//line sql.y:1458 { yyVAL.str = RepeatableReadStr } - case 184: + case 186: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1454 +//line sql.y:1462 { yyVAL.str = ReadCommittedStr } - case 185: + case 187: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1458 +//line sql.y:1466 { yyVAL.str = ReadUncommittedStr } - case 186: + case 188: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1462 +//line sql.y:1470 { yyVAL.str = SerializableStr } - case 187: + case 189: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Scope -//line sql.y:1468 +//line sql.y:1476 { yyLOCAL = SessionScope } yyVAL.union = yyLOCAL - case 188: + case 190: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Scope -//line sql.y:1472 +//line sql.y:1480 { yyLOCAL = SessionScope } yyVAL.union = yyLOCAL - case 189: + case 191: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Scope -//line sql.y:1476 +//line sql.y:1484 { yyLOCAL = GlobalScope } yyVAL.union = yyLOCAL - case 190: + case 192: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:1482 +//line sql.y:1490 { yyDollar[1].createTableUnion().TableSpec = yyDollar[2].tableSpecUnion() yyDollar[1].createTableUnion().FullyParsed = true yyLOCAL = yyDollar[1].createTableUnion() } yyVAL.union = yyLOCAL - case 191: + case 193: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:1488 +//line sql.y:1496 { // Create table [name] like [name] yyDollar[1].createTableUnion().OptLike = yyDollar[2].optLikeUnion() @@ -12424,18 +12572,18 @@ yydefault: yyLOCAL = yyDollar[1].createTableUnion() } yyVAL.union = yyLOCAL - case 192: + case 194: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:1495 +//line sql.y:1503 { yyLOCAL = yyDollar[1].createProcedureUnion() } yyVAL.union = yyLOCAL - case 193: + case 195: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:1499 +//line sql.y:1507 { indexDef := yyDollar[1].alterTableUnion().AlterOptions[0].(*AddIndexDefinition).IndexDefinition indexDef.Columns = yyDollar[3].indexColumnsUnion() @@ -12445,10 +12593,10 @@ yydefault: yyLOCAL = yyDollar[1].alterTableUnion() } yyVAL.union = yyLOCAL - case 194: + case 196: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:1508 +//line sql.y:1516 { yyDollar[1].createViewUnion().Columns = yyDollar[2].columnsUnion() yyDollar[1].createViewUnion().Select = yyDollar[4].tableStmtUnion() @@ -12456,429 +12604,429 @@ yydefault: yyLOCAL = yyDollar[1].createViewUnion() } yyVAL.union = yyLOCAL - case 195: + case 197: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:1515 +//line sql.y:1523 { yyDollar[1].createDatabaseUnion().FullyParsed = true yyDollar[1].createDatabaseUnion().CreateOptions = yyDollar[2].databaseOptionsUnion() yyLOCAL = yyDollar[1].createDatabaseUnion() } yyVAL.union = yyLOCAL - case 196: + case 198: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:1523 +//line sql.y:1531 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 197: + case 199: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1528 +//line sql.y:1536 { yyVAL.identifierCI = NewIdentifierCI("") } - case 198: + case 200: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1532 +//line sql.y:1540 { yyVAL.identifierCI = yyDollar[2].identifierCI } - case 199: + case 201: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1538 +//line sql.y:1546 { yyVAL.identifierCI = yyDollar[1].identifierCI } - case 200: + case 202: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []VindexParam -//line sql.y:1543 +//line sql.y:1551 { var v []VindexParam yyLOCAL = v } yyVAL.union = yyLOCAL - case 201: + case 203: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []VindexParam -//line sql.y:1548 +//line sql.y:1556 { yyLOCAL = yyDollar[2].vindexParamsUnion() } yyVAL.union = yyLOCAL - case 202: + case 204: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []VindexParam -//line sql.y:1554 +//line sql.y:1562 { yyLOCAL = make([]VindexParam, 0, 4) yyLOCAL = append(yyLOCAL, yyDollar[1].vindexParam) } yyVAL.union = yyLOCAL - case 203: + case 205: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1559 +//line sql.y:1567 { yySLICE := (*[]VindexParam)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].vindexParam) } - case 204: + case 206: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1565 +//line sql.y:1573 { yyVAL.vindexParam = VindexParam{Key: yyDollar[1].identifierCI, Val: yyDollar[3].str} } - case 205: + case 207: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*JSONObjectParam -//line sql.y:1570 +//line sql.y:1578 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 206: + case 208: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*JSONObjectParam -//line sql.y:1574 +//line sql.y:1582 { yyLOCAL = yyDollar[1].jsonObjectParamsUnion() } yyVAL.union = yyLOCAL - case 207: + case 209: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*JSONObjectParam -//line sql.y:1580 +//line sql.y:1588 { yyLOCAL = []*JSONObjectParam{yyDollar[1].jsonObjectParam} } yyVAL.union = yyLOCAL - case 208: + case 210: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1584 +//line sql.y:1592 { yySLICE := (*[]*JSONObjectParam)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].jsonObjectParam) } - case 209: + case 211: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1590 +//line sql.y:1598 { yyVAL.jsonObjectParam = &JSONObjectParam{Key: yyDollar[1].exprUnion(), Value: yyDollar[3].exprUnion()} } - case 210: + case 212: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL *CreateProcedure -//line sql.y:1596 +//line sql.y:1604 { yyLOCAL = &CreateProcedure{Comments: Comments(yyDollar[2].strs).Parsed(), Name: yyDollar[6].tableName, IfNotExists: yyDollar[5].booleanUnion(), Definer: yyDollar[3].definerUnion(), Params: yyDollar[8].procParamsUnion(), Body: yyDollar[10].compoundStatementUnion()} } yyVAL.union = yyLOCAL - case 211: + case 213: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *CreateTable -//line sql.y:1602 +//line sql.y:1610 { yyLOCAL = &CreateTable{Comments: Comments(yyDollar[2].strs).Parsed(), Table: yyDollar[6].tableName, IfNotExists: yyDollar[5].booleanUnion(), Temp: yyDollar[3].booleanUnion()} setDDL(yylex, yyLOCAL) } yyVAL.union = yyLOCAL - case 212: + case 214: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *CreateView -//line sql.y:1618 +//line sql.y:1626 { yyLOCAL = &CreateView{ViewName: yyDollar[6].tableName, Comments: Comments(yyDollar[2].strs).Parsed(), Definer: yyDollar[3].definerUnion(), Security: yyDollar[4].str} } yyVAL.union = yyLOCAL - case 213: + case 215: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *CreateView -//line sql.y:1622 +//line sql.y:1630 { yyLOCAL = &CreateView{ViewName: yyDollar[8].tableName, Comments: Comments(yyDollar[2].strs).Parsed(), IsReplace: yyDollar[3].booleanUnion(), Algorithm: yyDollar[4].str, Definer: yyDollar[5].definerUnion(), Security: yyDollar[6].str} } yyVAL.union = yyLOCAL - case 214: + case 216: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *CreateView -//line sql.y:1626 +//line sql.y:1634 { yyLOCAL = &CreateView{ViewName: yyDollar[7].tableName, Comments: Comments(yyDollar[2].strs).Parsed(), Algorithm: yyDollar[3].str, Definer: yyDollar[4].definerUnion(), Security: yyDollar[5].str} } yyVAL.union = yyLOCAL - case 215: + case 217: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *AlterTable -//line sql.y:1633 +//line sql.y:1641 { yyLOCAL = &AlterTable{Comments: Comments(yyDollar[2].strs).Parsed(), Table: yyDollar[4].tableName} setDDL(yylex, yyLOCAL) } yyVAL.union = yyLOCAL - case 216: + case 218: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *AlterTable -//line sql.y:1640 +//line sql.y:1648 { yyLOCAL = &AlterTable{Comments: Comments(yyDollar[2].strs).Parsed(), Table: yyDollar[7].tableName, AlterOptions: []AlterOption{&AddIndexDefinition{IndexDefinition: &IndexDefinition{Info: &IndexInfo{Name: yyDollar[4].identifierCI}, Options: yyDollar[5].indexOptionsUnion()}}}} setDDL(yylex, yyLOCAL) } yyVAL.union = yyLOCAL - case 217: + case 219: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *AlterTable -//line sql.y:1645 +//line sql.y:1653 { yyLOCAL = &AlterTable{Comments: Comments(yyDollar[2].strs).Parsed(), Table: yyDollar[8].tableName, AlterOptions: []AlterOption{&AddIndexDefinition{IndexDefinition: &IndexDefinition{Info: &IndexInfo{Name: yyDollar[5].identifierCI, Type: IndexTypeFullText}, Options: yyDollar[6].indexOptionsUnion()}}}} setDDL(yylex, yyLOCAL) } yyVAL.union = yyLOCAL - case 218: + case 220: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *AlterTable -//line sql.y:1650 +//line sql.y:1658 { yyLOCAL = &AlterTable{Comments: Comments(yyDollar[2].strs).Parsed(), Table: yyDollar[8].tableName, AlterOptions: []AlterOption{&AddIndexDefinition{IndexDefinition: &IndexDefinition{Info: &IndexInfo{Name: yyDollar[5].identifierCI, Type: IndexTypeSpatial}, Options: yyDollar[6].indexOptionsUnion()}}}} setDDL(yylex, yyLOCAL) } yyVAL.union = yyLOCAL - case 219: + case 221: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *AlterTable -//line sql.y:1655 +//line sql.y:1663 { yyLOCAL = &AlterTable{Comments: Comments(yyDollar[2].strs).Parsed(), Table: yyDollar[8].tableName, AlterOptions: []AlterOption{&AddIndexDefinition{IndexDefinition: &IndexDefinition{Info: &IndexInfo{Name: yyDollar[5].identifierCI, Type: IndexTypeUnique}, Options: yyDollar[6].indexOptionsUnion()}}}} setDDL(yylex, yyLOCAL) } yyVAL.union = yyLOCAL - case 220: + case 222: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *CreateDatabase -//line sql.y:1662 +//line sql.y:1670 { yyLOCAL = &CreateDatabase{Comments: Comments(yyDollar[2].strs).Parsed(), DBName: yyDollar[5].identifierCS, IfNotExists: yyDollar[4].booleanUnion()} setDDL(yylex, yyLOCAL) } yyVAL.union = yyLOCAL - case 221: + case 223: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *AlterDatabase -//line sql.y:1669 +//line sql.y:1677 { yyLOCAL = &AlterDatabase{Comments: Comments(yyDollar[2].strs).Parsed()} setDDL(yylex, yyLOCAL) } yyVAL.union = yyLOCAL - case 224: + case 226: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *TableSpec -//line sql.y:1680 +//line sql.y:1688 { yyLOCAL = yyDollar[2].tableSpecUnion() yyLOCAL.Options = yyDollar[4].tableOptionsUnion() yyLOCAL.PartitionOption = yyDollar[5].partitionOptionUnion() } yyVAL.union = yyLOCAL - case 225: + case 227: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []DatabaseOption -//line sql.y:1687 +//line sql.y:1695 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 226: + case 228: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []DatabaseOption -//line sql.y:1691 +//line sql.y:1699 { yyLOCAL = yyDollar[1].databaseOptionsUnion() } yyVAL.union = yyLOCAL - case 227: + case 229: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []DatabaseOption -//line sql.y:1697 +//line sql.y:1705 { yyLOCAL = []DatabaseOption{yyDollar[1].databaseOption} } yyVAL.union = yyLOCAL - case 228: + case 230: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []DatabaseOption -//line sql.y:1701 +//line sql.y:1709 { yyLOCAL = []DatabaseOption{yyDollar[1].databaseOption} } yyVAL.union = yyLOCAL - case 229: + case 231: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []DatabaseOption -//line sql.y:1705 +//line sql.y:1713 { yyLOCAL = []DatabaseOption{yyDollar[1].databaseOption} } yyVAL.union = yyLOCAL - case 230: + case 232: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1709 +//line sql.y:1717 { yySLICE := (*[]DatabaseOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[2].databaseOption) } - case 231: + case 233: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1713 +//line sql.y:1721 { yySLICE := (*[]DatabaseOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[2].databaseOption) } - case 232: + case 234: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1717 +//line sql.y:1725 { yySLICE := (*[]DatabaseOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[2].databaseOption) } - case 233: + case 235: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:1723 +//line sql.y:1731 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 234: + case 236: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:1727 +//line sql.y:1735 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 235: + case 237: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1733 +//line sql.y:1741 { yyVAL.databaseOption = DatabaseOption{Type: CharacterSetType, Value: string(yyDollar[4].str), IsDefault: yyDollar[1].booleanUnion()} } - case 236: + case 238: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1737 +//line sql.y:1745 { yyVAL.databaseOption = DatabaseOption{Type: CharacterSetType, Value: encodeSQLString(yyDollar[4].str), IsDefault: yyDollar[1].booleanUnion()} } - case 237: + case 239: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1743 +//line sql.y:1751 { yyVAL.databaseOption = DatabaseOption{Type: CollateType, Value: string(yyDollar[4].str), IsDefault: yyDollar[1].booleanUnion()} } - case 238: + case 240: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1747 +//line sql.y:1755 { yyVAL.databaseOption = DatabaseOption{Type: CollateType, Value: encodeSQLString(yyDollar[4].str), IsDefault: yyDollar[1].booleanUnion()} } - case 239: + case 241: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1753 +//line sql.y:1761 { yyVAL.databaseOption = DatabaseOption{Type: EncryptionType, Value: string(yyDollar[4].str), IsDefault: yyDollar[1].booleanUnion()} } - case 240: + case 242: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1757 +//line sql.y:1765 { yyVAL.databaseOption = DatabaseOption{Type: EncryptionType, Value: encodeSQLString(yyDollar[4].str), IsDefault: yyDollar[1].booleanUnion()} } - case 241: + case 243: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *OptLike -//line sql.y:1763 +//line sql.y:1771 { yyLOCAL = &OptLike{LikeTable: yyDollar[2].tableName} } yyVAL.union = yyLOCAL - case 242: + case 244: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *OptLike -//line sql.y:1767 +//line sql.y:1775 { yyLOCAL = &OptLike{LikeTable: yyDollar[3].tableName} } yyVAL.union = yyLOCAL - case 243: + case 245: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*ColumnDefinition -//line sql.y:1773 +//line sql.y:1781 { yyLOCAL = []*ColumnDefinition{yyDollar[1].columnDefinitionUnion()} } yyVAL.union = yyLOCAL - case 244: + case 246: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1777 +//line sql.y:1785 { yySLICE := (*[]*ColumnDefinition)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].columnDefinitionUnion()) } - case 245: + case 247: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *TableSpec -//line sql.y:1783 +//line sql.y:1791 { yyLOCAL = &TableSpec{} yyLOCAL.AddColumn(yyDollar[1].columnDefinitionUnion()) } yyVAL.union = yyLOCAL - case 246: + case 248: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *TableSpec -//line sql.y:1788 +//line sql.y:1796 { yyLOCAL = &TableSpec{} yyLOCAL.AddConstraint(yyDollar[1].constraintDefinitionUnion()) } yyVAL.union = yyLOCAL - case 247: + case 249: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1793 +//line sql.y:1801 { yyVAL.tableSpecUnion().AddColumn(yyDollar[3].columnDefinitionUnion()) } - case 248: + case 250: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1797 +//line sql.y:1805 { yyVAL.tableSpecUnion().AddColumn(yyDollar[3].columnDefinitionUnion()) yyVAL.tableSpecUnion().AddConstraint(yyDollar[4].constraintDefinitionUnion()) } - case 249: + case 251: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1802 +//line sql.y:1810 { yyVAL.tableSpecUnion().AddIndex(yyDollar[3].indexDefinitionUnion()) } - case 250: + case 252: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1806 +//line sql.y:1814 { yyVAL.tableSpecUnion().AddConstraint(yyDollar[3].constraintDefinitionUnion()) } - case 251: + case 253: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1810 +//line sql.y:1818 { yyVAL.tableSpecUnion().AddConstraint(yyDollar[3].constraintDefinitionUnion()) } - case 252: + case 254: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *ColumnDefinition -//line sql.y:1821 +//line sql.y:1829 { yyDollar[2].columnType.Options = yyDollar[4].columnTypeOptionsUnion() if yyDollar[2].columnType.Options.Collate == "" { @@ -12888,10 +13036,10 @@ yydefault: yyLOCAL = &ColumnDefinition{Name: yyDollar[1].identifierCI, Type: yyDollar[2].columnType} } yyVAL.union = yyLOCAL - case 253: + case 255: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL *ColumnDefinition -//line sql.y:1830 +//line sql.y:1838 { yyDollar[2].columnType.Options = yyDollar[9].columnTypeOptionsUnion() yyDollar[2].columnType.Options.As = yyDollar[7].exprUnion() @@ -12900,317 +13048,301 @@ yydefault: yyLOCAL = &ColumnDefinition{Name: yyDollar[1].identifierCI, Type: yyDollar[2].columnType} } yyVAL.union = yyLOCAL - case 254: + case 256: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1839 +//line sql.y:1847 { yyVAL.str = "" } - case 255: + case 257: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1843 +//line sql.y:1851 { yyVAL.str = "" } - case 256: + case 258: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1852 +//line sql.y:1860 { yyLOCAL = &ColumnTypeOptions{Null: nil, Default: nil, OnUpdate: nil, Autoincrement: false, KeyOpt: ColKeyNone, Comment: nil, As: nil, Invisible: nil, Format: UnspecifiedFormat, EngineAttribute: nil, SecondaryEngineAttribute: nil} } yyVAL.union = yyLOCAL - case 257: + case 259: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1856 +//line sql.y:1864 { yyDollar[1].columnTypeOptionsUnion().Null = ptr.Of(true) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() } yyVAL.union = yyLOCAL - case 258: + case 260: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1861 +//line sql.y:1869 { yyDollar[1].columnTypeOptionsUnion().Null = ptr.Of(false) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() } yyVAL.union = yyLOCAL - case 259: + case 261: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1866 +//line sql.y:1874 { yyDollar[1].columnTypeOptionsUnion().Default = yyDollar[4].exprUnion() yyLOCAL = yyDollar[1].columnTypeOptionsUnion() } yyVAL.union = yyLOCAL - case 260: + case 262: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1871 +//line sql.y:1879 { yyDollar[1].columnTypeOptionsUnion().Default = yyDollar[3].exprUnion() yyDollar[1].columnTypeOptionsUnion().DefaultLiteral = true yyLOCAL = yyDollar[1].columnTypeOptionsUnion() } yyVAL.union = yyLOCAL - case 261: + case 263: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1877 +//line sql.y:1885 { yyDollar[1].columnTypeOptionsUnion().OnUpdate = yyDollar[4].exprUnion() yyLOCAL = yyDollar[1].columnTypeOptionsUnion() } yyVAL.union = yyLOCAL - case 262: + case 264: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1882 +//line sql.y:1890 { yyDollar[1].columnTypeOptionsUnion().Autoincrement = true yyLOCAL = yyDollar[1].columnTypeOptionsUnion() } yyVAL.union = yyLOCAL - case 263: + case 265: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1887 +//line sql.y:1895 { yyDollar[1].columnTypeOptionsUnion().Comment = NewStrLiteral(yyDollar[3].str) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() } yyVAL.union = yyLOCAL - case 264: + case 266: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1892 +//line sql.y:1900 { yyDollar[1].columnTypeOptionsUnion().KeyOpt = yyDollar[2].colKeyOptUnion() yyLOCAL = yyDollar[1].columnTypeOptionsUnion() } yyVAL.union = yyLOCAL - case 265: + case 267: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1897 +//line sql.y:1905 { yyDollar[1].columnTypeOptionsUnion().Collate = encodeSQLString(yyDollar[3].str) } - case 266: + case 268: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1901 +//line sql.y:1909 { yyDollar[1].columnTypeOptionsUnion().Collate = string(yyDollar[3].identifierCI.String()) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() } yyVAL.union = yyLOCAL - case 267: + case 269: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1906 +//line sql.y:1914 { yyDollar[1].columnTypeOptionsUnion().Format = yyDollar[3].columnFormatUnion() } - case 268: + case 270: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1910 +//line sql.y:1918 { yyDollar[1].columnTypeOptionsUnion().SRID = NewIntLiteral(yyDollar[3].str) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() } yyVAL.union = yyLOCAL - case 269: + case 271: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1915 +//line sql.y:1923 { yyDollar[1].columnTypeOptionsUnion().Invisible = ptr.Of(false) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() } yyVAL.union = yyLOCAL - case 270: + case 272: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1920 +//line sql.y:1928 { yyDollar[1].columnTypeOptionsUnion().Invisible = ptr.Of(true) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() } yyVAL.union = yyLOCAL - case 271: + case 273: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1925 +//line sql.y:1933 { yyDollar[1].columnTypeOptionsUnion().EngineAttribute = NewStrLiteral(yyDollar[4].str) } - case 272: + case 274: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1929 +//line sql.y:1937 { yyDollar[1].columnTypeOptionsUnion().SecondaryEngineAttribute = NewStrLiteral(yyDollar[4].str) } - case 273: + case 275: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColumnFormat -//line sql.y:1935 +//line sql.y:1943 { yyLOCAL = FixedFormat } yyVAL.union = yyLOCAL - case 274: + case 276: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColumnFormat -//line sql.y:1939 +//line sql.y:1947 { yyLOCAL = DynamicFormat } yyVAL.union = yyLOCAL - case 275: + case 277: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColumnFormat -//line sql.y:1943 +//line sql.y:1951 { yyLOCAL = DefaultFormat } yyVAL.union = yyLOCAL - case 276: + case 278: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColumnFormat -//line sql.y:1947 +//line sql.y:1955 { yyLOCAL = CompressedFormat } yyVAL.union = yyLOCAL - case 277: + case 279: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColumnStorage -//line sql.y:1953 +//line sql.y:1961 { yyLOCAL = VirtualStorage } yyVAL.union = yyLOCAL - case 278: + case 280: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColumnStorage -//line sql.y:1957 +//line sql.y:1965 { yyLOCAL = StoredStorage } yyVAL.union = yyLOCAL - case 279: + case 281: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1962 +//line sql.y:1970 { yyLOCAL = &ColumnTypeOptions{} } yyVAL.union = yyLOCAL - case 280: + case 282: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1966 +//line sql.y:1974 { yyDollar[1].columnTypeOptionsUnion().Storage = yyDollar[2].columnStorageUnion() yyLOCAL = yyDollar[1].columnTypeOptionsUnion() } yyVAL.union = yyLOCAL - case 281: + case 283: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1971 +//line sql.y:1979 { yyDollar[1].columnTypeOptionsUnion().Null = ptr.Of(true) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() } yyVAL.union = yyLOCAL - case 282: + case 284: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1976 +//line sql.y:1984 { yyDollar[1].columnTypeOptionsUnion().Null = ptr.Of(false) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() } yyVAL.union = yyLOCAL - case 283: + case 285: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1981 +//line sql.y:1989 { yyDollar[1].columnTypeOptionsUnion().Comment = NewStrLiteral(yyDollar[3].str) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() } yyVAL.union = yyLOCAL - case 284: + case 286: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1986 +//line sql.y:1994 { yyDollar[1].columnTypeOptionsUnion().KeyOpt = yyDollar[2].colKeyOptUnion() yyLOCAL = yyDollar[1].columnTypeOptionsUnion() } yyVAL.union = yyLOCAL - case 285: + case 287: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1991 +//line sql.y:1999 { yyDollar[1].columnTypeOptionsUnion().SRID = NewIntLiteral(yyDollar[3].str) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() } yyVAL.union = yyLOCAL - case 286: + case 288: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1996 +//line sql.y:2004 { yyDollar[1].columnTypeOptionsUnion().Invisible = ptr.Of(false) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() } yyVAL.union = yyLOCAL - case 287: + case 289: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:2001 +//line sql.y:2009 { yyDollar[1].columnTypeOptionsUnion().Invisible = ptr.Of(true) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() } yyVAL.union = yyLOCAL - case 288: + case 290: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:2008 +//line sql.y:2016 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 290: - yyDollar = yyS[yypt-2 : yypt+1] - var yyLOCAL Expr -//line sql.y:2015 - { - yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("current_timestamp"), Fsp: yyDollar[2].integerUnion()} - } - yyVAL.union = yyLOCAL - case 291: - yyDollar = yyS[yypt-2 : yypt+1] - var yyLOCAL Expr -//line sql.y:2019 - { - yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("localtime"), Fsp: yyDollar[2].integerUnion()} - } - yyVAL.union = yyLOCAL case 292: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr //line sql.y:2023 { - yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("localtimestamp"), Fsp: yyDollar[2].integerUnion()} + yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("current_timestamp"), Fsp: yyDollar[2].integerUnion()} } yyVAL.union = yyLOCAL case 293: @@ -13218,7 +13350,7 @@ yydefault: var yyLOCAL Expr //line sql.y:2027 { - yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("utc_timestamp"), Fsp: yyDollar[2].integerUnion()} + yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("localtime"), Fsp: yyDollar[2].integerUnion()} } yyVAL.union = yyLOCAL case 294: @@ -13226,7 +13358,7 @@ yydefault: var yyLOCAL Expr //line sql.y:2031 { - yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("now"), Fsp: yyDollar[2].integerUnion()} + yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("localtimestamp"), Fsp: yyDollar[2].integerUnion()} } yyVAL.union = yyLOCAL case 295: @@ -13234,47 +13366,47 @@ yydefault: var yyLOCAL Expr //line sql.y:2035 { - yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("sysdate"), Fsp: yyDollar[2].integerUnion()} + yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("utc_timestamp"), Fsp: yyDollar[2].integerUnion()} } yyVAL.union = yyLOCAL - case 298: - yyDollar = yyS[yypt-1 : yypt+1] + case 296: + yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:2045 +//line sql.y:2039 { - yyLOCAL = &NullVal{} + yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("now"), Fsp: yyDollar[2].integerUnion()} } yyVAL.union = yyLOCAL - case 300: + case 297: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:2052 +//line sql.y:2043 { - yyLOCAL = yyDollar[2].exprUnion() + yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("sysdate"), Fsp: yyDollar[2].integerUnion()} } yyVAL.union = yyLOCAL - case 301: - yyDollar = yyS[yypt-2 : yypt+1] + case 300: + yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:2056 +//line sql.y:2053 { - yyLOCAL = &UnaryExpr{Operator: UMinusOp, Expr: yyDollar[2].exprUnion()} + yyLOCAL = &NullVal{} } yyVAL.union = yyLOCAL case 302: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:2062 +//line sql.y:2060 { - yyLOCAL = yyDollar[1].exprUnion() + yyLOCAL = yyDollar[2].exprUnion() } yyVAL.union = yyLOCAL case 303: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:2066 +//line sql.y:2064 { - yyLOCAL = yyDollar[1].exprUnion() + yyLOCAL = &UnaryExpr{Operator: UMinusOp, Expr: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL case 304: @@ -13282,7 +13414,7 @@ yydefault: var yyLOCAL Expr //line sql.y:2070 { - yyLOCAL = yyDollar[1].boolValUnion() + yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL case 305: @@ -13290,7 +13422,7 @@ yydefault: var yyLOCAL Expr //line sql.y:2074 { - yyLOCAL = NewHexLiteral(yyDollar[1].str) + yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL case 306: @@ -13298,7 +13430,7 @@ yydefault: var yyLOCAL Expr //line sql.y:2078 { - yyLOCAL = NewHexNumLiteral(yyDollar[1].str) + yyLOCAL = yyDollar[1].boolValUnion() } yyVAL.union = yyLOCAL case 307: @@ -13306,7 +13438,7 @@ yydefault: var yyLOCAL Expr //line sql.y:2082 { - yyLOCAL = NewBitLiteral(yyDollar[1].str) + yyLOCAL = NewHexLiteral(yyDollar[1].str) } yyVAL.union = yyLOCAL case 308: @@ -13314,7 +13446,7 @@ yydefault: var yyLOCAL Expr //line sql.y:2086 { - yyLOCAL = NewBitLiteral("0b" + yyDollar[1].str) + yyLOCAL = NewHexNumLiteral(yyDollar[1].str) } yyVAL.union = yyLOCAL case 309: @@ -13322,23 +13454,23 @@ yydefault: var yyLOCAL Expr //line sql.y:2090 { - yyLOCAL = parseBindVariable(yylex, yyDollar[1].str[1:]) + yyLOCAL = NewBitLiteral(yyDollar[1].str) } yyVAL.union = yyLOCAL case 310: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr //line sql.y:2094 { - yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: NewBitLiteral("0b" + yyDollar[2].str)} + yyLOCAL = NewBitLiteral("0b" + yyDollar[1].str) } yyVAL.union = yyLOCAL case 311: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr //line sql.y:2098 { - yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: NewHexNumLiteral(yyDollar[2].str)} + yyLOCAL = parseBindVariable(yylex, yyDollar[1].str[1:]) } yyVAL.union = yyLOCAL case 312: @@ -13346,7 +13478,7 @@ yydefault: var yyLOCAL Expr //line sql.y:2102 { - yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: NewBitLiteral(yyDollar[2].str)} + yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: NewBitLiteral("0b" + yyDollar[2].str)} } yyVAL.union = yyLOCAL case 313: @@ -13354,7 +13486,7 @@ yydefault: var yyLOCAL Expr //line sql.y:2106 { - yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: NewHexLiteral(yyDollar[2].str)} + yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: NewHexNumLiteral(yyDollar[2].str)} } yyVAL.union = yyLOCAL case 314: @@ -13362,24 +13494,24 @@ yydefault: var yyLOCAL Expr //line sql.y:2110 { - arg := parseBindVariable(yylex, yyDollar[2].str[1:]) - yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: arg} + yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: NewBitLiteral(yyDollar[2].str)} } yyVAL.union = yyLOCAL case 315: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:2115 +//line sql.y:2114 { - yyLOCAL = NewDateLiteral(yyDollar[2].str) + yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: NewHexLiteral(yyDollar[2].str)} } yyVAL.union = yyLOCAL case 316: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:2119 +//line sql.y:2118 { - yyLOCAL = NewTimeLiteral(yyDollar[2].str) + arg := parseBindVariable(yylex, yyDollar[2].str[1:]) + yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: arg} } yyVAL.union = yyLOCAL case 317: @@ -13387,254 +13519,258 @@ yydefault: var yyLOCAL Expr //line sql.y:2123 { - yyLOCAL = NewTimestampLiteral(yyDollar[2].str) + yyLOCAL = NewDateLiteral(yyDollar[2].str) } yyVAL.union = yyLOCAL case 318: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2129 + yyDollar = yyS[yypt-2 : yypt+1] + var yyLOCAL Expr +//line sql.y:2127 { - yyVAL.str = Armscii8Str + yyLOCAL = NewTimeLiteral(yyDollar[2].str) } + yyVAL.union = yyLOCAL case 319: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2133 + yyDollar = yyS[yypt-2 : yypt+1] + var yyLOCAL Expr +//line sql.y:2131 { - yyVAL.str = ASCIIStr + yyLOCAL = NewTimestampLiteral(yyDollar[2].str) } + yyVAL.union = yyLOCAL case 320: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2137 { - yyVAL.str = Big5Str + yyVAL.str = Armscii8Str } case 321: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2141 { - yyVAL.str = UBinaryStr + yyVAL.str = ASCIIStr } case 322: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2145 { - yyVAL.str = Cp1250Str + yyVAL.str = Big5Str } case 323: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2149 { - yyVAL.str = Cp1251Str + yyVAL.str = UBinaryStr } case 324: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2153 { - yyVAL.str = Cp1256Str + yyVAL.str = Cp1250Str } case 325: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2157 { - yyVAL.str = Cp1257Str + yyVAL.str = Cp1251Str } case 326: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2161 { - yyVAL.str = Cp850Str + yyVAL.str = Cp1256Str } case 327: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2165 { - yyVAL.str = Cp852Str + yyVAL.str = Cp1257Str } case 328: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2169 { - yyVAL.str = Cp866Str + yyVAL.str = Cp850Str } case 329: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2173 { - yyVAL.str = Cp932Str + yyVAL.str = Cp852Str } case 330: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2177 { - yyVAL.str = Dec8Str + yyVAL.str = Cp866Str } case 331: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2181 { - yyVAL.str = EucjpmsStr + yyVAL.str = Cp932Str } case 332: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2185 { - yyVAL.str = EuckrStr + yyVAL.str = Dec8Str } case 333: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2189 { - yyVAL.str = Gb18030Str + yyVAL.str = EucjpmsStr } case 334: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2193 { - yyVAL.str = Gb2312Str + yyVAL.str = EuckrStr } case 335: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2197 { - yyVAL.str = GbkStr + yyVAL.str = Gb18030Str } case 336: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2201 { - yyVAL.str = Geostd8Str + yyVAL.str = Gb2312Str } case 337: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2205 { - yyVAL.str = GreekStr + yyVAL.str = GbkStr } case 338: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2209 { - yyVAL.str = HebrewStr + yyVAL.str = Geostd8Str } case 339: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2213 { - yyVAL.str = Hp8Str + yyVAL.str = GreekStr } case 340: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2217 { - yyVAL.str = Keybcs2Str + yyVAL.str = HebrewStr } case 341: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2221 { - yyVAL.str = Koi8rStr + yyVAL.str = Hp8Str } case 342: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2225 { - yyVAL.str = Koi8uStr + yyVAL.str = Keybcs2Str } case 343: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2229 { - yyVAL.str = Latin1Str + yyVAL.str = Koi8rStr } case 344: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2233 { - yyVAL.str = Latin2Str + yyVAL.str = Koi8uStr } case 345: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2237 { - yyVAL.str = Latin5Str + yyVAL.str = Latin1Str } case 346: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2241 { - yyVAL.str = Latin7Str + yyVAL.str = Latin2Str } case 347: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2245 { - yyVAL.str = MacceStr + yyVAL.str = Latin5Str } case 348: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2249 { - yyVAL.str = MacromanStr + yyVAL.str = Latin7Str } case 349: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2253 { - yyVAL.str = SjisStr + yyVAL.str = MacceStr } case 350: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2257 { - yyVAL.str = Swe7Str + yyVAL.str = MacromanStr } case 351: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2261 { - yyVAL.str = Tis620Str + yyVAL.str = SjisStr } case 352: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2265 { - yyVAL.str = Ucs2Str + yyVAL.str = Swe7Str } case 353: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2269 { - yyVAL.str = UjisStr + yyVAL.str = Tis620Str } case 354: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2273 { - yyVAL.str = Utf16Str + yyVAL.str = Ucs2Str } case 355: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2277 { - yyVAL.str = Utf16leStr + yyVAL.str = UjisStr } case 356: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2281 { - yyVAL.str = Utf32Str + yyVAL.str = Utf16Str } case 357: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2285 { - yyVAL.str = Utf8mb3Str + yyVAL.str = Utf16leStr } case 358: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2289 { - yyVAL.str = Utf8mb4Str + yyVAL.str = Utf32Str } case 359: yyDollar = yyS[yypt-1 : yypt+1] @@ -13642,150 +13778,150 @@ yydefault: { yyVAL.str = Utf8mb3Str } - case 362: + case 360: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:2297 + { + yyVAL.str = Utf8mb4Str + } + case 361: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:2301 + { + yyVAL.str = Utf8mb3Str + } + case 364: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:2303 +//line sql.y:2311 { yyLOCAL = NewIntLiteral(yyDollar[1].str) } yyVAL.union = yyLOCAL - case 363: + case 365: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:2307 +//line sql.y:2315 { yyLOCAL = NewFloatLiteral(yyDollar[1].str) } yyVAL.union = yyLOCAL - case 364: + case 366: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:2311 +//line sql.y:2319 { yyLOCAL = NewDecimalLiteral(yyDollar[1].str) } yyVAL.union = yyLOCAL - case 365: + case 367: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:2317 +//line sql.y:2325 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 366: + case 368: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:2321 +//line sql.y:2329 { yyLOCAL = AppendString(yyDollar[1].exprUnion(), yyDollar[2].str) } yyVAL.union = yyLOCAL - case 367: + case 369: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:2327 +//line sql.y:2335 { yyLOCAL = NewStrLiteral(yyDollar[1].str) } yyVAL.union = yyLOCAL - case 368: + case 370: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:2331 +//line sql.y:2339 { yyLOCAL = &UnaryExpr{Operator: NStringOp, Expr: NewStrLiteral(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 369: + case 371: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:2335 +//line sql.y:2343 { yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: NewStrLiteral(yyDollar[2].str)} } yyVAL.union = yyLOCAL - case 370: + case 372: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:2341 +//line sql.y:2349 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 371: + case 373: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:2345 +//line sql.y:2353 { yyLOCAL = parseBindVariable(yylex, yyDollar[1].str[1:]) } yyVAL.union = yyLOCAL - case 372: + case 374: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL ColumnKeyOption -//line sql.y:2351 +//line sql.y:2359 { yyLOCAL = ColKeyPrimary } yyVAL.union = yyLOCAL - case 373: + case 375: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColumnKeyOption -//line sql.y:2355 +//line sql.y:2363 { yyLOCAL = ColKeyUnique } yyVAL.union = yyLOCAL - case 374: + case 376: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL ColumnKeyOption -//line sql.y:2359 +//line sql.y:2367 { yyLOCAL = ColKeyUniqueKey } yyVAL.union = yyLOCAL - case 375: + case 377: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColumnKeyOption -//line sql.y:2363 +//line sql.y:2371 { yyLOCAL = ColKey } yyVAL.union = yyLOCAL - case 376: + case 378: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2369 +//line sql.y:2377 { yyVAL.columnType = yyDollar[1].columnType yyVAL.columnType.Unsigned = yyDollar[2].booleanUnion() yyVAL.columnType.Zerofill = yyDollar[3].booleanUnion() } - case 380: + case 382: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2380 +//line sql.y:2388 { yyVAL.columnType = yyDollar[1].columnType yyVAL.columnType.Length = yyDollar[2].intPtrUnion() } - case 381: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2385 - { - yyVAL.columnType = yyDollar[1].columnType - } - case 382: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2391 - { - yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} - } case 383: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2395 +//line sql.y:2393 { - yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} + yyVAL.columnType = yyDollar[1].columnType } case 384: yyDollar = yyS[yypt-1 : yypt+1] @@ -13830,24 +13966,20 @@ yydefault: yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 391: - yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2429 + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:2427 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} - yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length - yyVAL.columnType.Scale = yyDollar[2].LengthScaleOption.Scale } case 392: - yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2435 + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:2431 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} - yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length - yyVAL.columnType.Scale = yyDollar[2].LengthScaleOption.Scale } case 393: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2441 +//line sql.y:2437 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -13855,7 +13987,7 @@ yydefault: } case 394: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2447 +//line sql.y:2443 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -13863,7 +13995,7 @@ yydefault: } case 395: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2453 +//line sql.y:2449 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -13871,7 +14003,7 @@ yydefault: } case 396: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2459 +//line sql.y:2455 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -13879,29 +14011,33 @@ yydefault: } case 397: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2465 +//line sql.y:2461 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length yyVAL.columnType.Scale = yyDollar[2].LengthScaleOption.Scale } case 398: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2473 + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:2467 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} + yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length + yyVAL.columnType.Scale = yyDollar[2].LengthScaleOption.Scale } case 399: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2477 +//line sql.y:2473 { - yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} + yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} + yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length + yyVAL.columnType.Scale = yyDollar[2].LengthScaleOption.Scale } case 400: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2481 { - yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} + yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 401: yyDollar = yyS[yypt-2 : yypt+1] @@ -13916,54 +14052,54 @@ yydefault: yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } case 403: - yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2495 + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:2493 { - yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion(), Charset: yyDollar[3].columnCharset} + yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } case 404: - yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2499 + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:2497 { - // CHAR BYTE is an alias for binary. See also: - // https://dev.mysql.com/doc/refman/8.0/en/string-type-syntax.html - yyVAL.columnType = &ColumnType{Type: "binary", Length: yyDollar[2].intPtrUnion()} + yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } case 405: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2505 +//line sql.y:2503 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion(), Charset: yyDollar[3].columnCharset} } case 406: - yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2509 + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:2507 { - yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} + // CHAR BYTE is an alias for binary. See also: + // https://dev.mysql.com/doc/refman/8.0/en/string-type-syntax.html + yyVAL.columnType = &ColumnType{Type: "binary", Length: yyDollar[2].intPtrUnion()} } case 407: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:2513 { - yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} + yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion(), Charset: yyDollar[3].columnCharset} } case 408: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:2517 { - yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion(), Charset: yyDollar[3].columnCharset} + yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } case 409: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:2521 { - yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Charset: yyDollar[2].columnCharset} + yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } case 410: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:2525 { - yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Charset: yyDollar[2].columnCharset} + yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion(), Charset: yyDollar[3].columnCharset} } case 411: yyDollar = yyS[yypt-2 : yypt+1] @@ -13975,19 +14111,19 @@ yydefault: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:2533 { - yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} + yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Charset: yyDollar[2].columnCharset} } case 413: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:2537 { - yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} + yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Charset: yyDollar[2].columnCharset} } case 414: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:2541 { - yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} + yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } case 415: yyDollar = yyS[yypt-1 : yypt+1] @@ -14002,34 +14138,34 @@ yydefault: yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 417: - yyDollar = yyS[yypt-5 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2553 { - yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), EnumValues: yyDollar[3].strs, Charset: yyDollar[5].columnCharset} + yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 418: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:2557 { - yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} + yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 419: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2562 +//line sql.y:2561 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), EnumValues: yyDollar[3].strs, Charset: yyDollar[5].columnCharset} } case 420: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2568 + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:2565 { - yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} + yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } case 421: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2572 + yyDollar = yyS[yypt-5 : yypt+1] +//line sql.y:2570 { - yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} + yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), EnumValues: yyDollar[3].strs, Charset: yyDollar[5].columnCharset} } case 422: yyDollar = yyS[yypt-1 : yypt+1] @@ -14069,810 +14205,806 @@ yydefault: } case 428: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2602 +//line sql.y:2600 + { + yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} + } + case 429: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:2604 + { + yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} + } + case 430: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:2610 { yyVAL.strs = make([]string, 0, 4) yyVAL.strs = append(yyVAL.strs, encodeSQLString(yyDollar[1].str)) } - case 429: + case 431: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2607 +//line sql.y:2615 { yyVAL.strs = append(yyDollar[1].strs, encodeSQLString(yyDollar[3].str)) } - case 430: + case 432: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *int -//line sql.y:2612 +//line sql.y:2620 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 431: + case 433: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *int -//line sql.y:2616 +//line sql.y:2624 { yyLOCAL = ptr.Of(convertStringToInt(yyDollar[2].str)) } yyVAL.union = yyLOCAL - case 432: + case 434: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2621 +//line sql.y:2629 { yyVAL.LengthScaleOption = LengthScaleOption{} } - case 433: + case 435: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2625 +//line sql.y:2633 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: ptr.Of(convertStringToInt(yyDollar[2].str)), Scale: ptr.Of(convertStringToInt(yyDollar[4].str)), } } - case 434: + case 436: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2634 +//line sql.y:2642 { yyVAL.LengthScaleOption = yyDollar[1].LengthScaleOption } - case 435: + case 437: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2638 +//line sql.y:2646 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: ptr.Of(convertStringToInt(yyDollar[2].str)), } } - case 436: + case 438: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2645 +//line sql.y:2653 { yyVAL.LengthScaleOption = LengthScaleOption{} } - case 437: + case 439: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2649 +//line sql.y:2657 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: ptr.Of(convertStringToInt(yyDollar[2].str)), } } - case 438: + case 440: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2655 +//line sql.y:2663 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: ptr.Of(convertStringToInt(yyDollar[2].str)), Scale: ptr.Of(convertStringToInt(yyDollar[4].str)), } } - case 439: + case 441: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:2663 +//line sql.y:2671 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 440: + case 442: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:2667 +//line sql.y:2675 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 441: + case 443: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:2671 +//line sql.y:2679 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 442: + case 444: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:2676 +//line sql.y:2684 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 443: + case 445: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:2680 +//line sql.y:2688 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 444: + case 446: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2685 +//line sql.y:2693 { yyVAL.columnCharset = ColumnCharset{} } - case 445: + case 447: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2689 +//line sql.y:2697 { yyVAL.columnCharset = ColumnCharset{Name: string(yyDollar[2].identifierCI.String()), Binary: yyDollar[3].booleanUnion()} } - case 446: + case 448: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2693 +//line sql.y:2701 { yyVAL.columnCharset = ColumnCharset{Name: encodeSQLString(yyDollar[2].str), Binary: yyDollar[3].booleanUnion()} } - case 447: + case 449: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2697 +//line sql.y:2705 { yyVAL.columnCharset = ColumnCharset{Name: string(yyDollar[2].str)} } - case 448: + case 450: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2701 +//line sql.y:2709 { // ASCII: Shorthand for CHARACTER SET latin1. yyVAL.columnCharset = ColumnCharset{Name: "latin1", Binary: yyDollar[2].booleanUnion()} } - case 449: + case 451: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2706 +//line sql.y:2714 { // UNICODE: Shorthand for CHARACTER SET ucs2. yyVAL.columnCharset = ColumnCharset{Name: "ucs2", Binary: yyDollar[2].booleanUnion()} } - case 450: + case 452: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2711 +//line sql.y:2719 { // BINARY: Shorthand for default CHARACTER SET but with binary collation yyVAL.columnCharset = ColumnCharset{Name: "", Binary: true} } - case 451: + case 453: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2716 +//line sql.y:2724 { // BINARY ASCII: Shorthand for CHARACTER SET latin1 with binary collation yyVAL.columnCharset = ColumnCharset{Name: "latin1", Binary: true} } - case 452: + case 454: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2721 +//line sql.y:2729 { // BINARY UNICODE: Shorthand for CHARACTER SET ucs2 with binary collation yyVAL.columnCharset = ColumnCharset{Name: "ucs2", Binary: true} } - case 453: + case 455: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:2727 +//line sql.y:2735 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 454: + case 456: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:2731 +//line sql.y:2739 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 455: + case 457: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2736 +//line sql.y:2744 { yyVAL.str = "" } - case 456: + case 458: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2740 +//line sql.y:2748 { yyVAL.str = string(yyDollar[2].identifierCI.String()) } - case 457: + case 459: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2744 +//line sql.y:2752 { yyVAL.str = encodeSQLString(yyDollar[2].str) } - case 458: + case 460: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *IndexDefinition -//line sql.y:2750 +//line sql.y:2758 { yyLOCAL = &IndexDefinition{Info: yyDollar[1].indexInfoUnion(), Columns: yyDollar[3].indexColumnsUnion(), Options: yyDollar[5].indexOptionsUnion()} } yyVAL.union = yyLOCAL - case 459: + case 461: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*IndexOption -//line sql.y:2755 +//line sql.y:2763 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 460: + case 462: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*IndexOption -//line sql.y:2759 +//line sql.y:2767 { yyLOCAL = yyDollar[1].indexOptionsUnion() } yyVAL.union = yyLOCAL - case 461: + case 463: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*IndexOption -//line sql.y:2765 +//line sql.y:2773 { yyLOCAL = []*IndexOption{yyDollar[1].indexOptionUnion()} } yyVAL.union = yyLOCAL - case 462: + case 464: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2769 +//line sql.y:2777 { yySLICE := (*[]*IndexOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[2].indexOptionUnion()) } - case 463: + case 465: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *IndexOption -//line sql.y:2775 +//line sql.y:2783 { yyLOCAL = yyDollar[1].indexOptionUnion() } yyVAL.union = yyLOCAL - case 464: + case 466: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *IndexOption -//line sql.y:2779 +//line sql.y:2787 { // should not be string yyLOCAL = &IndexOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 465: + case 467: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *IndexOption -//line sql.y:2784 +//line sql.y:2792 { yyLOCAL = &IndexOption{Name: string(yyDollar[1].str), Value: NewStrLiteral(yyDollar[2].str)} } yyVAL.union = yyLOCAL - case 466: + case 468: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *IndexOption -//line sql.y:2788 +//line sql.y:2796 { yyLOCAL = &IndexOption{Name: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 467: + case 469: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *IndexOption -//line sql.y:2792 +//line sql.y:2800 { yyLOCAL = &IndexOption{Name: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 468: + case 470: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *IndexOption -//line sql.y:2796 +//line sql.y:2804 { yyLOCAL = &IndexOption{Name: string(yyDollar[1].str) + " " + string(yyDollar[2].str), String: yyDollar[3].identifierCI.String()} } yyVAL.union = yyLOCAL - case 469: + case 471: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *IndexOption -//line sql.y:2800 +//line sql.y:2808 { yyLOCAL = &IndexOption{Name: string(yyDollar[1].str), Value: NewStrLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 470: + case 472: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *IndexOption -//line sql.y:2804 +//line sql.y:2812 { yyLOCAL = &IndexOption{Name: string(yyDollar[1].str), Value: NewStrLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 471: + case 473: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2810 +//line sql.y:2818 { yyVAL.str = "" } - case 472: + case 474: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2814 +//line sql.y:2822 { yyVAL.str = string(yyDollar[1].str) } - case 473: + case 475: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *IndexInfo -//line sql.y:2820 +//line sql.y:2828 { yyLOCAL = &IndexInfo{Type: IndexTypePrimary, ConstraintName: NewIdentifierCI(yyDollar[1].str), Name: NewIdentifierCI("PRIMARY")} } yyVAL.union = yyLOCAL - case 474: + case 476: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *IndexInfo -//line sql.y:2824 +//line sql.y:2832 { yyLOCAL = &IndexInfo{Type: IndexTypeSpatial, Name: NewIdentifierCI(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 475: + case 477: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *IndexInfo -//line sql.y:2828 +//line sql.y:2836 { yyLOCAL = &IndexInfo{Type: IndexTypeFullText, Name: NewIdentifierCI(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 476: + case 478: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *IndexInfo -//line sql.y:2832 +//line sql.y:2840 { yyLOCAL = &IndexInfo{Type: IndexTypeUnique, ConstraintName: NewIdentifierCI(yyDollar[1].str), Name: NewIdentifierCI(yyDollar[4].str)} } yyVAL.union = yyLOCAL - case 477: + case 479: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *IndexInfo -//line sql.y:2836 +//line sql.y:2844 { yyLOCAL = &IndexInfo{Type: IndexTypeDefault, Name: NewIdentifierCI(yyDollar[2].str)} } yyVAL.union = yyLOCAL - case 478: + case 480: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2841 +//line sql.y:2849 { yyVAL.str = "" } - case 479: + case 481: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2845 +//line sql.y:2853 { yyVAL.str = yyDollar[2].str } - case 480: + case 482: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2851 +//line sql.y:2859 { yyVAL.str = string(yyDollar[1].str) } - case 481: + case 483: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2855 +//line sql.y:2863 { yyVAL.str = string(yyDollar[1].str) } - case 482: + case 484: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2859 +//line sql.y:2867 { yyVAL.str = string(yyDollar[1].str) } - case 483: + case 485: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2865 +//line sql.y:2873 { yyVAL.str = string(yyDollar[1].str) } - case 484: + case 486: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2869 +//line sql.y:2877 { yyVAL.str = string(yyDollar[1].str) } - case 485: + case 487: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2874 +//line sql.y:2882 { yyVAL.str = "" } - case 486: + case 488: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2878 +//line sql.y:2886 { yyVAL.str = yyDollar[1].str } - case 487: + case 489: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2884 +//line sql.y:2892 { yyVAL.str = string(yyDollar[1].str) } - case 488: + case 490: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2888 +//line sql.y:2896 { yyVAL.str = string(yyDollar[1].str) } - case 489: + case 491: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2893 +//line sql.y:2901 { yyVAL.str = "" } - case 490: + case 492: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2897 +//line sql.y:2905 { yyVAL.str = string(yyDollar[1].identifierCI.String()) } - case 491: + case 493: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*IndexColumn -//line sql.y:2903 +//line sql.y:2911 { yyLOCAL = []*IndexColumn{yyDollar[1].indexColumnUnion()} } yyVAL.union = yyLOCAL - case 492: + case 494: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2907 +//line sql.y:2915 { yySLICE := (*[]*IndexColumn)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].indexColumnUnion()) } - case 493: + case 495: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *IndexColumn -//line sql.y:2913 +//line sql.y:2921 { yyLOCAL = &IndexColumn{Column: yyDollar[1].identifierCI, Length: yyDollar[2].intPtrUnion(), Direction: yyDollar[3].orderDirectionUnion()} } yyVAL.union = yyLOCAL - case 494: + case 496: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *IndexColumn -//line sql.y:2917 +//line sql.y:2925 { yyLOCAL = &IndexColumn{Expression: yyDollar[2].exprUnion(), Direction: yyDollar[4].orderDirectionUnion()} } yyVAL.union = yyLOCAL - case 495: + case 497: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ConstraintDefinition -//line sql.y:2923 +//line sql.y:2931 { yyLOCAL = &ConstraintDefinition{Name: yyDollar[2].identifierCI, Details: yyDollar[3].constraintInfoUnion()} } yyVAL.union = yyLOCAL - case 496: + case 498: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ConstraintDefinition -//line sql.y:2927 +//line sql.y:2935 { yyLOCAL = &ConstraintDefinition{Details: yyDollar[1].constraintInfoUnion()} } yyVAL.union = yyLOCAL - case 497: + case 499: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ConstraintDefinition -//line sql.y:2933 +//line sql.y:2941 { yyLOCAL = &ConstraintDefinition{Name: yyDollar[2].identifierCI, Details: yyDollar[3].constraintInfoUnion()} } yyVAL.union = yyLOCAL - case 498: + case 500: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ConstraintDefinition -//line sql.y:2937 +//line sql.y:2945 { yyLOCAL = &ConstraintDefinition{Details: yyDollar[1].constraintInfoUnion()} } yyVAL.union = yyLOCAL - case 499: + case 501: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL ConstraintInfo -//line sql.y:2943 +//line sql.y:2951 { yyLOCAL = &ForeignKeyDefinition{IndexName: NewIdentifierCI(yyDollar[3].str), Source: yyDollar[5].columnsUnion(), ReferenceDefinition: yyDollar[7].referenceDefinitionUnion()} } yyVAL.union = yyLOCAL - case 500: + case 502: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *ReferenceDefinition -//line sql.y:2949 +//line sql.y:2957 { yyLOCAL = &ReferenceDefinition{ReferencedTable: yyDollar[2].tableName, ReferencedColumns: yyDollar[4].columnsUnion(), Match: yyDollar[6].matchActionUnion()} } yyVAL.union = yyLOCAL - case 501: + case 503: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *ReferenceDefinition -//line sql.y:2953 +//line sql.y:2961 { yyLOCAL = &ReferenceDefinition{ReferencedTable: yyDollar[2].tableName, ReferencedColumns: yyDollar[4].columnsUnion(), Match: yyDollar[6].matchActionUnion(), OnDelete: yyDollar[7].referenceActionUnion()} } yyVAL.union = yyLOCAL - case 502: + case 504: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *ReferenceDefinition -//line sql.y:2957 +//line sql.y:2965 { yyLOCAL = &ReferenceDefinition{ReferencedTable: yyDollar[2].tableName, ReferencedColumns: yyDollar[4].columnsUnion(), Match: yyDollar[6].matchActionUnion(), OnUpdate: yyDollar[7].referenceActionUnion()} } yyVAL.union = yyLOCAL - case 503: + case 505: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *ReferenceDefinition -//line sql.y:2961 +//line sql.y:2969 { yyLOCAL = &ReferenceDefinition{ReferencedTable: yyDollar[2].tableName, ReferencedColumns: yyDollar[4].columnsUnion(), Match: yyDollar[6].matchActionUnion(), OnDelete: yyDollar[7].referenceActionUnion(), OnUpdate: yyDollar[8].referenceActionUnion()} } yyVAL.union = yyLOCAL - case 504: + case 506: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *ReferenceDefinition -//line sql.y:2965 +//line sql.y:2973 { yyLOCAL = &ReferenceDefinition{ReferencedTable: yyDollar[2].tableName, ReferencedColumns: yyDollar[4].columnsUnion(), Match: yyDollar[6].matchActionUnion(), OnUpdate: yyDollar[7].referenceActionUnion(), OnDelete: yyDollar[8].referenceActionUnion()} } yyVAL.union = yyLOCAL - case 505: + case 507: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ReferenceDefinition -//line sql.y:2970 +//line sql.y:2978 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 506: + case 508: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ReferenceDefinition -//line sql.y:2974 +//line sql.y:2982 { yyLOCAL = yyDollar[1].referenceDefinitionUnion() } yyVAL.union = yyLOCAL - case 507: + case 509: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL ConstraintInfo -//line sql.y:2980 +//line sql.y:2988 { yyLOCAL = &CheckConstraintDefinition{Expr: yyDollar[3].exprUnion(), Enforced: yyDollar[5].booleanUnion()} } yyVAL.union = yyLOCAL - case 508: + case 510: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL MatchAction -//line sql.y:2986 +//line sql.y:2994 { yyLOCAL = yyDollar[2].matchActionUnion() } yyVAL.union = yyLOCAL - case 509: + case 511: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL MatchAction -//line sql.y:2992 +//line sql.y:3000 { yyLOCAL = Full } yyVAL.union = yyLOCAL - case 510: + case 512: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL MatchAction -//line sql.y:2996 +//line sql.y:3004 { yyLOCAL = Partial } yyVAL.union = yyLOCAL - case 511: + case 513: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL MatchAction -//line sql.y:3000 +//line sql.y:3008 { yyLOCAL = Simple } yyVAL.union = yyLOCAL - case 512: + case 514: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL MatchAction -//line sql.y:3005 +//line sql.y:3013 { yyLOCAL = DefaultMatch } yyVAL.union = yyLOCAL - case 513: + case 515: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL MatchAction -//line sql.y:3009 +//line sql.y:3017 { yyLOCAL = yyDollar[1].matchActionUnion() } yyVAL.union = yyLOCAL - case 514: + case 516: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL ReferenceAction -//line sql.y:3015 +//line sql.y:3023 { yyLOCAL = yyDollar[3].referenceActionUnion() } yyVAL.union = yyLOCAL - case 515: + case 517: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL ReferenceAction -//line sql.y:3021 +//line sql.y:3029 { yyLOCAL = yyDollar[3].referenceActionUnion() } yyVAL.union = yyLOCAL - case 516: + case 518: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ReferenceAction -//line sql.y:3027 +//line sql.y:3035 { yyLOCAL = Restrict } yyVAL.union = yyLOCAL - case 517: + case 519: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ReferenceAction -//line sql.y:3031 +//line sql.y:3039 { yyLOCAL = Cascade } yyVAL.union = yyLOCAL - case 518: + case 520: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL ReferenceAction -//line sql.y:3035 +//line sql.y:3043 { yyLOCAL = NoAction } yyVAL.union = yyLOCAL - case 519: + case 521: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL ReferenceAction -//line sql.y:3039 +//line sql.y:3047 { yyLOCAL = SetDefault } yyVAL.union = yyLOCAL - case 520: + case 522: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL ReferenceAction -//line sql.y:3043 +//line sql.y:3051 { yyLOCAL = SetNull } yyVAL.union = yyLOCAL - case 521: + case 523: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3048 +//line sql.y:3056 { yyVAL.str = "" } - case 522: + case 524: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3052 +//line sql.y:3060 { yyVAL.str = string(yyDollar[1].str) } - case 523: + case 525: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3056 +//line sql.y:3064 { yyVAL.str = string(yyDollar[1].str) } - case 524: + case 526: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:3062 +//line sql.y:3070 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 525: + case 527: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:3066 +//line sql.y:3074 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 526: + case 528: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:3071 +//line sql.y:3079 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 527: + case 529: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:3075 +//line sql.y:3083 { yyLOCAL = yyDollar[1].booleanUnion() } yyVAL.union = yyLOCAL - case 528: + case 530: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL TableOptions -//line sql.y:3080 +//line sql.y:3088 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 529: + case 531: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableOptions -//line sql.y:3084 +//line sql.y:3092 { yyLOCAL = yyDollar[1].tableOptionsUnion() } yyVAL.union = yyLOCAL - case 530: + case 532: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableOptions -//line sql.y:3090 +//line sql.y:3098 { yyLOCAL = TableOptions{yyDollar[1].tableOptionUnion()} } yyVAL.union = yyLOCAL - case 531: + case 533: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3094 +//line sql.y:3102 { yySLICE := (*TableOptions)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].tableOptionUnion()) } - case 532: + case 534: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3098 +//line sql.y:3106 { yySLICE := (*TableOptions)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[2].tableOptionUnion()) } - case 533: + case 535: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableOptions -//line sql.y:3104 +//line sql.y:3112 { yyLOCAL = TableOptions{yyDollar[1].tableOptionUnion()} } yyVAL.union = yyLOCAL - case 534: + case 536: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3108 +//line sql.y:3116 { yySLICE := (*TableOptions)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[2].tableOptionUnion()) } - case 535: - yyDollar = yyS[yypt-3 : yypt+1] - var yyLOCAL *TableOption -//line sql.y:3114 - { - yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} - } - yyVAL.union = yyLOCAL - case 536: - yyDollar = yyS[yypt-3 : yypt+1] - var yyLOCAL *TableOption -//line sql.y:3118 - { - yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} - } - yyVAL.union = yyLOCAL case 537: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption @@ -14882,35 +15014,35 @@ yydefault: } yyVAL.union = yyLOCAL case 538: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption //line sql.y:3126 { - yyLOCAL = &TableOption{Name: (string(yyDollar[2].str)), String: yyDollar[4].str, CaseSensitive: true} + yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL case 539: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption //line sql.y:3130 { - yyLOCAL = &TableOption{Name: string(yyDollar[2].str), String: yyDollar[4].str, CaseSensitive: true} + yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL case 540: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *TableOption //line sql.y:3134 { - yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} + yyLOCAL = &TableOption{Name: (string(yyDollar[2].str)), String: yyDollar[4].str, CaseSensitive: true} } yyVAL.union = yyLOCAL case 541: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *TableOption //line sql.y:3138 { - yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewStrLiteral(yyDollar[3].str)} + yyLOCAL = &TableOption{Name: string(yyDollar[2].str), String: yyDollar[4].str, CaseSensitive: true} } yyVAL.union = yyLOCAL case 542: @@ -14918,7 +15050,7 @@ yydefault: var yyLOCAL *TableOption //line sql.y:3142 { - yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewStrLiteral(yyDollar[3].str)} + yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL case 543: @@ -14930,35 +15062,35 @@ yydefault: } yyVAL.union = yyLOCAL case 544: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption //line sql.y:3150 { - yyLOCAL = &TableOption{Name: (string(yyDollar[1].str) + " " + string(yyDollar[2].str)), Value: NewStrLiteral(yyDollar[4].str)} + yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewStrLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL case 545: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption //line sql.y:3154 { - yyLOCAL = &TableOption{Name: (string(yyDollar[1].str) + " " + string(yyDollar[2].str)), Value: NewStrLiteral(yyDollar[4].str)} + yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewStrLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL case 546: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *TableOption //line sql.y:3158 { - yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} + yyLOCAL = &TableOption{Name: (string(yyDollar[1].str) + " " + string(yyDollar[2].str)), Value: NewStrLiteral(yyDollar[4].str)} } yyVAL.union = yyLOCAL case 547: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *TableOption //line sql.y:3162 { - yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewStrLiteral(yyDollar[3].str)} + yyLOCAL = &TableOption{Name: (string(yyDollar[1].str) + " " + string(yyDollar[2].str)), Value: NewStrLiteral(yyDollar[4].str)} } yyVAL.union = yyLOCAL case 548: @@ -14966,7 +15098,7 @@ yydefault: var yyLOCAL *TableOption //line sql.y:3166 { - yyLOCAL = &TableOption{Name: string(yyDollar[1].str), String: yyDollar[3].identifierCS.String(), CaseSensitive: true} + yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL case 549: @@ -14982,7 +15114,7 @@ yydefault: var yyLOCAL *TableOption //line sql.y:3174 { - yyLOCAL = &TableOption{Name: string(yyDollar[1].str), String: string(yyDollar[3].str)} + yyLOCAL = &TableOption{Name: string(yyDollar[1].str), String: yyDollar[3].identifierCS.String(), CaseSensitive: true} } yyVAL.union = yyLOCAL case 551: @@ -14990,7 +15122,7 @@ yydefault: var yyLOCAL *TableOption //line sql.y:3178 { - yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} + yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewStrLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL case 552: @@ -14998,7 +15130,7 @@ yydefault: var yyLOCAL *TableOption //line sql.y:3182 { - yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} + yyLOCAL = &TableOption{Name: string(yyDollar[1].str), String: string(yyDollar[3].str)} } yyVAL.union = yyLOCAL case 553: @@ -15022,7 +15154,7 @@ yydefault: var yyLOCAL *TableOption //line sql.y:3194 { - yyLOCAL = &TableOption{Name: string(yyDollar[1].str), String: string(yyDollar[3].str)} + yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL case 556: @@ -15030,7 +15162,7 @@ yydefault: var yyLOCAL *TableOption //line sql.y:3198 { - yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewStrLiteral(yyDollar[3].str)} + yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL case 557: @@ -15054,7 +15186,7 @@ yydefault: var yyLOCAL *TableOption //line sql.y:3210 { - yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} + yyLOCAL = &TableOption{Name: string(yyDollar[1].str), String: string(yyDollar[3].str)} } yyVAL.union = yyLOCAL case 560: @@ -15062,7 +15194,7 @@ yydefault: var yyLOCAL *TableOption //line sql.y:3214 { - yyLOCAL = &TableOption{Name: string(yyDollar[1].str), String: string(yyDollar[3].str)} + yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewStrLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL case 561: @@ -15090,552 +15222,568 @@ yydefault: } yyVAL.union = yyLOCAL case 564: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption //line sql.y:3230 { - yyLOCAL = &TableOption{Name: string(yyDollar[1].str), String: (yyDollar[3].identifierCI.String() + yyDollar[4].str), CaseSensitive: true} + yyLOCAL = &TableOption{Name: string(yyDollar[1].str), String: string(yyDollar[3].str)} } yyVAL.union = yyLOCAL case 565: - yyDollar = yyS[yypt-5 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption //line sql.y:3234 { - yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Tables: yyDollar[4].tableNamesUnion()} + yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL case 566: + yyDollar = yyS[yypt-4 : yypt+1] + var yyLOCAL *TableOption +//line sql.y:3238 + { + yyLOCAL = &TableOption{Name: string(yyDollar[1].str), String: (yyDollar[3].identifierCI.String() + yyDollar[4].str), CaseSensitive: true} + } + yyVAL.union = yyLOCAL + case 567: + yyDollar = yyS[yypt-5 : yypt+1] + var yyLOCAL *TableOption +//line sql.y:3242 + { + yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Tables: yyDollar[4].tableNamesUnion()} + } + yyVAL.union = yyLOCAL + case 568: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3239 +//line sql.y:3247 { yyVAL.str = "" } - case 567: + case 569: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3243 +//line sql.y:3251 { yyVAL.str = " " + string(yyDollar[1].str) + " " + string(yyDollar[2].str) } - case 568: + case 570: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3247 +//line sql.y:3255 { yyVAL.str = " " + string(yyDollar[1].str) + " " + string(yyDollar[2].str) } - case 578: + case 580: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3266 +//line sql.y:3274 { yyVAL.str = String(TableName{Qualifier: yyDollar[1].identifierCS, Name: yyDollar[3].identifierCS}) } - case 579: + case 581: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3270 +//line sql.y:3278 { yyVAL.str = yyDollar[1].identifierCI.String() } - case 580: + case 582: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3274 +//line sql.y:3282 { yyVAL.str = encodeSQLString(yyDollar[1].str) } - case 581: + case 583: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3278 +//line sql.y:3286 { yyVAL.str = string(yyDollar[1].str) } - case 582: + case 584: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3283 +//line sql.y:3291 { yyVAL.str = "" } - case 584: + case 586: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:3289 +//line sql.y:3297 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 585: + case 587: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:3293 +//line sql.y:3301 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 586: + case 588: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ColName -//line sql.y:3298 +//line sql.y:3306 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 587: + case 589: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColName -//line sql.y:3302 +//line sql.y:3310 { yyLOCAL = yyDollar[2].colNameUnion() } yyVAL.union = yyLOCAL - case 588: + case 590: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3307 +//line sql.y:3315 { yyVAL.str = "" } - case 589: + case 591: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3311 +//line sql.y:3319 { yyVAL.str = string(yyDollar[2].str) } - case 590: + case 592: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *Literal -//line sql.y:3316 +//line sql.y:3324 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 591: + case 593: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *Literal -//line sql.y:3320 +//line sql.y:3328 { yyLOCAL = NewIntLiteral(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 592: + case 594: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *Literal -//line sql.y:3324 +//line sql.y:3332 { yyLOCAL = NewDecimalLiteral(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 593: + case 595: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:3329 +//line sql.y:3337 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 594: + case 596: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:3333 +//line sql.y:3341 { yyLOCAL = yyDollar[1].alterOptionsUnion() } yyVAL.union = yyLOCAL - case 595: + case 597: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:3337 +//line sql.y:3345 { yySLICE := (*[]AlterOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, &OrderByOption{Cols: yyDollar[5].columnsUnion()}) } - case 596: + case 598: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:3341 +//line sql.y:3349 { yyLOCAL = yyDollar[1].alterOptionsUnion() } yyVAL.union = yyLOCAL - case 597: + case 599: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3345 +//line sql.y:3353 { yySLICE := (*[]AlterOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].alterOptionsUnion()...) } - case 598: + case 600: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:3349 +//line sql.y:3357 { yyLOCAL = append(append(yyDollar[1].alterOptionsUnion(), yyDollar[3].alterOptionsUnion()...), &OrderByOption{Cols: yyDollar[7].columnsUnion()}) } yyVAL.union = yyLOCAL - case 599: + case 601: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:3355 +//line sql.y:3363 { yyLOCAL = []AlterOption{yyDollar[1].alterOptionUnion()} } yyVAL.union = yyLOCAL - case 600: + case 602: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3359 +//line sql.y:3367 { yySLICE := (*[]AlterOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].alterOptionUnion()) } - case 601: + case 603: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3363 +//line sql.y:3371 { yySLICE := (*[]AlterOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].alterOptionUnion()) } - case 602: + case 604: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3369 +//line sql.y:3377 { yyLOCAL = yyDollar[1].tableOptionsUnion() } yyVAL.union = yyLOCAL - case 603: + case 605: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3373 +//line sql.y:3381 { yyLOCAL = &AddConstraintDefinition{ConstraintDefinition: yyDollar[2].constraintDefinitionUnion()} } yyVAL.union = yyLOCAL - case 604: + case 606: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3377 +//line sql.y:3385 { yyLOCAL = &AddConstraintDefinition{ConstraintDefinition: yyDollar[2].constraintDefinitionUnion()} } yyVAL.union = yyLOCAL - case 605: + case 607: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3381 +//line sql.y:3389 { yyLOCAL = &AddIndexDefinition{IndexDefinition: yyDollar[2].indexDefinitionUnion()} } yyVAL.union = yyLOCAL - case 606: + case 608: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3385 +//line sql.y:3393 { yyLOCAL = &AddColumns{Columns: yyDollar[4].columnDefinitionsUnion()} } yyVAL.union = yyLOCAL - case 607: + case 609: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3389 +//line sql.y:3397 { yyLOCAL = &AddColumns{Columns: []*ColumnDefinition{yyDollar[3].columnDefinitionUnion()}, First: yyDollar[4].booleanUnion(), After: yyDollar[5].colNameUnion()} } yyVAL.union = yyLOCAL - case 608: + case 610: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3393 +//line sql.y:3401 { yyLOCAL = &AlterColumn{Column: yyDollar[3].colNameUnion(), DropDefault: true} } yyVAL.union = yyLOCAL - case 609: + case 611: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3397 +//line sql.y:3405 { yyLOCAL = &AlterColumn{Column: yyDollar[3].colNameUnion(), DropDefault: false, DefaultVal: yyDollar[6].exprUnion(), DefaultLiteral: true} } yyVAL.union = yyLOCAL - case 610: + case 612: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3401 +//line sql.y:3409 { yyLOCAL = &AlterColumn{Column: yyDollar[3].colNameUnion(), DropDefault: false, DefaultVal: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 611: + case 613: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3405 +//line sql.y:3413 { yyLOCAL = &AlterColumn{Column: yyDollar[3].colNameUnion(), Invisible: ptr.Of(false)} } yyVAL.union = yyLOCAL - case 612: + case 614: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3409 +//line sql.y:3417 { yyLOCAL = &AlterColumn{Column: yyDollar[3].colNameUnion(), Invisible: ptr.Of(true)} } yyVAL.union = yyLOCAL - case 613: + case 615: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3413 +//line sql.y:3421 { yyLOCAL = &AlterCheck{Name: yyDollar[3].identifierCI, Enforced: yyDollar[4].booleanUnion()} } yyVAL.union = yyLOCAL - case 614: + case 616: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3417 +//line sql.y:3425 { yyLOCAL = &AlterIndex{Name: yyDollar[3].identifierCI, Invisible: false} } yyVAL.union = yyLOCAL - case 615: + case 617: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3421 +//line sql.y:3429 { yyLOCAL = &AlterIndex{Name: yyDollar[3].identifierCI, Invisible: true} } yyVAL.union = yyLOCAL - case 616: + case 618: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3425 +//line sql.y:3433 { yyLOCAL = &ChangeColumn{OldColumn: yyDollar[3].colNameUnion(), NewColDefinition: yyDollar[4].columnDefinitionUnion(), First: yyDollar[5].booleanUnion(), After: yyDollar[6].colNameUnion()} } yyVAL.union = yyLOCAL - case 617: + case 619: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3429 +//line sql.y:3437 { yyLOCAL = &ModifyColumn{NewColDefinition: yyDollar[3].columnDefinitionUnion(), First: yyDollar[4].booleanUnion(), After: yyDollar[5].colNameUnion()} } yyVAL.union = yyLOCAL - case 618: + case 620: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3433 +//line sql.y:3441 { yyLOCAL = &RenameColumn{OldName: yyDollar[3].colNameUnion(), NewName: yyDollar[5].colNameUnion()} } yyVAL.union = yyLOCAL - case 619: + case 621: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3437 +//line sql.y:3445 { yyLOCAL = &AlterCharset{CharacterSet: yyDollar[4].str, Collate: yyDollar[5].str} } yyVAL.union = yyLOCAL - case 620: + case 622: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3441 +//line sql.y:3449 { yyLOCAL = &KeyState{Enable: false} } yyVAL.union = yyLOCAL - case 621: + case 623: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3445 +//line sql.y:3453 { yyLOCAL = &KeyState{Enable: true} } yyVAL.union = yyLOCAL - case 622: + case 624: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3449 +//line sql.y:3457 { yyLOCAL = &TablespaceOperation{Import: false} } yyVAL.union = yyLOCAL - case 623: + case 625: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3453 +//line sql.y:3461 { yyLOCAL = &TablespaceOperation{Import: true} } yyVAL.union = yyLOCAL - case 624: + case 626: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3457 +//line sql.y:3465 { yyLOCAL = &DropColumn{Name: yyDollar[3].colNameUnion()} } yyVAL.union = yyLOCAL - case 625: + case 627: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3461 +//line sql.y:3469 { yyLOCAL = &DropKey{Type: NormalKeyType, Name: yyDollar[3].identifierCI} } yyVAL.union = yyLOCAL - case 626: + case 628: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3465 +//line sql.y:3473 { yyLOCAL = &DropKey{Type: PrimaryKeyType} } yyVAL.union = yyLOCAL - case 627: + case 629: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3469 +//line sql.y:3477 { yyLOCAL = &DropKey{Type: ForeignKeyType, Name: yyDollar[4].identifierCI} } yyVAL.union = yyLOCAL - case 628: + case 630: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3473 +//line sql.y:3481 { yyLOCAL = &DropKey{Type: CheckKeyType, Name: yyDollar[3].identifierCI} } yyVAL.union = yyLOCAL - case 629: + case 631: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3477 +//line sql.y:3485 { - yyLOCAL = &DropKey{Type: CheckKeyType, Name: yyDollar[3].identifierCI} + yyLOCAL = &DropKey{Type: ConstraintType, Name: yyDollar[3].identifierCI} } yyVAL.union = yyLOCAL - case 630: + case 632: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3481 +//line sql.y:3489 { yyLOCAL = &Force{} } yyVAL.union = yyLOCAL - case 631: + case 633: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3485 +//line sql.y:3493 { yyLOCAL = &RenameTableName{Table: yyDollar[3].tableName} } yyVAL.union = yyLOCAL - case 632: + case 634: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3489 +//line sql.y:3497 { yyLOCAL = &RenameIndex{OldName: yyDollar[3].identifierCI, NewName: yyDollar[5].identifierCI} } yyVAL.union = yyLOCAL - case 633: + case 635: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:3495 +//line sql.y:3503 { yyLOCAL = []AlterOption{yyDollar[1].alterOptionUnion()} } yyVAL.union = yyLOCAL - case 634: + case 636: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3499 +//line sql.y:3507 { yySLICE := (*[]AlterOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].alterOptionUnion()) } - case 635: + case 637: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3505 +//line sql.y:3513 { yyLOCAL = AlgorithmValue(string(yyDollar[3].str)) } yyVAL.union = yyLOCAL - case 636: + case 638: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3509 +//line sql.y:3517 { yyLOCAL = AlgorithmValue(string(yyDollar[3].str)) } yyVAL.union = yyLOCAL - case 637: + case 639: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3513 +//line sql.y:3521 { yyLOCAL = AlgorithmValue(string(yyDollar[3].str)) } yyVAL.union = yyLOCAL - case 638: + case 640: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3517 +//line sql.y:3525 { yyLOCAL = AlgorithmValue(string(yyDollar[3].str)) } yyVAL.union = yyLOCAL - case 639: + case 641: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3521 +//line sql.y:3529 { yyLOCAL = &LockOption{Type: DefaultType} } yyVAL.union = yyLOCAL - case 640: + case 642: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3525 +//line sql.y:3533 { yyLOCAL = &LockOption{Type: NoneType} } yyVAL.union = yyLOCAL - case 641: + case 643: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3529 +//line sql.y:3537 { yyLOCAL = &LockOption{Type: SharedType} } yyVAL.union = yyLOCAL - case 642: + case 644: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3533 +//line sql.y:3541 { yyLOCAL = &LockOption{Type: ExclusiveType} } yyVAL.union = yyLOCAL - case 643: + case 645: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3537 +//line sql.y:3545 { yyLOCAL = &Validation{With: true} } yyVAL.union = yyLOCAL - case 644: + case 646: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3541 +//line sql.y:3549 { yyLOCAL = &Validation{With: false} } yyVAL.union = yyLOCAL - case 645: + case 647: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:3547 +//line sql.y:3555 { yyDollar[1].alterTableUnion().FullyParsed = true yyDollar[1].alterTableUnion().AlterOptions = yyDollar[2].alterOptionsUnion() @@ -15643,10 +15791,10 @@ yydefault: yyLOCAL = yyDollar[1].alterTableUnion() } yyVAL.union = yyLOCAL - case 646: + case 648: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:3554 +//line sql.y:3562 { yyDollar[1].alterTableUnion().FullyParsed = true yyDollar[1].alterTableUnion().AlterOptions = yyDollar[2].alterOptionsUnion() @@ -15654,10 +15802,10 @@ yydefault: yyLOCAL = yyDollar[1].alterTableUnion() } yyVAL.union = yyLOCAL - case 647: + case 649: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:3561 +//line sql.y:3569 { yyDollar[1].alterTableUnion().FullyParsed = true yyDollar[1].alterTableUnion().AlterOptions = yyDollar[2].alterOptionsUnion() @@ -15665,28 +15813,28 @@ yydefault: yyLOCAL = yyDollar[1].alterTableUnion() } yyVAL.union = yyLOCAL - case 648: + case 650: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:3568 +//line sql.y:3576 { yyDollar[1].alterTableUnion().FullyParsed = true yyDollar[1].alterTableUnion().PartitionSpec = yyDollar[2].partSpecUnion() yyLOCAL = yyDollar[1].alterTableUnion() } yyVAL.union = yyLOCAL - case 649: + case 651: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL Statement -//line sql.y:3574 +//line sql.y:3582 { yyLOCAL = &AlterView{ViewName: yyDollar[7].tableName, Comments: Comments(yyDollar[2].strs).Parsed(), Algorithm: yyDollar[3].str, Definer: yyDollar[4].definerUnion(), Security: yyDollar[5].str, Columns: yyDollar[8].columnsUnion(), Select: yyDollar[10].tableStmtUnion(), CheckOption: yyDollar[11].str} } yyVAL.union = yyLOCAL - case 650: + case 652: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:3584 +//line sql.y:3592 { yyDollar[1].alterDatabaseUnion().FullyParsed = true yyDollar[1].alterDatabaseUnion().DBName = yyDollar[2].identifierCS @@ -15694,10 +15842,10 @@ yydefault: yyLOCAL = yyDollar[1].alterDatabaseUnion() } yyVAL.union = yyLOCAL - case 651: + case 653: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:3591 +//line sql.y:3599 { yyDollar[1].alterDatabaseUnion().FullyParsed = true yyDollar[1].alterDatabaseUnion().DBName = yyDollar[2].identifierCS @@ -15705,10 +15853,10 @@ yydefault: yyLOCAL = yyDollar[1].alterDatabaseUnion() } yyVAL.union = yyLOCAL - case 652: + case 654: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Statement -//line sql.y:3598 +//line sql.y:3606 { yyLOCAL = &AlterVschema{ Action: CreateVindexDDLAction, @@ -15721,10 +15869,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 653: + case 655: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:3610 +//line sql.y:3618 { yyLOCAL = &AlterVschema{ Action: DropVindexDDLAction, @@ -15735,26 +15883,26 @@ yydefault: } } yyVAL.union = yyLOCAL - case 654: + case 656: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:3620 +//line sql.y:3628 { yyLOCAL = &AlterVschema{Action: AddVschemaTableDDLAction, Table: yyDollar[6].tableName} } yyVAL.union = yyLOCAL - case 655: + case 657: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:3624 +//line sql.y:3632 { yyLOCAL = &AlterVschema{Action: DropVschemaTableDDLAction, Table: yyDollar[6].tableName} } yyVAL.union = yyLOCAL - case 656: + case 658: yyDollar = yyS[yypt-13 : yypt+1] var yyLOCAL Statement -//line sql.y:3628 +//line sql.y:3636 { yyLOCAL = &AlterVschema{ Action: AddColVindexDDLAction, @@ -15768,10 +15916,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 657: + case 659: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Statement -//line sql.y:3641 +//line sql.y:3649 { yyLOCAL = &AlterVschema{ Action: DropColVindexDDLAction, @@ -15782,26 +15930,26 @@ yydefault: } } yyVAL.union = yyLOCAL - case 658: + case 660: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:3651 +//line sql.y:3659 { yyLOCAL = &AlterVschema{Action: AddSequenceDDLAction, Table: yyDollar[6].tableName} } yyVAL.union = yyLOCAL - case 659: + case 661: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:3655 +//line sql.y:3663 { yyLOCAL = &AlterVschema{Action: DropSequenceDDLAction, Table: yyDollar[6].tableName} } yyVAL.union = yyLOCAL - case 660: + case 662: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL Statement -//line sql.y:3659 +//line sql.y:3667 { yyLOCAL = &AlterVschema{ Action: AddAutoIncDDLAction, @@ -15813,10 +15961,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 661: + case 663: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:3670 +//line sql.y:3678 { yyLOCAL = &AlterVschema{ Action: DropAutoIncDDLAction, @@ -15824,10 +15972,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 662: + case 664: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3677 +//line sql.y:3685 { yyLOCAL = &AlterMigration{ Type: RetryMigrationType, @@ -15835,10 +15983,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 663: + case 665: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3684 +//line sql.y:3692 { yyLOCAL = &AlterMigration{ Type: CleanupMigrationType, @@ -15846,20 +15994,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 664: + case 666: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3691 +//line sql.y:3699 { yyLOCAL = &AlterMigration{ Type: CleanupAllMigrationType, } } yyVAL.union = yyLOCAL - case 665: + case 667: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3697 +//line sql.y:3705 { yyLOCAL = &AlterMigration{ Type: LaunchMigrationType, @@ -15867,10 +16015,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 666: + case 668: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:3704 +//line sql.y:3712 { yyLOCAL = &AlterMigration{ Type: LaunchMigrationType, @@ -15879,20 +16027,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 667: + case 669: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3712 +//line sql.y:3720 { yyLOCAL = &AlterMigration{ Type: LaunchAllMigrationType, } } yyVAL.union = yyLOCAL - case 668: + case 670: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3718 +//line sql.y:3726 { yyLOCAL = &AlterMigration{ Type: CompleteMigrationType, @@ -15900,20 +16048,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 669: + case 671: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3725 +//line sql.y:3733 { yyLOCAL = &AlterMigration{ Type: CompleteAllMigrationType, } } yyVAL.union = yyLOCAL - case 670: + case 672: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3731 +//line sql.y:3739 { yyLOCAL = &AlterMigration{ Type: CancelMigrationType, @@ -15921,20 +16069,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 671: + case 673: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3738 +//line sql.y:3746 { yyLOCAL = &AlterMigration{ Type: CancelAllMigrationType, } } yyVAL.union = yyLOCAL - case 672: + case 674: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:3744 +//line sql.y:3752 { yyLOCAL = &AlterMigration{ Type: ThrottleMigrationType, @@ -15944,10 +16092,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 673: + case 675: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:3753 +//line sql.y:3761 { yyLOCAL = &AlterMigration{ Type: ThrottleAllMigrationType, @@ -15956,10 +16104,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 674: + case 676: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3761 +//line sql.y:3769 { yyLOCAL = &AlterMigration{ Type: UnthrottleMigrationType, @@ -15967,20 +16115,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 675: + case 677: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3768 +//line sql.y:3776 { yyLOCAL = &AlterMigration{ Type: UnthrottleAllMigrationType, } } yyVAL.union = yyLOCAL - case 676: + case 678: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3774 +//line sql.y:3782 { yyLOCAL = &AlterMigration{ Type: ForceCutOverMigrationType, @@ -15988,20 +16136,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 677: + case 679: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3781 +//line sql.y:3789 { yyLOCAL = &AlterMigration{ Type: ForceCutOverAllMigrationType, } } yyVAL.union = yyLOCAL - case 678: + case 680: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:3787 +//line sql.y:3795 { yyLOCAL = &AlterMigration{ Type: SetCutOverThresholdMigrationType, @@ -16010,18 +16158,18 @@ yydefault: } } yyVAL.union = yyLOCAL - case 679: + case 681: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *PartitionOption -//line sql.y:3796 +//line sql.y:3804 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 680: + case 682: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *PartitionOption -//line sql.y:3800 +//line sql.y:3808 { yyDollar[3].partitionOptionUnion().Partitions = yyDollar[4].integerUnion() yyDollar[3].partitionOptionUnion().SubPartition = yyDollar[5].subPartitionUnion() @@ -16029,10 +16177,10 @@ yydefault: yyLOCAL = yyDollar[3].partitionOptionUnion() } yyVAL.union = yyLOCAL - case 681: + case 683: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *PartitionOption -//line sql.y:3809 +//line sql.y:3817 { yyLOCAL = &PartitionOption{ IsLinear: yyDollar[1].booleanUnion(), @@ -16041,10 +16189,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 682: + case 684: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *PartitionOption -//line sql.y:3817 +//line sql.y:3825 { yyLOCAL = &PartitionOption{ IsLinear: yyDollar[1].booleanUnion(), @@ -16054,10 +16202,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 683: + case 685: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *PartitionOption -//line sql.y:3826 +//line sql.y:3834 { yyLOCAL = &PartitionOption{ Type: yyDollar[1].partitionByTypeUnion(), @@ -16065,10 +16213,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 684: + case 686: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *PartitionOption -//line sql.y:3833 +//line sql.y:3841 { yyLOCAL = &PartitionOption{ Type: yyDollar[1].partitionByTypeUnion(), @@ -16076,18 +16224,18 @@ yydefault: } } yyVAL.union = yyLOCAL - case 685: + case 687: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *SubPartition -//line sql.y:3841 +//line sql.y:3849 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 686: + case 688: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *SubPartition -//line sql.y:3845 +//line sql.y:3853 { yyLOCAL = &SubPartition{ IsLinear: yyDollar[3].booleanUnion(), @@ -16097,10 +16245,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 687: + case 689: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL *SubPartition -//line sql.y:3854 +//line sql.y:3862 { yyLOCAL = &SubPartition{ IsLinear: yyDollar[3].booleanUnion(), @@ -16111,300 +16259,284 @@ yydefault: } } yyVAL.union = yyLOCAL - case 688: + case 690: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*PartitionDefinition -//line sql.y:3865 +//line sql.y:3873 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 689: + case 691: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*PartitionDefinition -//line sql.y:3869 +//line sql.y:3877 { yyLOCAL = yyDollar[2].partDefsUnion() } yyVAL.union = yyLOCAL - case 690: + case 692: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:3874 +//line sql.y:3882 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 691: + case 693: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:3878 +//line sql.y:3886 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 692: + case 694: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int -//line sql.y:3883 +//line sql.y:3891 { yyLOCAL = 0 } yyVAL.union = yyLOCAL - case 693: + case 695: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int -//line sql.y:3887 +//line sql.y:3895 { yyLOCAL = convertStringToInt(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 694: + case 696: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL TableExpr -//line sql.y:3893 +//line sql.y:3901 { yyLOCAL = &JSONTableExpr{Expr: yyDollar[3].exprUnion(), Filter: yyDollar[5].exprUnion(), Columns: yyDollar[6].jtColumnListUnion(), Alias: yyDollar[8].identifierCS} } yyVAL.union = yyLOCAL - case 695: + case 697: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL []*JtColumnDefinition -//line sql.y:3899 +//line sql.y:3907 { yyLOCAL = yyDollar[3].jtColumnListUnion() } yyVAL.union = yyLOCAL - case 696: + case 698: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*JtColumnDefinition -//line sql.y:3905 +//line sql.y:3913 { yyLOCAL = []*JtColumnDefinition{yyDollar[1].jtColumnDefinitionUnion()} } yyVAL.union = yyLOCAL - case 697: + case 699: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3909 +//line sql.y:3917 { yySLICE := (*[]*JtColumnDefinition)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].jtColumnDefinitionUnion()) } - case 698: + case 700: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *JtColumnDefinition -//line sql.y:3915 +//line sql.y:3923 { yyLOCAL = &JtColumnDefinition{JtOrdinal: &JtOrdinalColDef{Name: yyDollar[1].identifierCI}} } yyVAL.union = yyLOCAL - case 699: + case 701: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *JtColumnDefinition -//line sql.y:3919 +//line sql.y:3927 { yyDollar[2].columnType.Options = &ColumnTypeOptions{Collate: yyDollar[3].str} jtPath := &JtPathColDef{Name: yyDollar[1].identifierCI, Type: yyDollar[2].columnType, JtColExists: yyDollar[4].booleanUnion(), Path: yyDollar[6].exprUnion()} yyLOCAL = &JtColumnDefinition{JtPath: jtPath} } yyVAL.union = yyLOCAL - case 700: + case 702: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *JtColumnDefinition -//line sql.y:3925 +//line sql.y:3933 { yyDollar[2].columnType.Options = &ColumnTypeOptions{Collate: yyDollar[3].str} jtPath := &JtPathColDef{Name: yyDollar[1].identifierCI, Type: yyDollar[2].columnType, JtColExists: yyDollar[4].booleanUnion(), Path: yyDollar[6].exprUnion(), EmptyOnResponse: yyDollar[7].jtOnResponseUnion()} yyLOCAL = &JtColumnDefinition{JtPath: jtPath} } yyVAL.union = yyLOCAL - case 701: + case 703: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *JtColumnDefinition -//line sql.y:3931 +//line sql.y:3939 { yyDollar[2].columnType.Options = &ColumnTypeOptions{Collate: yyDollar[3].str} jtPath := &JtPathColDef{Name: yyDollar[1].identifierCI, Type: yyDollar[2].columnType, JtColExists: yyDollar[4].booleanUnion(), Path: yyDollar[6].exprUnion(), ErrorOnResponse: yyDollar[7].jtOnResponseUnion()} yyLOCAL = &JtColumnDefinition{JtPath: jtPath} } yyVAL.union = yyLOCAL - case 702: + case 704: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *JtColumnDefinition -//line sql.y:3937 +//line sql.y:3945 { yyDollar[2].columnType.Options = &ColumnTypeOptions{Collate: yyDollar[3].str} jtPath := &JtPathColDef{Name: yyDollar[1].identifierCI, Type: yyDollar[2].columnType, JtColExists: yyDollar[4].booleanUnion(), Path: yyDollar[6].exprUnion(), EmptyOnResponse: yyDollar[7].jtOnResponseUnion(), ErrorOnResponse: yyDollar[8].jtOnResponseUnion()} yyLOCAL = &JtColumnDefinition{JtPath: jtPath} } yyVAL.union = yyLOCAL - case 703: + case 705: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *JtColumnDefinition -//line sql.y:3943 +//line sql.y:3951 { jtNestedPath := &JtNestedPathColDef{Path: yyDollar[3].exprUnion(), Columns: yyDollar[4].jtColumnListUnion()} yyLOCAL = &JtColumnDefinition{JtNestedPath: jtNestedPath} } yyVAL.union = yyLOCAL - case 704: + case 706: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:3949 +//line sql.y:3957 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 705: + case 707: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:3953 +//line sql.y:3961 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 706: + case 708: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:3957 +//line sql.y:3965 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 707: + case 709: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:3961 +//line sql.y:3969 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 708: + case 710: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *JtOnResponse -//line sql.y:3967 +//line sql.y:3975 { yyLOCAL = yyDollar[1].jtOnResponseUnion() } yyVAL.union = yyLOCAL - case 709: + case 711: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *JtOnResponse -//line sql.y:3973 +//line sql.y:3981 { yyLOCAL = yyDollar[1].jtOnResponseUnion() } yyVAL.union = yyLOCAL - case 710: + case 712: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *JtOnResponse -//line sql.y:3979 +//line sql.y:3987 { yyLOCAL = &JtOnResponse{ResponseType: ErrorJSONType} } yyVAL.union = yyLOCAL - case 711: + case 713: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *JtOnResponse -//line sql.y:3983 +//line sql.y:3991 { yyLOCAL = &JtOnResponse{ResponseType: NullJSONType} } yyVAL.union = yyLOCAL - case 712: + case 714: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *JtOnResponse -//line sql.y:3987 +//line sql.y:3995 { yyLOCAL = &JtOnResponse{ResponseType: DefaultJSONType, Expr: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 713: + case 715: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL PartitionByType -//line sql.y:3993 +//line sql.y:4001 { yyLOCAL = RangeType } yyVAL.union = yyLOCAL - case 714: + case 716: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL PartitionByType -//line sql.y:3997 +//line sql.y:4005 { yyLOCAL = ListType } yyVAL.union = yyLOCAL - case 715: + case 717: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int -//line sql.y:4002 +//line sql.y:4010 { yyLOCAL = -1 } yyVAL.union = yyLOCAL - case 716: + case 718: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL int -//line sql.y:4006 +//line sql.y:4014 { yyLOCAL = convertStringToInt(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 717: + case 719: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int -//line sql.y:4011 +//line sql.y:4019 { yyLOCAL = -1 } yyVAL.union = yyLOCAL - case 718: + case 720: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL int -//line sql.y:4015 +//line sql.y:4023 { yyLOCAL = convertStringToInt(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 719: - yyDollar = yyS[yypt-5 : yypt+1] - var yyLOCAL *PartitionSpec -//line sql.y:4021 - { - yyLOCAL = &PartitionSpec{Action: AddAction, Definitions: []*PartitionDefinition{yyDollar[4].partDefUnion()}} - } - yyVAL.union = yyLOCAL - case 720: - yyDollar = yyS[yypt-3 : yypt+1] - var yyLOCAL *PartitionSpec -//line sql.y:4025 - { - yyLOCAL = &PartitionSpec{Action: DropAction, Names: yyDollar[3].partitionsUnion()} - } - yyVAL.union = yyLOCAL case 721: - yyDollar = yyS[yypt-7 : yypt+1] + yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *PartitionSpec //line sql.y:4029 { - yyLOCAL = &PartitionSpec{Action: ReorganizeAction, Names: yyDollar[3].partitionsUnion(), Definitions: yyDollar[6].partDefsUnion()} + yyLOCAL = &PartitionSpec{Action: AddAction, Definitions: []*PartitionDefinition{yyDollar[4].partDefUnion()}} } yyVAL.union = yyLOCAL case 722: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *PartitionSpec //line sql.y:4033 { - yyLOCAL = &PartitionSpec{Action: DiscardAction, Names: yyDollar[3].partitionsUnion()} + yyLOCAL = &PartitionSpec{Action: DropAction, Names: yyDollar[3].partitionsUnion()} } yyVAL.union = yyLOCAL case 723: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *PartitionSpec //line sql.y:4037 { - yyLOCAL = &PartitionSpec{Action: DiscardAction, IsAll: true} + yyLOCAL = &PartitionSpec{Action: ReorganizeAction, Names: yyDollar[3].partitionsUnion(), Definitions: yyDollar[6].partDefsUnion()} } yyVAL.union = yyLOCAL case 724: @@ -16412,7 +16544,7 @@ yydefault: var yyLOCAL *PartitionSpec //line sql.y:4041 { - yyLOCAL = &PartitionSpec{Action: ImportAction, Names: yyDollar[3].partitionsUnion()} + yyLOCAL = &PartitionSpec{Action: DiscardAction, Names: yyDollar[3].partitionsUnion()} } yyVAL.union = yyLOCAL case 725: @@ -16420,23 +16552,23 @@ yydefault: var yyLOCAL *PartitionSpec //line sql.y:4045 { - yyLOCAL = &PartitionSpec{Action: ImportAction, IsAll: true} + yyLOCAL = &PartitionSpec{Action: DiscardAction, IsAll: true} } yyVAL.union = yyLOCAL case 726: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *PartitionSpec //line sql.y:4049 { - yyLOCAL = &PartitionSpec{Action: TruncateAction, Names: yyDollar[3].partitionsUnion()} + yyLOCAL = &PartitionSpec{Action: ImportAction, Names: yyDollar[3].partitionsUnion()} } yyVAL.union = yyLOCAL case 727: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *PartitionSpec //line sql.y:4053 { - yyLOCAL = &PartitionSpec{Action: TruncateAction, IsAll: true} + yyLOCAL = &PartitionSpec{Action: ImportAction, IsAll: true} } yyVAL.union = yyLOCAL case 728: @@ -16444,15 +16576,15 @@ yydefault: var yyLOCAL *PartitionSpec //line sql.y:4057 { - yyLOCAL = &PartitionSpec{Action: CoalesceAction, Number: NewIntLiteral(yyDollar[3].str)} + yyLOCAL = &PartitionSpec{Action: TruncateAction, Names: yyDollar[3].partitionsUnion()} } yyVAL.union = yyLOCAL case 729: - yyDollar = yyS[yypt-7 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *PartitionSpec //line sql.y:4061 { - yyLOCAL = &PartitionSpec{Action: ExchangeAction, Names: Partitions{yyDollar[3].identifierCI}, TableName: yyDollar[6].tableName, WithoutValidation: yyDollar[7].booleanUnion()} + yyLOCAL = &PartitionSpec{Action: TruncateAction, IsAll: true} } yyVAL.union = yyLOCAL case 730: @@ -16460,15 +16592,15 @@ yydefault: var yyLOCAL *PartitionSpec //line sql.y:4065 { - yyLOCAL = &PartitionSpec{Action: AnalyzeAction, Names: yyDollar[3].partitionsUnion()} + yyLOCAL = &PartitionSpec{Action: CoalesceAction, Number: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL case 731: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *PartitionSpec //line sql.y:4069 { - yyLOCAL = &PartitionSpec{Action: AnalyzeAction, IsAll: true} + yyLOCAL = &PartitionSpec{Action: ExchangeAction, Names: Partitions{yyDollar[3].identifierCI}, TableName: yyDollar[6].tableName, WithoutValidation: yyDollar[7].booleanUnion()} } yyVAL.union = yyLOCAL case 732: @@ -16476,7 +16608,7 @@ yydefault: var yyLOCAL *PartitionSpec //line sql.y:4073 { - yyLOCAL = &PartitionSpec{Action: CheckAction, Names: yyDollar[3].partitionsUnion()} + yyLOCAL = &PartitionSpec{Action: AnalyzeAction, Names: yyDollar[3].partitionsUnion()} } yyVAL.union = yyLOCAL case 733: @@ -16484,7 +16616,7 @@ yydefault: var yyLOCAL *PartitionSpec //line sql.y:4077 { - yyLOCAL = &PartitionSpec{Action: CheckAction, IsAll: true} + yyLOCAL = &PartitionSpec{Action: AnalyzeAction, IsAll: true} } yyVAL.union = yyLOCAL case 734: @@ -16492,7 +16624,7 @@ yydefault: var yyLOCAL *PartitionSpec //line sql.y:4081 { - yyLOCAL = &PartitionSpec{Action: OptimizeAction, Names: yyDollar[3].partitionsUnion()} + yyLOCAL = &PartitionSpec{Action: CheckAction, Names: yyDollar[3].partitionsUnion()} } yyVAL.union = yyLOCAL case 735: @@ -16500,7 +16632,7 @@ yydefault: var yyLOCAL *PartitionSpec //line sql.y:4085 { - yyLOCAL = &PartitionSpec{Action: OptimizeAction, IsAll: true} + yyLOCAL = &PartitionSpec{Action: CheckAction, IsAll: true} } yyVAL.union = yyLOCAL case 736: @@ -16508,7 +16640,7 @@ yydefault: var yyLOCAL *PartitionSpec //line sql.y:4089 { - yyLOCAL = &PartitionSpec{Action: RebuildAction, Names: yyDollar[3].partitionsUnion()} + yyLOCAL = &PartitionSpec{Action: OptimizeAction, Names: yyDollar[3].partitionsUnion()} } yyVAL.union = yyLOCAL case 737: @@ -16516,7 +16648,7 @@ yydefault: var yyLOCAL *PartitionSpec //line sql.y:4093 { - yyLOCAL = &PartitionSpec{Action: RebuildAction, IsAll: true} + yyLOCAL = &PartitionSpec{Action: OptimizeAction, IsAll: true} } yyVAL.union = yyLOCAL case 738: @@ -16524,7 +16656,7 @@ yydefault: var yyLOCAL *PartitionSpec //line sql.y:4097 { - yyLOCAL = &PartitionSpec{Action: RepairAction, Names: yyDollar[3].partitionsUnion()} + yyLOCAL = &PartitionSpec{Action: RebuildAction, Names: yyDollar[3].partitionsUnion()} } yyVAL.union = yyLOCAL case 739: @@ -16532,257 +16664,273 @@ yydefault: var yyLOCAL *PartitionSpec //line sql.y:4101 { - yyLOCAL = &PartitionSpec{Action: RepairAction, IsAll: true} + yyLOCAL = &PartitionSpec{Action: RebuildAction, IsAll: true} } yyVAL.union = yyLOCAL case 740: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *PartitionSpec //line sql.y:4105 { - yyLOCAL = &PartitionSpec{Action: UpgradeAction} + yyLOCAL = &PartitionSpec{Action: RepairAction, Names: yyDollar[3].partitionsUnion()} } yyVAL.union = yyLOCAL case 741: + yyDollar = yyS[yypt-3 : yypt+1] + var yyLOCAL *PartitionSpec +//line sql.y:4109 + { + yyLOCAL = &PartitionSpec{Action: RepairAction, IsAll: true} + } + yyVAL.union = yyLOCAL + case 742: + yyDollar = yyS[yypt-2 : yypt+1] + var yyLOCAL *PartitionSpec +//line sql.y:4113 + { + yyLOCAL = &PartitionSpec{Action: UpgradeAction} + } + yyVAL.union = yyLOCAL + case 743: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:4110 +//line sql.y:4118 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 742: + case 744: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:4114 +//line sql.y:4122 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 743: + case 745: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:4118 +//line sql.y:4126 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 744: + case 746: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*PartitionDefinition -//line sql.y:4124 +//line sql.y:4132 { yyLOCAL = []*PartitionDefinition{yyDollar[1].partDefUnion()} } yyVAL.union = yyLOCAL - case 745: + case 747: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4128 +//line sql.y:4136 { yySLICE := (*[]*PartitionDefinition)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].partDefUnion()) } - case 746: + case 748: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4134 +//line sql.y:4142 { yyVAL.partDefUnion().Options = yyDollar[2].partitionDefinitionOptionsUnion() } - case 747: + case 749: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *PartitionDefinitionOptions -//line sql.y:4139 +//line sql.y:4147 { yyLOCAL = &PartitionDefinitionOptions{} } yyVAL.union = yyLOCAL - case 748: + case 750: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionDefinitionOptions -//line sql.y:4143 +//line sql.y:4151 { yyDollar[1].partitionDefinitionOptionsUnion().ValueRange = yyDollar[2].partitionValueRangeUnion() yyLOCAL = yyDollar[1].partitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 749: + case 751: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionDefinitionOptions -//line sql.y:4148 +//line sql.y:4156 { yyDollar[1].partitionDefinitionOptionsUnion().Comment = yyDollar[2].literalUnion() yyLOCAL = yyDollar[1].partitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 750: + case 752: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionDefinitionOptions -//line sql.y:4153 +//line sql.y:4161 { yyDollar[1].partitionDefinitionOptionsUnion().Engine = yyDollar[2].partitionEngineUnion() yyLOCAL = yyDollar[1].partitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 751: + case 753: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionDefinitionOptions -//line sql.y:4158 +//line sql.y:4166 { yyDollar[1].partitionDefinitionOptionsUnion().DataDirectory = yyDollar[2].literalUnion() yyLOCAL = yyDollar[1].partitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 752: + case 754: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionDefinitionOptions -//line sql.y:4163 +//line sql.y:4171 { yyDollar[1].partitionDefinitionOptionsUnion().IndexDirectory = yyDollar[2].literalUnion() yyLOCAL = yyDollar[1].partitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 753: + case 755: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionDefinitionOptions -//line sql.y:4168 +//line sql.y:4176 { yyDollar[1].partitionDefinitionOptionsUnion().MaxRows = ptr.Of(yyDollar[2].integerUnion()) yyLOCAL = yyDollar[1].partitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 754: + case 756: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionDefinitionOptions -//line sql.y:4173 +//line sql.y:4181 { yyDollar[1].partitionDefinitionOptionsUnion().MinRows = ptr.Of(yyDollar[2].integerUnion()) yyLOCAL = yyDollar[1].partitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 755: + case 757: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionDefinitionOptions -//line sql.y:4178 +//line sql.y:4186 { yyDollar[1].partitionDefinitionOptionsUnion().TableSpace = yyDollar[2].str yyLOCAL = yyDollar[1].partitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 756: + case 758: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionDefinitionOptions -//line sql.y:4183 +//line sql.y:4191 { yyDollar[1].partitionDefinitionOptionsUnion().SubPartitionDefinitions = yyDollar[2].subPartitionDefinitionsUnion() yyLOCAL = yyDollar[1].partitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 757: + case 759: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SubPartitionDefinitions -//line sql.y:4189 +//line sql.y:4197 { yyLOCAL = yyDollar[2].subPartitionDefinitionsUnion() } yyVAL.union = yyLOCAL - case 758: + case 760: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL SubPartitionDefinitions -//line sql.y:4195 +//line sql.y:4203 { yyLOCAL = SubPartitionDefinitions{yyDollar[1].subPartitionDefinitionUnion()} } yyVAL.union = yyLOCAL - case 759: + case 761: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4199 +//line sql.y:4207 { yySLICE := (*SubPartitionDefinitions)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].subPartitionDefinitionUnion()) } - case 760: + case 762: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *SubPartitionDefinition -//line sql.y:4205 +//line sql.y:4213 { yyLOCAL = &SubPartitionDefinition{Name: yyDollar[2].identifierCI, Options: yyDollar[3].subPartitionDefinitionOptionsUnion()} } yyVAL.union = yyLOCAL - case 761: + case 763: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *SubPartitionDefinitionOptions -//line sql.y:4210 +//line sql.y:4218 { yyLOCAL = &SubPartitionDefinitionOptions{} } yyVAL.union = yyLOCAL - case 762: + case 764: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *SubPartitionDefinitionOptions -//line sql.y:4214 +//line sql.y:4222 { yyDollar[1].subPartitionDefinitionOptionsUnion().Comment = yyDollar[2].literalUnion() yyLOCAL = yyDollar[1].subPartitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 763: + case 765: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *SubPartitionDefinitionOptions -//line sql.y:4219 +//line sql.y:4227 { yyDollar[1].subPartitionDefinitionOptionsUnion().Engine = yyDollar[2].partitionEngineUnion() yyLOCAL = yyDollar[1].subPartitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 764: + case 766: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *SubPartitionDefinitionOptions -//line sql.y:4224 +//line sql.y:4232 { yyDollar[1].subPartitionDefinitionOptionsUnion().DataDirectory = yyDollar[2].literalUnion() yyLOCAL = yyDollar[1].subPartitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 765: + case 767: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *SubPartitionDefinitionOptions -//line sql.y:4229 +//line sql.y:4237 { yyDollar[1].subPartitionDefinitionOptionsUnion().IndexDirectory = yyDollar[2].literalUnion() yyLOCAL = yyDollar[1].subPartitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 766: + case 768: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *SubPartitionDefinitionOptions -//line sql.y:4234 +//line sql.y:4242 { yyDollar[1].subPartitionDefinitionOptionsUnion().MaxRows = ptr.Of(yyDollar[2].integerUnion()) yyLOCAL = yyDollar[1].subPartitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 767: + case 769: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *SubPartitionDefinitionOptions -//line sql.y:4239 +//line sql.y:4247 { yyDollar[1].subPartitionDefinitionOptionsUnion().MinRows = ptr.Of(yyDollar[2].integerUnion()) yyLOCAL = yyDollar[1].subPartitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 768: + case 770: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *SubPartitionDefinitionOptions -//line sql.y:4244 +//line sql.y:4252 { yyDollar[1].subPartitionDefinitionOptionsUnion().TableSpace = yyDollar[2].str yyLOCAL = yyDollar[1].subPartitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 769: + case 771: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *PartitionValueRange -//line sql.y:4251 +//line sql.y:4259 { yyLOCAL = &PartitionValueRange{ Type: LessThanType, @@ -16790,10 +16938,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 770: + case 772: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *PartitionValueRange -//line sql.y:4258 +//line sql.y:4266 { yyLOCAL = &PartitionValueRange{ Type: LessThanType, @@ -16801,10 +16949,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 771: + case 773: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *PartitionValueRange -//line sql.y:4265 +//line sql.y:4273 { yyLOCAL = &PartitionValueRange{ Type: InType, @@ -16812,131 +16960,131 @@ yydefault: } } yyVAL.union = yyLOCAL - case 772: + case 774: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:4273 +//line sql.y:4281 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 773: + case 775: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:4277 +//line sql.y:4285 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 774: + case 776: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *PartitionEngine -//line sql.y:4283 +//line sql.y:4291 { yyLOCAL = &PartitionEngine{Storage: yyDollar[1].booleanUnion(), Name: yyDollar[4].identifierCS.String()} } yyVAL.union = yyLOCAL - case 775: + case 777: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *Literal -//line sql.y:4289 +//line sql.y:4297 { yyLOCAL = NewStrLiteral(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 776: + case 778: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *Literal -//line sql.y:4295 +//line sql.y:4303 { yyLOCAL = NewStrLiteral(yyDollar[4].str) } yyVAL.union = yyLOCAL - case 777: + case 779: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *Literal -//line sql.y:4301 +//line sql.y:4309 { yyLOCAL = NewStrLiteral(yyDollar[4].str) } yyVAL.union = yyLOCAL - case 778: + case 780: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int -//line sql.y:4307 +//line sql.y:4315 { yyLOCAL = convertStringToInt(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 779: + case 781: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int -//line sql.y:4313 +//line sql.y:4321 { yyLOCAL = convertStringToInt(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 780: + case 782: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4319 +//line sql.y:4327 { yyVAL.str = yyDollar[3].identifierCS.String() } - case 781: + case 783: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionDefinition -//line sql.y:4325 +//line sql.y:4333 { yyLOCAL = &PartitionDefinition{Name: yyDollar[2].identifierCI} } yyVAL.union = yyLOCAL - case 782: + case 784: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4331 +//line sql.y:4339 { yyVAL.str = "" } - case 783: + case 785: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4335 +//line sql.y:4343 { yyVAL.str = "" } - case 784: + case 786: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4341 +//line sql.y:4349 { yyLOCAL = &RenameTable{TablePairs: yyDollar[3].renameTablePairsUnion()} } yyVAL.union = yyLOCAL - case 785: + case 787: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*RenameTablePair -//line sql.y:4347 +//line sql.y:4355 { yyLOCAL = []*RenameTablePair{{FromTable: yyDollar[1].tableName, ToTable: yyDollar[3].tableName}} } yyVAL.union = yyLOCAL - case 786: + case 788: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:4351 +//line sql.y:4359 { yySLICE := (*[]*RenameTablePair)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, &RenameTablePair{FromTable: yyDollar[3].tableName, ToTable: yyDollar[5].tableName}) } - case 787: + case 789: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:4357 +//line sql.y:4365 { yyLOCAL = &DropTable{FromTables: yyDollar[6].tableNamesUnion(), IfExists: yyDollar[5].booleanUnion(), Comments: Comments(yyDollar[2].strs).Parsed(), Temp: yyDollar[3].booleanUnion()} } yyVAL.union = yyLOCAL - case 788: + case 790: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:4361 +//line sql.y:4369 { // Change this to an alter statement if yyDollar[4].identifierCI.Lowered() == "primary" { @@ -16946,92 +17094,76 @@ yydefault: } } yyVAL.union = yyLOCAL - case 789: + case 791: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:4370 +//line sql.y:4378 { yyLOCAL = &DropView{FromTables: yyDollar[5].tableNamesUnion(), Comments: Comments(yyDollar[2].strs).Parsed(), IfExists: yyDollar[4].booleanUnion()} } yyVAL.union = yyLOCAL - case 790: + case 792: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:4374 +//line sql.y:4382 { yyLOCAL = &DropDatabase{Comments: Comments(yyDollar[2].strs).Parsed(), DBName: yyDollar[5].identifierCS, IfExists: yyDollar[4].booleanUnion()} } yyVAL.union = yyLOCAL - case 791: + case 793: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:4378 +//line sql.y:4386 { yyLOCAL = &DropProcedure{Comments: Comments(yyDollar[2].strs).Parsed(), Name: yyDollar[5].tableName, IfExists: yyDollar[4].booleanUnion()} } yyVAL.union = yyLOCAL - case 792: + case 794: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4384 +//line sql.y:4392 { yyLOCAL = &TruncateTable{Table: yyDollar[3].tableName} } yyVAL.union = yyLOCAL - case 793: + case 795: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4388 +//line sql.y:4396 { yyLOCAL = &TruncateTable{Table: yyDollar[2].tableName} } yyVAL.union = yyLOCAL - case 794: + case 796: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4394 +//line sql.y:4402 { yyLOCAL = &Analyze{IsLocal: yyDollar[2].booleanUnion(), Table: yyDollar[4].tableName} } yyVAL.union = yyLOCAL - case 795: + case 797: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:4400 +//line sql.y:4408 { yyLOCAL = &PurgeBinaryLogs{To: string(yyDollar[5].str)} } yyVAL.union = yyLOCAL - case 796: + case 798: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:4404 +//line sql.y:4412 { yyLOCAL = &PurgeBinaryLogs{Before: string(yyDollar[5].str)} } yyVAL.union = yyLOCAL - case 797: - yyDollar = yyS[yypt-3 : yypt+1] - var yyLOCAL Statement -//line sql.y:4410 - { - yyLOCAL = &Show{&ShowBasic{Command: Charset, Filter: yyDollar[3].showFilterUnion()}} - } - yyVAL.union = yyLOCAL - case 798: - yyDollar = yyS[yypt-3 : yypt+1] - var yyLOCAL Statement -//line sql.y:4414 - { - yyLOCAL = &Show{&ShowBasic{Command: Collation, Filter: yyDollar[3].showFilterUnion()}} - } - yyVAL.union = yyLOCAL case 799: - yyDollar = yyS[yypt-7 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement //line sql.y:4418 { - yyLOCAL = &Show{&ShowBasic{Full: yyDollar[2].booleanUnion(), Command: Column, Tbl: yyDollar[5].tableName, DbName: yyDollar[6].identifierCS, Filter: yyDollar[7].showFilterUnion()}} + yyLOCAL = &Show{&ShowBasic{Command: Charset, Filter: yyDollar[3].showFilterUnion()}} } yyVAL.union = yyLOCAL case 800: @@ -17039,15 +17171,15 @@ yydefault: var yyLOCAL Statement //line sql.y:4422 { - yyLOCAL = &Show{&ShowBasic{Command: Database, Filter: yyDollar[3].showFilterUnion()}} + yyLOCAL = &Show{&ShowBasic{Command: Collation, Filter: yyDollar[3].showFilterUnion()}} } yyVAL.union = yyLOCAL case 801: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement //line sql.y:4426 { - yyLOCAL = &Show{&ShowBasic{Command: Database, Filter: yyDollar[3].showFilterUnion()}} + yyLOCAL = &Show{&ShowBasic{Full: yyDollar[2].booleanUnion(), Command: Column, Tbl: yyDollar[5].tableName, DbName: yyDollar[6].identifierCS, Filter: yyDollar[7].showFilterUnion()}} } yyVAL.union = yyLOCAL case 802: @@ -17055,7 +17187,7 @@ yydefault: var yyLOCAL Statement //line sql.y:4430 { - yyLOCAL = &Show{&ShowBasic{Command: Keyspace, Filter: yyDollar[3].showFilterUnion()}} + yyLOCAL = &Show{&ShowBasic{Command: Database, Filter: yyDollar[3].showFilterUnion()}} } yyVAL.union = yyLOCAL case 803: @@ -17063,55 +17195,55 @@ yydefault: var yyLOCAL Statement //line sql.y:4434 { - yyLOCAL = &Show{&ShowBasic{Command: Keyspace, Filter: yyDollar[3].showFilterUnion()}} + yyLOCAL = &Show{&ShowBasic{Command: Database, Filter: yyDollar[3].showFilterUnion()}} } yyVAL.union = yyLOCAL case 804: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement //line sql.y:4438 { - yyLOCAL = &Show{&ShowBasic{Command: Function, Filter: yyDollar[4].showFilterUnion()}} + yyLOCAL = &Show{&ShowBasic{Command: Keyspace, Filter: yyDollar[3].showFilterUnion()}} } yyVAL.union = yyLOCAL case 805: - yyDollar = yyS[yypt-7 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement //line sql.y:4442 { - yyLOCAL = &Show{&ShowBasic{Command: Index, Tbl: yyDollar[5].tableName, DbName: yyDollar[6].identifierCS, Filter: yyDollar[7].showFilterUnion()}} + yyLOCAL = &Show{&ShowBasic{Command: Keyspace, Filter: yyDollar[3].showFilterUnion()}} } yyVAL.union = yyLOCAL case 806: - yyDollar = yyS[yypt-5 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement //line sql.y:4446 { - yyLOCAL = &Show{&ShowBasic{Command: OpenTable, DbName: yyDollar[4].identifierCS, Filter: yyDollar[5].showFilterUnion()}} + yyLOCAL = &Show{&ShowBasic{Command: Function, Filter: yyDollar[4].showFilterUnion()}} } yyVAL.union = yyLOCAL case 807: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement //line sql.y:4450 { - yyLOCAL = &Show{&ShowBasic{Command: Privilege}} + yyLOCAL = &Show{&ShowBasic{Command: Index, Tbl: yyDollar[5].tableName, DbName: yyDollar[6].identifierCS, Filter: yyDollar[7].showFilterUnion()}} } yyVAL.union = yyLOCAL case 808: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement //line sql.y:4454 { - yyLOCAL = &Show{&ShowBasic{Command: Procedure, Filter: yyDollar[4].showFilterUnion()}} + yyLOCAL = &Show{&ShowBasic{Command: OpenTable, DbName: yyDollar[4].identifierCS, Filter: yyDollar[5].showFilterUnion()}} } yyVAL.union = yyLOCAL case 809: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement //line sql.y:4458 { - yyLOCAL = &Show{&ShowBasic{Command: StatusSession, Filter: yyDollar[4].showFilterUnion()}} + yyLOCAL = &Show{&ShowBasic{Command: Privilege}} } yyVAL.union = yyLOCAL case 810: @@ -17119,7 +17251,7 @@ yydefault: var yyLOCAL Statement //line sql.y:4462 { - yyLOCAL = &Show{&ShowBasic{Command: StatusGlobal, Filter: yyDollar[4].showFilterUnion()}} + yyLOCAL = &Show{&ShowBasic{Command: Procedure, Filter: yyDollar[4].showFilterUnion()}} } yyVAL.union = yyLOCAL case 811: @@ -17127,7 +17259,7 @@ yydefault: var yyLOCAL Statement //line sql.y:4466 { - yyLOCAL = &Show{&ShowBasic{Command: VariableSession, Filter: yyDollar[4].showFilterUnion()}} + yyLOCAL = &Show{&ShowBasic{Command: StatusSession, Filter: yyDollar[4].showFilterUnion()}} } yyVAL.union = yyLOCAL case 812: @@ -17135,39 +17267,39 @@ yydefault: var yyLOCAL Statement //line sql.y:4470 { - yyLOCAL = &Show{&ShowBasic{Command: VariableGlobal, Filter: yyDollar[4].showFilterUnion()}} + yyLOCAL = &Show{&ShowBasic{Command: StatusGlobal, Filter: yyDollar[4].showFilterUnion()}} } yyVAL.union = yyLOCAL case 813: - yyDollar = yyS[yypt-5 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement //line sql.y:4474 { - yyLOCAL = &Show{&ShowBasic{Command: TableStatus, DbName: yyDollar[4].identifierCS, Filter: yyDollar[5].showFilterUnion()}} + yyLOCAL = &Show{&ShowBasic{Command: VariableSession, Filter: yyDollar[4].showFilterUnion()}} } yyVAL.union = yyLOCAL case 814: - yyDollar = yyS[yypt-5 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement //line sql.y:4478 { - yyLOCAL = &Show{&ShowBasic{Command: Table, Full: yyDollar[2].booleanUnion(), DbName: yyDollar[4].identifierCS, Filter: yyDollar[5].showFilterUnion()}} + yyLOCAL = &Show{&ShowBasic{Command: VariableGlobal, Filter: yyDollar[4].showFilterUnion()}} } yyVAL.union = yyLOCAL case 815: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement //line sql.y:4482 { - yyLOCAL = &Show{&ShowBasic{Command: Trigger, DbName: yyDollar[3].identifierCS, Filter: yyDollar[4].showFilterUnion()}} + yyLOCAL = &Show{&ShowBasic{Command: TableStatus, DbName: yyDollar[4].identifierCS, Filter: yyDollar[5].showFilterUnion()}} } yyVAL.union = yyLOCAL case 816: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement //line sql.y:4486 { - yyLOCAL = &Show{&ShowCreate{Command: CreateDb, Op: yyDollar[4].tableName}} + yyLOCAL = &Show{&ShowBasic{Command: Table, Full: yyDollar[2].booleanUnion(), DbName: yyDollar[4].identifierCS, Filter: yyDollar[5].showFilterUnion()}} } yyVAL.union = yyLOCAL case 817: @@ -17175,7 +17307,7 @@ yydefault: var yyLOCAL Statement //line sql.y:4490 { - yyLOCAL = &Show{&ShowCreate{Command: CreateE, Op: yyDollar[4].tableName}} + yyLOCAL = &Show{&ShowBasic{Command: Trigger, DbName: yyDollar[3].identifierCS, Filter: yyDollar[4].showFilterUnion()}} } yyVAL.union = yyLOCAL case 818: @@ -17183,7 +17315,7 @@ yydefault: var yyLOCAL Statement //line sql.y:4494 { - yyLOCAL = &Show{&ShowCreate{Command: CreateF, Op: yyDollar[4].tableName}} + yyLOCAL = &Show{&ShowCreate{Command: CreateDb, Op: yyDollar[4].tableName}} } yyVAL.union = yyLOCAL case 819: @@ -17191,7 +17323,7 @@ yydefault: var yyLOCAL Statement //line sql.y:4498 { - yyLOCAL = &Show{&ShowCreate{Command: CreateProc, Op: yyDollar[4].tableName}} + yyLOCAL = &Show{&ShowCreate{Command: CreateE, Op: yyDollar[4].tableName}} } yyVAL.union = yyLOCAL case 820: @@ -17199,7 +17331,7 @@ yydefault: var yyLOCAL Statement //line sql.y:4502 { - yyLOCAL = &Show{&ShowCreate{Command: CreateTbl, Op: yyDollar[4].tableName}} + yyLOCAL = &Show{&ShowCreate{Command: CreateF, Op: yyDollar[4].tableName}} } yyVAL.union = yyLOCAL case 821: @@ -17207,7 +17339,7 @@ yydefault: var yyLOCAL Statement //line sql.y:4506 { - yyLOCAL = &Show{&ShowCreate{Command: CreateTr, Op: yyDollar[4].tableName}} + yyLOCAL = &Show{&ShowCreate{Command: CreateProc, Op: yyDollar[4].tableName}} } yyVAL.union = yyLOCAL case 822: @@ -17215,39 +17347,39 @@ yydefault: var yyLOCAL Statement //line sql.y:4510 { - yyLOCAL = &Show{&ShowCreate{Command: CreateV, Op: yyDollar[4].tableName}} + yyLOCAL = &Show{&ShowCreate{Command: CreateTbl, Op: yyDollar[4].tableName}} } yyVAL.union = yyLOCAL case 823: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement //line sql.y:4514 { - yyLOCAL = &Show{&ShowBasic{Command: Engines}} + yyLOCAL = &Show{&ShowCreate{Command: CreateTr, Op: yyDollar[4].tableName}} } yyVAL.union = yyLOCAL case 824: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement //line sql.y:4518 { - yyLOCAL = &Show{&ShowBasic{Command: Plugins}} + yyLOCAL = &Show{&ShowCreate{Command: CreateV, Op: yyDollar[4].tableName}} } yyVAL.union = yyLOCAL case 825: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement //line sql.y:4522 { - yyLOCAL = &Show{&ShowBasic{Command: GtidExecGlobal, DbName: yyDollar[4].identifierCS}} + yyLOCAL = &Show{&ShowBasic{Command: Engines}} } yyVAL.union = yyLOCAL case 826: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement //line sql.y:4526 { - yyLOCAL = &Show{&ShowBasic{Command: VGtidExecGlobal, DbName: yyDollar[4].identifierCS}} + yyLOCAL = &Show{&ShowBasic{Command: Plugins}} } yyVAL.union = yyLOCAL case 827: @@ -17255,7 +17387,7 @@ yydefault: var yyLOCAL Statement //line sql.y:4530 { - yyLOCAL = &Show{&ShowBasic{Command: VitessVariables, Filter: yyDollar[4].showFilterUnion()}} + yyLOCAL = &Show{&ShowBasic{Command: GtidExecGlobal, DbName: yyDollar[4].identifierCS}} } yyVAL.union = yyLOCAL case 828: @@ -17263,7 +17395,7 @@ yydefault: var yyLOCAL Statement //line sql.y:4534 { - yyLOCAL = &Show{&ShowBasic{Command: VitessMigrations, Filter: yyDollar[4].showFilterUnion(), DbName: yyDollar[3].identifierCS}} + yyLOCAL = &Show{&ShowBasic{Command: VGtidExecGlobal, DbName: yyDollar[4].identifierCS}} } yyVAL.union = yyLOCAL case 829: @@ -17271,31 +17403,31 @@ yydefault: var yyLOCAL Statement //line sql.y:4538 { - yyLOCAL = &ShowMigrationLogs{UUID: string(yyDollar[3].str)} + yyLOCAL = &Show{&ShowBasic{Command: VitessVariables, Filter: yyDollar[4].showFilterUnion()}} } yyVAL.union = yyLOCAL case 830: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement //line sql.y:4542 { - yyLOCAL = &ShowThrottledApps{} + yyLOCAL = &Show{&ShowBasic{Command: VitessMigrations, Filter: yyDollar[4].showFilterUnion(), DbName: yyDollar[3].identifierCS}} } yyVAL.union = yyLOCAL case 831: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement //line sql.y:4546 { - yyLOCAL = &Show{&ShowBasic{Command: VitessReplicationStatus, Filter: yyDollar[3].showFilterUnion()}} + yyLOCAL = &ShowMigrationLogs{UUID: string(yyDollar[3].str)} } yyVAL.union = yyLOCAL case 832: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement //line sql.y:4550 { - yyLOCAL = &ShowThrottlerStatus{} + yyLOCAL = &ShowThrottledApps{} } yyVAL.union = yyLOCAL case 833: @@ -17303,7 +17435,7 @@ yydefault: var yyLOCAL Statement //line sql.y:4554 { - yyLOCAL = &Show{&ShowBasic{Command: VschemaTables}} + yyLOCAL = &Show{&ShowBasic{Command: VitessReplicationStatus, Filter: yyDollar[3].showFilterUnion()}} } yyVAL.union = yyLOCAL case 834: @@ -17311,7 +17443,7 @@ yydefault: var yyLOCAL Statement //line sql.y:4558 { - yyLOCAL = &Show{&ShowBasic{Command: VschemaKeyspaces}} + yyLOCAL = &ShowThrottlerStatus{} } yyVAL.union = yyLOCAL case 835: @@ -17319,71 +17451,71 @@ yydefault: var yyLOCAL Statement //line sql.y:4562 { - yyLOCAL = &Show{&ShowBasic{Command: VschemaVindexes}} + yyLOCAL = &Show{&ShowBasic{Command: VschemaTables}} } yyVAL.union = yyLOCAL case 836: - yyDollar = yyS[yypt-5 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement //line sql.y:4566 { - yyLOCAL = &Show{&ShowBasic{Command: VschemaVindexes, Tbl: yyDollar[5].tableName}} + yyLOCAL = &Show{&ShowBasic{Command: VschemaKeyspaces}} } yyVAL.union = yyLOCAL case 837: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement //line sql.y:4570 { - yyLOCAL = &Show{&ShowBasic{Command: Warnings}} + yyLOCAL = &Show{&ShowBasic{Command: VschemaVindexes}} } yyVAL.union = yyLOCAL case 838: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement //line sql.y:4574 { - yyLOCAL = &Show{&ShowBasic{Command: VitessShards, Filter: yyDollar[3].showFilterUnion()}} + yyLOCAL = &Show{&ShowBasic{Command: VschemaVindexes, Tbl: yyDollar[5].tableName}} } yyVAL.union = yyLOCAL case 839: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement //line sql.y:4578 { - yyLOCAL = &Show{&ShowBasic{Command: VitessTablets, Filter: yyDollar[3].showFilterUnion()}} + yyLOCAL = &Show{&ShowBasic{Command: Warnings}} } yyVAL.union = yyLOCAL case 840: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement //line sql.y:4582 { - yyLOCAL = &Show{&ShowBasic{Command: VitessTarget}} + yyLOCAL = &Show{&ShowBasic{Command: VitessShards, Filter: yyDollar[3].showFilterUnion()}} } yyVAL.union = yyLOCAL case 841: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4589 +//line sql.y:4586 { - yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[2].identifierCI.String())}} + yyLOCAL = &Show{&ShowBasic{Command: VitessTablets, Filter: yyDollar[3].showFilterUnion()}} } yyVAL.union = yyLOCAL case 842: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4593 +//line sql.y:4590 { - yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[2].str) + " " + string(yyDollar[3].str)}} + yyLOCAL = &Show{&ShowBasic{Command: VitessTarget}} } yyVAL.union = yyLOCAL case 843: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement //line sql.y:4597 { - yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[2].str) + " " + yyDollar[3].identifierCI.String()}} + yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[2].identifierCI.String())}} } yyVAL.union = yyLOCAL case 844: @@ -17395,11 +17527,11 @@ yydefault: } yyVAL.union = yyLOCAL case 845: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement //line sql.y:4605 { - yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[2].str)}} + yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[2].str) + " " + yyDollar[3].identifierCI.String()}} } yyVAL.union = yyLOCAL case 846: @@ -17407,31 +17539,31 @@ yydefault: var yyLOCAL Statement //line sql.y:4609 { - yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[2].str) + " " + string(yyDollar[3].str) + " " + String(yyDollar[4].tableName)}} + yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[2].str) + " " + string(yyDollar[3].str)}} } yyVAL.union = yyLOCAL case 847: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement //line sql.y:4613 { - yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[2].str) + " " + string(yyDollar[3].str) + " " + String(yyDollar[4].tableName)}} + yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[2].str)}} } yyVAL.union = yyLOCAL case 848: - yyDollar = yyS[yypt-5 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement //line sql.y:4617 { - yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[3].str)}} + yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[2].str) + " " + string(yyDollar[3].str) + " " + String(yyDollar[4].tableName)}} } yyVAL.union = yyLOCAL case 849: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement //line sql.y:4621 { - yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[2].str)}} + yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[2].str) + " " + string(yyDollar[3].str) + " " + String(yyDollar[4].tableName)}} } yyVAL.union = yyLOCAL case 850: @@ -17439,7 +17571,7 @@ yydefault: var yyLOCAL Statement //line sql.y:4625 { - yyLOCAL = &Show{&ShowTransactionStatus{TransactionID: string(yyDollar[5].str)}} + yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[3].str)}} } yyVAL.union = yyLOCAL case 851: @@ -17447,7 +17579,7 @@ yydefault: var yyLOCAL Statement //line sql.y:4629 { - yyLOCAL = &Show{&ShowTransactionStatus{}} + yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[2].str)}} } yyVAL.union = yyLOCAL case 852: @@ -17455,677 +17587,681 @@ yydefault: var yyLOCAL Statement //line sql.y:4633 { - yyLOCAL = &Show{&ShowTransactionStatus{Keyspace: yyDollar[5].identifierCS.String()}} + yyLOCAL = &Show{&ShowTransactionStatus{TransactionID: string(yyDollar[5].str)}} } yyVAL.union = yyLOCAL case 853: - yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4638 + yyDollar = yyS[yypt-3 : yypt+1] + var yyLOCAL Statement +//line sql.y:4637 { + yyLOCAL = &Show{&ShowTransactionStatus{}} } + yyVAL.union = yyLOCAL case 854: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4640 + yyDollar = yyS[yypt-5 : yypt+1] + var yyLOCAL Statement +//line sql.y:4641 { + yyLOCAL = &Show{&ShowTransactionStatus{Keyspace: yyDollar[5].identifierCS.String()}} } + yyVAL.union = yyLOCAL case 855: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4644 +//line sql.y:4646 { - yyVAL.str = "" } case 856: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:4648 { - yyVAL.str = "extended " } case 857: yyDollar = yyS[yypt-0 : yypt+1] +//line sql.y:4652 + { + yyVAL.str = "" + } + case 858: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:4656 + { + yyVAL.str = "extended " + } + case 859: + yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:4654 +//line sql.y:4662 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 858: + case 860: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:4658 +//line sql.y:4666 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 859: + case 861: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4664 +//line sql.y:4672 { yyVAL.str = string(yyDollar[1].str) } - case 860: + case 862: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4668 +//line sql.y:4676 { yyVAL.str = string(yyDollar[1].str) } - case 861: + case 863: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4674 +//line sql.y:4682 { yyVAL.identifierCS = NewIdentifierCS("") } - case 862: + case 864: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4678 +//line sql.y:4686 { yyVAL.identifierCS = yyDollar[2].identifierCS } - case 863: + case 865: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4682 +//line sql.y:4690 { yyVAL.identifierCS = yyDollar[2].identifierCS } - case 864: + case 866: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ShowFilter -//line sql.y:4688 +//line sql.y:4696 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 865: + case 867: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ShowFilter -//line sql.y:4692 +//line sql.y:4700 { yyLOCAL = &ShowFilter{Like: string(yyDollar[2].str)} } yyVAL.union = yyLOCAL - case 866: + case 868: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ShowFilter -//line sql.y:4696 +//line sql.y:4704 { yyLOCAL = &ShowFilter{Filter: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 867: + case 869: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ShowFilter -//line sql.y:4702 +//line sql.y:4710 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 868: + case 870: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ShowFilter -//line sql.y:4706 +//line sql.y:4714 { yyLOCAL = &ShowFilter{Like: string(yyDollar[2].str)} } yyVAL.union = yyLOCAL - case 869: + case 871: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4712 +//line sql.y:4720 { yyVAL.empty = struct{}{} } - case 870: + case 872: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4716 +//line sql.y:4724 { yyVAL.empty = struct{}{} } - case 871: + case 873: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4720 +//line sql.y:4728 { yyVAL.empty = struct{}{} } - case 872: + case 874: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4726 +//line sql.y:4734 { yyVAL.str = string(yyDollar[1].str) } - case 873: + case 875: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4730 +//line sql.y:4738 { yyVAL.str = string(yyDollar[1].str) } - case 874: + case 876: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4736 +//line sql.y:4744 { yyLOCAL = &Use{DBName: yyDollar[2].identifierCS} } yyVAL.union = yyLOCAL - case 875: + case 877: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4740 +//line sql.y:4748 { yyLOCAL = &Use{DBName: IdentifierCS{v: ""}} } yyVAL.union = yyLOCAL - case 876: + case 878: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4744 +//line sql.y:4752 { yyLOCAL = &Use{DBName: NewIdentifierCS(yyDollar[2].identifierCS.String() + "@" + string(yyDollar[3].str))} } yyVAL.union = yyLOCAL - case 877: + case 879: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4751 +//line sql.y:4759 { yyVAL.identifierCS = NewIdentifierCS(string(yyDollar[1].str)) } - case 878: + case 880: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4755 +//line sql.y:4763 { yyVAL.identifierCS = NewIdentifierCS("@" + string(yyDollar[1].str)) } - case 879: + case 881: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4759 +//line sql.y:4767 { yyVAL.identifierCS = NewIdentifierCS("@@" + string(yyDollar[1].str)) } - case 880: + case 882: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4763 +//line sql.y:4771 { yyVAL.identifierCS = NewIdentifierCS(string(yyDollar[1].str)) } - case 881: + case 883: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4770 +//line sql.y:4778 { yyLOCAL = &Begin{Type: BeginStmt} } yyVAL.union = yyLOCAL - case 882: + case 884: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4774 +//line sql.y:4782 { yyLOCAL = &Begin{Type: StartTransactionStmt, TxAccessModes: yyDollar[3].txAccessModesUnion()} } yyVAL.union = yyLOCAL - case 883: + case 885: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []TxAccessMode -//line sql.y:4779 +//line sql.y:4787 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 884: + case 886: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []TxAccessMode -//line sql.y:4783 +//line sql.y:4791 { yyLOCAL = yyDollar[1].txAccessModesUnion() } yyVAL.union = yyLOCAL - case 885: + case 887: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []TxAccessMode -//line sql.y:4789 +//line sql.y:4797 { yyLOCAL = []TxAccessMode{yyDollar[1].txAccessModeUnion()} } yyVAL.union = yyLOCAL - case 886: + case 888: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4793 +//line sql.y:4801 { yySLICE := (*[]TxAccessMode)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].txAccessModeUnion()) } - case 887: + case 889: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL TxAccessMode -//line sql.y:4799 +//line sql.y:4807 { yyLOCAL = WithConsistentSnapshot } yyVAL.union = yyLOCAL - case 888: + case 890: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL TxAccessMode -//line sql.y:4803 +//line sql.y:4811 { yyLOCAL = ReadWrite } yyVAL.union = yyLOCAL - case 889: + case 891: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL TxAccessMode -//line sql.y:4807 +//line sql.y:4815 { yyLOCAL = ReadOnly } yyVAL.union = yyLOCAL - case 890: + case 892: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4814 +//line sql.y:4822 { yyLOCAL = &Commit{} } yyVAL.union = yyLOCAL - case 891: + case 893: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4820 +//line sql.y:4828 { yyLOCAL = &Rollback{} } yyVAL.union = yyLOCAL - case 892: + case 894: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:4824 +//line sql.y:4832 { yyLOCAL = &SRollback{Name: yyDollar[5].identifierCI} } yyVAL.union = yyLOCAL - case 893: + case 895: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4829 +//line sql.y:4837 { yyVAL.empty = struct{}{} } - case 894: + case 896: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4831 +//line sql.y:4839 { yyVAL.empty = struct{}{} } - case 895: + case 897: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4834 +//line sql.y:4842 { yyVAL.empty = struct{}{} } - case 896: + case 898: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4836 +//line sql.y:4844 { yyVAL.empty = struct{}{} } - case 897: + case 899: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4840 +//line sql.y:4848 { yyLOCAL = &Savepoint{Name: yyDollar[2].identifierCI} } yyVAL.union = yyLOCAL - case 898: + case 900: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4846 +//line sql.y:4854 { yyLOCAL = &Release{Name: yyDollar[3].identifierCI} } yyVAL.union = yyLOCAL - case 899: + case 901: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL ExplainType -//line sql.y:4851 +//line sql.y:4859 { yyLOCAL = EmptyType } yyVAL.union = yyLOCAL - case 900: + case 902: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL ExplainType -//line sql.y:4855 +//line sql.y:4863 { yyLOCAL = JSONType } yyVAL.union = yyLOCAL - case 901: + case 903: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL ExplainType -//line sql.y:4859 +//line sql.y:4867 { yyLOCAL = TreeType } yyVAL.union = yyLOCAL - case 902: + case 904: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL ExplainType -//line sql.y:4863 +//line sql.y:4871 { yyLOCAL = TraditionalType } yyVAL.union = yyLOCAL - case 903: + case 905: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ExplainType -//line sql.y:4867 +//line sql.y:4875 { yyLOCAL = AnalyzeType } yyVAL.union = yyLOCAL - case 904: + case 906: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL VExplainType -//line sql.y:4872 +//line sql.y:4880 { yyLOCAL = PlanVExplainType } yyVAL.union = yyLOCAL - case 905: + case 907: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL VExplainType -//line sql.y:4876 +//line sql.y:4884 { yyLOCAL = PlanVExplainType } yyVAL.union = yyLOCAL - case 906: + case 908: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL VExplainType -//line sql.y:4880 +//line sql.y:4888 { yyLOCAL = AllVExplainType } yyVAL.union = yyLOCAL - case 907: + case 909: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL VExplainType -//line sql.y:4884 +//line sql.y:4892 { yyLOCAL = QueriesVExplainType } yyVAL.union = yyLOCAL - case 908: + case 910: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL VExplainType -//line sql.y:4888 +//line sql.y:4896 { yyLOCAL = TraceVExplainType } yyVAL.union = yyLOCAL - case 909: + case 911: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL VExplainType -//line sql.y:4892 +//line sql.y:4900 { yyLOCAL = KeysVExplainType } yyVAL.union = yyLOCAL - case 910: + case 912: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4898 +//line sql.y:4906 { yyVAL.str = yyDollar[1].str } - case 911: + case 913: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4902 +//line sql.y:4910 { yyVAL.str = yyDollar[1].str } - case 912: + case 914: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4906 +//line sql.y:4914 { yyVAL.str = yyDollar[1].str } - case 913: + case 915: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4912 +//line sql.y:4920 { yyLOCAL = yyDollar[1].tableStmtUnion() } yyVAL.union = yyLOCAL - case 914: + case 916: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4916 +//line sql.y:4924 { yyLOCAL = yyDollar[1].statementUnion() } yyVAL.union = yyLOCAL - case 915: + case 917: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4920 +//line sql.y:4928 { yyLOCAL = yyDollar[1].statementUnion() } yyVAL.union = yyLOCAL - case 916: + case 918: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4924 +//line sql.y:4932 { yyLOCAL = yyDollar[1].statementUnion() } yyVAL.union = yyLOCAL - case 917: + case 919: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4929 +//line sql.y:4937 { yyVAL.str = "" } - case 918: + case 920: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4933 +//line sql.y:4941 { yyVAL.str = yyDollar[1].identifierCI.val } - case 919: + case 921: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4937 +//line sql.y:4945 { yyVAL.str = encodeSQLString(yyDollar[1].str) } - case 920: + case 922: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4943 +//line sql.y:4951 { yyLOCAL = &ExplainTab{Table: yyDollar[3].tableName, Wild: yyDollar[4].str} } yyVAL.union = yyLOCAL - case 921: + case 923: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4947 +//line sql.y:4955 { yyLOCAL = &ExplainStmt{Type: yyDollar[3].explainTypeUnion(), Statement: yyDollar[4].statementUnion(), Comments: Comments(yyDollar[2].strs).Parsed()} } yyVAL.union = yyLOCAL - case 922: + case 924: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4953 +//line sql.y:4961 { yyLOCAL = &VExplainStmt{Type: yyDollar[3].vexplainTypeUnion(), Statement: yyDollar[4].statementUnion(), Comments: Comments(yyDollar[2].strs).Parsed()} } yyVAL.union = yyLOCAL - case 923: + case 925: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4959 +//line sql.y:4967 { yyLOCAL = &OtherAdmin{} } yyVAL.union = yyLOCAL - case 924: + case 926: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4963 +//line sql.y:4971 { yyLOCAL = &OtherAdmin{} } yyVAL.union = yyLOCAL - case 925: + case 927: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4969 +//line sql.y:4977 { yyLOCAL = &LockTables{Tables: yyDollar[3].tableAndLockTypesUnion()} } yyVAL.union = yyLOCAL - case 926: + case 928: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableAndLockTypes -//line sql.y:4975 +//line sql.y:4983 { yyLOCAL = TableAndLockTypes{yyDollar[1].tableAndLockTypeUnion()} } yyVAL.union = yyLOCAL - case 927: + case 929: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4979 +//line sql.y:4987 { yySLICE := (*TableAndLockTypes)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].tableAndLockTypeUnion()) } - case 928: + case 930: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *TableAndLockType -//line sql.y:4985 +//line sql.y:4993 { yyLOCAL = &TableAndLockType{Table: yyDollar[1].aliasedTableNameUnion(), Lock: yyDollar[2].lockTypeUnion()} } yyVAL.union = yyLOCAL - case 929: + case 931: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL LockType -//line sql.y:4991 +//line sql.y:4999 { yyLOCAL = Read } yyVAL.union = yyLOCAL - case 930: + case 932: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL LockType -//line sql.y:4995 +//line sql.y:5003 { yyLOCAL = ReadLocal } yyVAL.union = yyLOCAL - case 931: + case 933: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL LockType -//line sql.y:4999 +//line sql.y:5007 { yyLOCAL = Write } yyVAL.union = yyLOCAL - case 932: + case 934: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL LockType -//line sql.y:5003 +//line sql.y:5011 { yyLOCAL = LowPriorityWrite } yyVAL.union = yyLOCAL - case 933: + case 935: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:5009 +//line sql.y:5017 { yyLOCAL = &UnlockTables{} } yyVAL.union = yyLOCAL - case 934: + case 936: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:5015 +//line sql.y:5023 { yyLOCAL = &RevertMigration{Comments: Comments(yyDollar[2].strs).Parsed(), UUID: string(yyDollar[4].str)} } yyVAL.union = yyLOCAL - case 935: + case 937: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:5021 +//line sql.y:5029 { yyLOCAL = &Flush{IsLocal: yyDollar[2].booleanUnion(), FlushOptions: yyDollar[3].strs} } yyVAL.union = yyLOCAL - case 936: + case 938: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:5025 +//line sql.y:5033 { yyLOCAL = &Flush{IsLocal: yyDollar[2].booleanUnion()} } yyVAL.union = yyLOCAL - case 937: + case 939: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:5029 +//line sql.y:5037 { yyLOCAL = &Flush{IsLocal: yyDollar[2].booleanUnion(), WithLock: true} } yyVAL.union = yyLOCAL - case 938: + case 940: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:5033 +//line sql.y:5041 { yyLOCAL = &Flush{IsLocal: yyDollar[2].booleanUnion(), TableNames: yyDollar[4].tableNamesUnion()} } yyVAL.union = yyLOCAL - case 939: + case 941: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:5037 +//line sql.y:5045 { yyLOCAL = &Flush{IsLocal: yyDollar[2].booleanUnion(), TableNames: yyDollar[4].tableNamesUnion(), WithLock: true} } yyVAL.union = yyLOCAL - case 940: + case 942: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:5041 +//line sql.y:5049 { yyLOCAL = &Flush{IsLocal: yyDollar[2].booleanUnion(), TableNames: yyDollar[4].tableNamesUnion(), ForExport: true} } yyVAL.union = yyLOCAL - case 941: + case 943: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5047 +//line sql.y:5055 { yyVAL.strs = []string{yyDollar[1].str} } - case 942: + case 944: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5051 +//line sql.y:5059 { yyVAL.strs = append(yyDollar[1].strs, yyDollar[3].str) } - case 943: - yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:5057 - { - yyVAL.str = string(yyDollar[1].str) + " " + string(yyDollar[2].str) - } - case 944: - yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:5061 - { - yyVAL.str = string(yyDollar[1].str) + " " + string(yyDollar[2].str) - } case 945: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:5065 @@ -18139,16 +18275,16 @@ yydefault: yyVAL.str = string(yyDollar[1].str) + " " + string(yyDollar[2].str) } case 947: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:5073 { - yyVAL.str = string(yyDollar[1].str) + yyVAL.str = string(yyDollar[1].str) + " " + string(yyDollar[2].str) } case 948: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:5077 { - yyVAL.str = string(yyDollar[1].str) + yyVAL.str = string(yyDollar[1].str) + " " + string(yyDollar[2].str) } case 949: yyDollar = yyS[yypt-1 : yypt+1] @@ -18157,28 +18293,28 @@ yydefault: yyVAL.str = string(yyDollar[1].str) } case 950: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:5085 { - yyVAL.str = string(yyDollar[1].str) + " " + string(yyDollar[2].str) + yyDollar[3].str + yyVAL.str = string(yyDollar[1].str) } case 951: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:5089 { - yyVAL.str = string(yyDollar[1].str) + " " + string(yyDollar[2].str) + yyVAL.str = string(yyDollar[1].str) } case 952: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:5093 { - yyVAL.str = string(yyDollar[1].str) + yyVAL.str = string(yyDollar[1].str) + " " + string(yyDollar[2].str) + yyDollar[3].str } case 953: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:5097 { - yyVAL.str = string(yyDollar[1].str) + yyVAL.str = string(yyDollar[1].str) + " " + string(yyDollar[2].str) } case 954: yyDollar = yyS[yypt-1 : yypt+1] @@ -18187,144 +18323,156 @@ yydefault: yyVAL.str = string(yyDollar[1].str) } case 955: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:5105 + { + yyVAL.str = string(yyDollar[1].str) + } + case 956: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:5109 + { + yyVAL.str = string(yyDollar[1].str) + } + case 957: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:5106 +//line sql.y:5114 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 956: + case 958: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:5110 +//line sql.y:5118 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 957: + case 959: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:5114 +//line sql.y:5122 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 958: + case 960: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:5119 +//line sql.y:5127 { yyVAL.str = "" } - case 959: + case 961: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5123 +//line sql.y:5131 { yyVAL.str = " " + string(yyDollar[1].str) + " " + string(yyDollar[2].str) + " " + yyDollar[3].identifierCI.String() } - case 960: + case 962: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:5128 +//line sql.y:5136 { setAllowComments(yylex, true) } - case 961: + case 963: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:5132 +//line sql.y:5140 { yyVAL.strs = yyDollar[2].strs setAllowComments(yylex, false) } - case 962: + case 964: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:5138 +//line sql.y:5146 { yyVAL.strs = nil } - case 963: + case 965: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:5142 +//line sql.y:5150 { yyVAL.strs = append(yyDollar[1].strs, yyDollar[2].str) } - case 964: + case 966: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:5148 +//line sql.y:5156 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 965: + case 967: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:5152 +//line sql.y:5160 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 966: + case 968: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:5156 +//line sql.y:5164 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 967: + case 969: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:5161 +//line sql.y:5169 { yyVAL.str = "" } - case 968: + case 970: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5165 +//line sql.y:5173 { yyVAL.str = SQLNoCacheStr } - case 969: + case 971: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5169 +//line sql.y:5177 { yyVAL.str = SQLCacheStr } - case 970: + case 972: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:5174 +//line sql.y:5182 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 971: + case 973: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:5178 +//line sql.y:5186 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 972: + case 974: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:5182 +//line sql.y:5190 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 973: + case 975: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:5188 +//line sql.y:5196 { yyLOCAL = &PrepareStmt{Name: yyDollar[3].identifierCI, Comments: Comments(yyDollar[2].strs).Parsed(), Statement: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 974: + case 976: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:5192 +//line sql.y:5200 { yyLOCAL = &PrepareStmt{ Name: yyDollar[3].identifierCI, @@ -18333,600 +18481,600 @@ yydefault: } } yyVAL.union = yyLOCAL - case 975: + case 977: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:5202 +//line sql.y:5210 { yyLOCAL = &ExecuteStmt{Name: yyDollar[3].identifierCI, Comments: Comments(yyDollar[2].strs).Parsed(), Arguments: yyDollar[4].variablesUnion()} } yyVAL.union = yyLOCAL - case 976: + case 978: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*Variable -//line sql.y:5207 +//line sql.y:5215 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 977: + case 979: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []*Variable -//line sql.y:5211 +//line sql.y:5219 { yyLOCAL = yyDollar[2].variablesUnion() } yyVAL.union = yyLOCAL - case 978: + case 980: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:5217 +//line sql.y:5225 { yyLOCAL = &DeallocateStmt{Comments: Comments(yyDollar[2].strs).Parsed(), Name: yyDollar[4].identifierCI} } yyVAL.union = yyLOCAL - case 979: + case 981: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:5221 +//line sql.y:5229 { yyLOCAL = &DeallocateStmt{Comments: Comments(yyDollar[2].strs).Parsed(), Name: yyDollar[4].identifierCI} } yyVAL.union = yyLOCAL - case 980: + case 982: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:5226 +//line sql.y:5234 { yyVAL.strs = nil } - case 981: + case 983: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5230 +//line sql.y:5238 { yyVAL.strs = yyDollar[1].strs } - case 982: + case 984: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5236 +//line sql.y:5244 { yyVAL.strs = []string{yyDollar[1].str} } - case 983: + case 985: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:5240 +//line sql.y:5248 { yyVAL.strs = append(yyDollar[1].strs, yyDollar[2].str) } - case 984: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5246 - { - yyVAL.str = SQLNoCacheStr - } - case 985: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5250 - { - yyVAL.str = SQLCacheStr - } case 986: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:5254 { - yyVAL.str = DistinctStr + yyVAL.str = SQLNoCacheStr } case 987: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:5258 { - yyVAL.str = DistinctStr + yyVAL.str = SQLCacheStr } case 988: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:5262 { - yyVAL.str = HighPriorityStr + yyVAL.str = DistinctStr } case 989: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:5266 { - yyVAL.str = StraightJoinHint + yyVAL.str = DistinctStr } case 990: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:5270 { - yyVAL.str = SQLBufferResultStr + yyVAL.str = HighPriorityStr } case 991: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:5274 { - yyVAL.str = SQLSmallResultStr + yyVAL.str = StraightJoinHint } case 992: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:5278 { - yyVAL.str = SQLBigResultStr + yyVAL.str = SQLBufferResultStr } case 993: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:5282 { - yyVAL.str = SQLCalcFoundRowsStr + yyVAL.str = SQLSmallResultStr } case 994: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:5286 { - yyVAL.str = AllStr // These are not picked up by NewSelect, and so ALL will be dropped. But this is OK, since it's redundant anyway + yyVAL.str = SQLBigResultStr } case 995: yyDollar = yyS[yypt-1 : yypt+1] - var yyLOCAL *SelectExprs -//line sql.y:5292 +//line sql.y:5290 { - yyLOCAL = &SelectExprs{Exprs: []SelectExpr{yyDollar[1].selectExprUnion()}} + yyVAL.str = SQLCalcFoundRowsStr } - yyVAL.union = yyLOCAL case 996: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:5294 + { + yyVAL.str = AllStr // These are not picked up by NewSelect, and so ALL will be dropped. But this is OK, since it's redundant anyway + } + case 997: + yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *SelectExprs -//line sql.y:5296 +//line sql.y:5300 { - res := yyDollar[1].selectExprsUnion() - res.Exprs = append(res.Exprs, yyDollar[3].selectExprUnion()) - yyLOCAL = res + yyLOCAL = &SelectExprs{Exprs: []SelectExpr{&StarExpr{}}} } yyVAL.union = yyLOCAL - case 997: + case 998: yyDollar = yyS[yypt-1 : yypt+1] - var yyLOCAL SelectExpr + var yyLOCAL *SelectExprs //line sql.y:5304 { - yyLOCAL = &StarExpr{} + yyLOCAL = &SelectExprs{Exprs: []SelectExpr{yyDollar[1].selectExprUnion()}} + } + yyVAL.union = yyLOCAL + case 999: + yyDollar = yyS[yypt-3 : yypt+1] + var yyLOCAL *SelectExprs +//line sql.y:5308 + { + res := yyDollar[1].selectExprsUnion() + res.Exprs = append(res.Exprs, yyDollar[3].selectExprUnion()) + yyLOCAL = res } yyVAL.union = yyLOCAL - case 998: + case 1000: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL SelectExpr -//line sql.y:5308 +//line sql.y:5316 { yyLOCAL = &AliasedExpr{Expr: yyDollar[1].exprUnion(), As: yyDollar[2].identifierCI} } yyVAL.union = yyLOCAL - case 999: + case 1001: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectExpr -//line sql.y:5312 +//line sql.y:5320 { yyLOCAL = &StarExpr{TableName: TableName{Name: yyDollar[1].identifierCS}} } yyVAL.union = yyLOCAL - case 1000: + case 1002: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL SelectExpr -//line sql.y:5316 +//line sql.y:5324 { yyLOCAL = &StarExpr{TableName: TableName{Qualifier: yyDollar[1].identifierCS, Name: yyDollar[3].identifierCS}} } yyVAL.union = yyLOCAL - case 1001: + case 1003: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:5321 +//line sql.y:5329 { yyVAL.identifierCI = IdentifierCI{} } - case 1002: + case 1004: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5325 +//line sql.y:5333 { yyVAL.identifierCI = yyDollar[1].identifierCI } - case 1003: + case 1005: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:5329 +//line sql.y:5337 { yyVAL.identifierCI = yyDollar[2].identifierCI } - case 1005: + case 1007: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5336 +//line sql.y:5344 { yyVAL.identifierCI = NewIdentifierCI(string(yyDollar[1].str)) } - case 1006: + case 1008: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL TableExprs -//line sql.y:5341 +//line sql.y:5349 { yyLOCAL = TableExprs{&AliasedTableExpr{Expr: TableName{Name: NewIdentifierCS("dual")}}} } yyVAL.union = yyLOCAL - case 1007: + case 1009: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableExprs -//line sql.y:5345 +//line sql.y:5353 { yyLOCAL = yyDollar[1].tableExprsUnion() } yyVAL.union = yyLOCAL - case 1008: + case 1010: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL TableExprs -//line sql.y:5351 +//line sql.y:5359 { yyLOCAL = yyDollar[2].tableExprsUnion() } yyVAL.union = yyLOCAL - case 1009: + case 1011: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableExprs -//line sql.y:5357 +//line sql.y:5365 { yyLOCAL = TableExprs{yyDollar[1].tableExprUnion()} } yyVAL.union = yyLOCAL - case 1010: + case 1012: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5361 +//line sql.y:5369 { yySLICE := (*TableExprs)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].tableExprUnion()) } - case 1013: + case 1015: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableExpr -//line sql.y:5371 +//line sql.y:5379 { yyLOCAL = yyDollar[1].aliasedTableNameUnion() } yyVAL.union = yyLOCAL - case 1014: + case 1016: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL TableExpr -//line sql.y:5375 +//line sql.y:5383 { yyLOCAL = &AliasedTableExpr{Expr: yyDollar[1].derivedTableUnion(), As: yyDollar[3].identifierCS, Columns: yyDollar[4].columnsUnion()} } yyVAL.union = yyLOCAL - case 1015: + case 1017: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL TableExpr -//line sql.y:5379 +//line sql.y:5387 { yyLOCAL = &ParenTableExpr{Exprs: yyDollar[2].tableExprsUnion()} } yyVAL.union = yyLOCAL - case 1016: + case 1018: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableExpr -//line sql.y:5383 +//line sql.y:5391 { yyLOCAL = yyDollar[1].tableExprUnion() } yyVAL.union = yyLOCAL - case 1017: + case 1019: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *DerivedTable -//line sql.y:5389 +//line sql.y:5397 { yyLOCAL = &DerivedTable{Lateral: false, Select: yyDollar[1].tableStmtUnion()} } yyVAL.union = yyLOCAL - case 1018: + case 1020: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *DerivedTable -//line sql.y:5393 +//line sql.y:5401 { yyLOCAL = &DerivedTable{Lateral: true, Select: yyDollar[2].tableStmtUnion()} } yyVAL.union = yyLOCAL - case 1019: + case 1021: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *AliasedTableExpr -//line sql.y:5399 +//line sql.y:5407 { yyLOCAL = &AliasedTableExpr{Expr: yyDollar[1].tableName, As: yyDollar[2].identifierCS, Hints: yyDollar[3].indexHintsUnion()} } yyVAL.union = yyLOCAL - case 1020: + case 1022: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *AliasedTableExpr -//line sql.y:5403 +//line sql.y:5411 { yyLOCAL = &AliasedTableExpr{Expr: yyDollar[1].tableName, Partitions: yyDollar[4].partitionsUnion(), As: yyDollar[6].identifierCS, Hints: yyDollar[7].indexHintsUnion()} } yyVAL.union = yyLOCAL - case 1021: + case 1023: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Columns -//line sql.y:5408 +//line sql.y:5416 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1022: + case 1024: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Columns -//line sql.y:5412 +//line sql.y:5420 { yyLOCAL = yyDollar[2].columnsUnion() } yyVAL.union = yyLOCAL - case 1023: + case 1025: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Columns -//line sql.y:5417 +//line sql.y:5425 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1024: + case 1026: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Columns -//line sql.y:5421 +//line sql.y:5429 { yyLOCAL = yyDollar[1].columnsUnion() } yyVAL.union = yyLOCAL - case 1025: + case 1027: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Columns -//line sql.y:5427 +//line sql.y:5435 { yyLOCAL = Columns{yyDollar[1].identifierCI} } yyVAL.union = yyLOCAL - case 1026: + case 1028: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5431 +//line sql.y:5439 { yySLICE := (*Columns)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].identifierCI) } - case 1027: + case 1029: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*Variable -//line sql.y:5437 +//line sql.y:5445 { yyLOCAL = []*Variable{yyDollar[1].variableUnion()} } yyVAL.union = yyLOCAL - case 1028: + case 1030: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5441 +//line sql.y:5449 { yySLICE := (*[]*Variable)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].variableUnion()) } - case 1029: + case 1031: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Columns -//line sql.y:5447 +//line sql.y:5455 { yyLOCAL = Columns{yyDollar[1].identifierCI} } yyVAL.union = yyLOCAL - case 1030: + case 1032: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Columns -//line sql.y:5451 +//line sql.y:5459 { yyLOCAL = Columns{NewIdentifierCI(string(yyDollar[1].str))} } yyVAL.union = yyLOCAL - case 1031: + case 1033: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5455 +//line sql.y:5463 { yySLICE := (*Columns)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].identifierCI) } - case 1032: + case 1034: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5459 +//line sql.y:5467 { yySLICE := (*Columns)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, NewIdentifierCI(string(yyDollar[3].str))) } - case 1033: + case 1035: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Partitions -//line sql.y:5465 +//line sql.y:5473 { yyLOCAL = Partitions{yyDollar[1].identifierCI} } yyVAL.union = yyLOCAL - case 1034: + case 1036: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5469 +//line sql.y:5477 { yySLICE := (*Partitions)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].identifierCI) } - case 1035: + case 1037: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL TableExpr -//line sql.y:5482 +//line sql.y:5490 { yyLOCAL = &JoinTableExpr{LeftExpr: yyDollar[1].tableExprUnion(), Join: yyDollar[2].joinTypeUnion(), RightExpr: yyDollar[3].tableExprUnion(), Condition: yyDollar[4].joinCondition} } yyVAL.union = yyLOCAL - case 1036: + case 1038: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL TableExpr -//line sql.y:5486 +//line sql.y:5494 { yyLOCAL = &JoinTableExpr{LeftExpr: yyDollar[1].tableExprUnion(), Join: yyDollar[2].joinTypeUnion(), RightExpr: yyDollar[3].tableExprUnion(), Condition: yyDollar[4].joinCondition} } yyVAL.union = yyLOCAL - case 1037: + case 1039: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL TableExpr -//line sql.y:5490 +//line sql.y:5498 { yyLOCAL = &JoinTableExpr{LeftExpr: yyDollar[1].tableExprUnion(), Join: yyDollar[2].joinTypeUnion(), RightExpr: yyDollar[3].tableExprUnion(), Condition: yyDollar[4].joinCondition} } yyVAL.union = yyLOCAL - case 1038: + case 1040: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL TableExpr -//line sql.y:5494 +//line sql.y:5502 { yyLOCAL = &JoinTableExpr{LeftExpr: yyDollar[1].tableExprUnion(), Join: yyDollar[2].joinTypeUnion(), RightExpr: yyDollar[3].tableExprUnion()} } yyVAL.union = yyLOCAL - case 1039: + case 1041: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:5500 +//line sql.y:5508 { yyVAL.joinCondition = &JoinCondition{On: yyDollar[2].exprUnion()} } - case 1040: + case 1042: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:5502 +//line sql.y:5510 { yyVAL.joinCondition = &JoinCondition{Using: yyDollar[3].columnsUnion()} } - case 1041: + case 1043: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:5506 +//line sql.y:5514 { yyVAL.joinCondition = &JoinCondition{} } - case 1042: + case 1044: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5508 +//line sql.y:5516 { yyVAL.joinCondition = yyDollar[1].joinCondition } - case 1043: + case 1045: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:5512 +//line sql.y:5520 { yyVAL.joinCondition = &JoinCondition{} } - case 1044: + case 1046: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:5514 +//line sql.y:5522 { yyVAL.joinCondition = &JoinCondition{On: yyDollar[2].exprUnion()} } - case 1045: + case 1047: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:5517 +//line sql.y:5525 { yyVAL.empty = struct{}{} } - case 1046: + case 1048: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5519 +//line sql.y:5527 { yyVAL.empty = struct{}{} } - case 1047: + case 1049: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:5522 +//line sql.y:5530 { yyVAL.identifierCS = NewIdentifierCS("") } - case 1048: + case 1050: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5526 +//line sql.y:5534 { yyVAL.identifierCS = yyDollar[1].identifierCS } - case 1049: + case 1051: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:5530 +//line sql.y:5538 { yyVAL.identifierCS = yyDollar[2].identifierCS } - case 1051: + case 1053: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5537 +//line sql.y:5545 { yyVAL.identifierCS = NewIdentifierCS(string(yyDollar[1].str)) } - case 1052: + case 1054: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL JoinType -//line sql.y:5543 +//line sql.y:5551 { yyLOCAL = NormalJoinType } yyVAL.union = yyLOCAL - case 1053: + case 1055: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL JoinType -//line sql.y:5547 +//line sql.y:5555 { yyLOCAL = NormalJoinType } yyVAL.union = yyLOCAL - case 1054: + case 1056: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL JoinType -//line sql.y:5551 +//line sql.y:5559 { yyLOCAL = NormalJoinType } yyVAL.union = yyLOCAL - case 1055: + case 1057: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL JoinType -//line sql.y:5557 +//line sql.y:5565 { yyLOCAL = StraightJoinType } yyVAL.union = yyLOCAL - case 1056: + case 1058: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL JoinType -//line sql.y:5563 +//line sql.y:5571 { yyLOCAL = LeftJoinType } yyVAL.union = yyLOCAL - case 1057: + case 1059: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL JoinType -//line sql.y:5567 +//line sql.y:5575 { yyLOCAL = LeftJoinType } yyVAL.union = yyLOCAL - case 1058: + case 1060: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL JoinType -//line sql.y:5571 +//line sql.y:5579 { yyLOCAL = RightJoinType } yyVAL.union = yyLOCAL - case 1059: + case 1061: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL JoinType -//line sql.y:5575 +//line sql.y:5583 { yyLOCAL = RightJoinType } yyVAL.union = yyLOCAL - case 1060: + case 1062: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL JoinType -//line sql.y:5581 +//line sql.y:5589 { yyLOCAL = NaturalJoinType } yyVAL.union = yyLOCAL - case 1061: + case 1063: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL JoinType -//line sql.y:5585 +//line sql.y:5593 { if yyDollar[2].joinTypeUnion() == LeftJoinType { yyLOCAL = NaturalLeftJoinType @@ -18935,413 +19083,397 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1062: + case 1064: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:5595 +//line sql.y:5603 { yyVAL.tableName = yyDollar[2].tableName } - case 1063: + case 1065: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5599 +//line sql.y:5607 { yyVAL.tableName = yyDollar[1].tableName } - case 1064: + case 1066: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5605 +//line sql.y:5613 { yyVAL.tableName = TableName{Name: yyDollar[1].identifierCS} } - case 1065: + case 1067: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5609 +//line sql.y:5617 { yyVAL.tableName = TableName{Qualifier: yyDollar[1].identifierCS, Name: yyDollar[3].identifierCS} } - case 1066: + case 1068: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5615 +//line sql.y:5623 { yyVAL.tableName = TableName{Name: yyDollar[1].identifierCS} } - case 1067: + case 1069: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL IndexHints -//line sql.y:5620 +//line sql.y:5628 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1068: + case 1070: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IndexHints -//line sql.y:5624 +//line sql.y:5632 { yyLOCAL = yyDollar[1].indexHintsUnion() } yyVAL.union = yyLOCAL - case 1069: + case 1071: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IndexHints -//line sql.y:5630 +//line sql.y:5638 { yyLOCAL = IndexHints{yyDollar[1].indexHintUnion()} } yyVAL.union = yyLOCAL - case 1070: + case 1072: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:5634 +//line sql.y:5642 { yySLICE := (*IndexHints)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[2].indexHintUnion()) } - case 1071: + case 1073: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *IndexHint -//line sql.y:5640 +//line sql.y:5648 { yyLOCAL = &IndexHint{Type: UseOp, ForType: yyDollar[3].indexHintForTypeUnion(), Indexes: yyDollar[5].columnsUnion()} } yyVAL.union = yyLOCAL - case 1072: + case 1074: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *IndexHint -//line sql.y:5644 +//line sql.y:5652 { yyLOCAL = &IndexHint{Type: UseOp, ForType: yyDollar[3].indexHintForTypeUnion()} } yyVAL.union = yyLOCAL - case 1073: + case 1075: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *IndexHint -//line sql.y:5648 +//line sql.y:5656 { yyLOCAL = &IndexHint{Type: IgnoreOp, ForType: yyDollar[3].indexHintForTypeUnion(), Indexes: yyDollar[5].columnsUnion()} } yyVAL.union = yyLOCAL - case 1074: + case 1076: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *IndexHint -//line sql.y:5652 +//line sql.y:5660 { yyLOCAL = &IndexHint{Type: ForceOp, ForType: yyDollar[3].indexHintForTypeUnion(), Indexes: yyDollar[5].columnsUnion()} } yyVAL.union = yyLOCAL - case 1075: + case 1077: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *IndexHint -//line sql.y:5656 +//line sql.y:5664 { yyLOCAL = &IndexHint{Type: UseVindexOp, Indexes: yyDollar[4].columnsUnion()} } yyVAL.union = yyLOCAL - case 1076: + case 1078: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *IndexHint -//line sql.y:5660 +//line sql.y:5668 { yyLOCAL = &IndexHint{Type: IgnoreVindexOp, Indexes: yyDollar[4].columnsUnion()} } yyVAL.union = yyLOCAL - case 1077: + case 1079: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL IndexHintForType -//line sql.y:5665 +//line sql.y:5673 { yyLOCAL = NoForType } yyVAL.union = yyLOCAL - case 1078: + case 1080: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL IndexHintForType -//line sql.y:5669 +//line sql.y:5677 { yyLOCAL = JoinForType } yyVAL.union = yyLOCAL - case 1079: + case 1081: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL IndexHintForType -//line sql.y:5673 +//line sql.y:5681 { yyLOCAL = OrderByForType } yyVAL.union = yyLOCAL - case 1080: + case 1082: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL IndexHintForType -//line sql.y:5677 +//line sql.y:5685 { yyLOCAL = GroupByForType } yyVAL.union = yyLOCAL - case 1081: + case 1083: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Expr -//line sql.y:5683 +//line sql.y:5691 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1082: + case 1084: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5687 +//line sql.y:5695 { yyLOCAL = yyDollar[2].exprUnion() } yyVAL.union = yyLOCAL - case 1083: + case 1085: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5694 +//line sql.y:5702 { yyLOCAL = &OrExpr{Left: yyDollar[1].exprUnion(), Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1084: + case 1086: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5698 +//line sql.y:5706 { yyLOCAL = &XorExpr{Left: yyDollar[1].exprUnion(), Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1085: + case 1087: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5702 +//line sql.y:5710 { yyLOCAL = &AndExpr{Left: yyDollar[1].exprUnion(), Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1086: + case 1088: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5706 +//line sql.y:5714 { yyLOCAL = &NotExpr{Expr: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 1087: + case 1089: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5710 +//line sql.y:5718 { yyLOCAL = &IsExpr{Left: yyDollar[1].exprUnion(), Right: yyDollar[3].isExprOperatorUnion()} } yyVAL.union = yyLOCAL - case 1088: + case 1090: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5714 +//line sql.y:5722 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1089: + case 1091: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5718 +//line sql.y:5726 { yyLOCAL = &AssignmentExpr{Left: yyDollar[1].variableUnion(), Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1090: + case 1092: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5722 +//line sql.y:5730 { yyLOCAL = &MemberOfExpr{Value: yyDollar[1].exprUnion(), JSONArr: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1091: + case 1093: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5728 +//line sql.y:5736 { } - case 1092: + case 1094: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5731 +//line sql.y:5739 { } - case 1093: + case 1095: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5736 +//line sql.y:5744 { yyLOCAL = &IsExpr{Left: yyDollar[1].exprUnion(), Right: IsNullOp} } yyVAL.union = yyLOCAL - case 1094: + case 1096: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5740 +//line sql.y:5748 { yyLOCAL = &IsExpr{Left: yyDollar[1].exprUnion(), Right: IsNotNullOp} } yyVAL.union = yyLOCAL - case 1095: + case 1097: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5744 +//line sql.y:5752 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: yyDollar[2].comparisonExprOperatorUnion(), Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1096: + case 1098: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5748 +//line sql.y:5756 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: yyDollar[2].comparisonExprOperatorUnion(), Modifier: Any, Right: yyDollar[4].subqueryUnion()} } yyVAL.union = yyLOCAL - case 1097: + case 1099: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5752 +//line sql.y:5760 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: yyDollar[2].comparisonExprOperatorUnion(), Modifier: Any, Right: yyDollar[4].subqueryUnion()} } yyVAL.union = yyLOCAL - case 1098: + case 1100: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5756 +//line sql.y:5764 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: yyDollar[2].comparisonExprOperatorUnion(), Modifier: All, Right: yyDollar[4].subqueryUnion()} } yyVAL.union = yyLOCAL - case 1099: + case 1101: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5760 +//line sql.y:5768 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1100: + case 1102: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5766 +//line sql.y:5774 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: InOp, Right: yyDollar[3].colTupleUnion()} } yyVAL.union = yyLOCAL - case 1101: + case 1103: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5770 +//line sql.y:5778 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: NotInOp, Right: yyDollar[4].colTupleUnion()} } yyVAL.union = yyLOCAL - case 1102: + case 1104: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:5774 +//line sql.y:5782 { yyLOCAL = &BetweenExpr{Left: yyDollar[1].exprUnion(), IsBetween: true, From: yyDollar[3].exprUnion(), To: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1103: + case 1105: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5778 +//line sql.y:5786 { yyLOCAL = &BetweenExpr{Left: yyDollar[1].exprUnion(), IsBetween: false, From: yyDollar[4].exprUnion(), To: yyDollar[6].exprUnion()} } yyVAL.union = yyLOCAL - case 1104: + case 1106: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5782 +//line sql.y:5790 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: LikeOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1105: + case 1107: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5786 +//line sql.y:5794 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: NotLikeOp, Right: yyDollar[4].exprUnion()} } yyVAL.union = yyLOCAL - case 1106: + case 1108: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:5790 +//line sql.y:5798 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: LikeOp, Right: yyDollar[3].exprUnion(), Escape: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1107: + case 1109: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5794 +//line sql.y:5802 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: NotLikeOp, Right: yyDollar[4].exprUnion(), Escape: yyDollar[6].exprUnion()} } yyVAL.union = yyLOCAL - case 1108: + case 1110: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5798 +//line sql.y:5806 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: RegexpOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1109: + case 1111: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5802 +//line sql.y:5810 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: NotRegexpOp, Right: yyDollar[4].exprUnion()} } yyVAL.union = yyLOCAL - case 1110: + case 1112: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5806 +//line sql.y:5814 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1111: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5812 - { - } - case 1112: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5815 - { - } case 1113: - yyDollar = yyS[yypt-3 : yypt+1] - var yyLOCAL Expr -//line sql.y:5821 + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:5820 { - yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: BitOrOp, Right: yyDollar[3].exprUnion()} } - yyVAL.union = yyLOCAL case 1114: - yyDollar = yyS[yypt-3 : yypt+1] - var yyLOCAL Expr -//line sql.y:5825 + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:5823 { - yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: BitAndOp, Right: yyDollar[3].exprUnion()} } - yyVAL.union = yyLOCAL case 1115: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr //line sql.y:5829 { - yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: ShiftLeftOp, Right: yyDollar[3].exprUnion()} + yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: BitOrOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1116: @@ -19349,7 +19481,7 @@ yydefault: var yyLOCAL Expr //line sql.y:5833 { - yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: ShiftRightOp, Right: yyDollar[3].exprUnion()} + yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: BitAndOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1117: @@ -19357,7 +19489,7 @@ yydefault: var yyLOCAL Expr //line sql.y:5837 { - yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: PlusOp, Right: yyDollar[3].exprUnion()} + yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: ShiftLeftOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1118: @@ -19365,39 +19497,39 @@ yydefault: var yyLOCAL Expr //line sql.y:5841 { - yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: MinusOp, Right: yyDollar[3].exprUnion()} + yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: ShiftRightOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1119: - yyDollar = yyS[yypt-5 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr //line sql.y:5845 { - yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprBinaryAdd, Date: yyDollar[1].exprUnion(), Unit: yyDollar[5].intervalTypeUnion(), Interval: yyDollar[4].exprUnion()} + yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: PlusOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1120: - yyDollar = yyS[yypt-5 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr //line sql.y:5849 { - yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprBinarySub, Date: yyDollar[1].exprUnion(), Unit: yyDollar[5].intervalTypeUnion(), Interval: yyDollar[4].exprUnion()} + yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: MinusOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1121: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr //line sql.y:5853 { - yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: MultOp, Right: yyDollar[3].exprUnion()} + yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprBinaryAdd, Date: yyDollar[1].exprUnion(), Unit: yyDollar[5].intervalTypeUnion(), Interval: yyDollar[4].exprUnion()} } yyVAL.union = yyLOCAL case 1122: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr //line sql.y:5857 { - yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: DivOp, Right: yyDollar[3].exprUnion()} + yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprBinarySub, Date: yyDollar[1].exprUnion(), Unit: yyDollar[5].intervalTypeUnion(), Interval: yyDollar[4].exprUnion()} } yyVAL.union = yyLOCAL case 1123: @@ -19405,7 +19537,7 @@ yydefault: var yyLOCAL Expr //line sql.y:5861 { - yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: ModOp, Right: yyDollar[3].exprUnion()} + yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: MultOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1124: @@ -19413,7 +19545,7 @@ yydefault: var yyLOCAL Expr //line sql.y:5865 { - yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: IntDivOp, Right: yyDollar[3].exprUnion()} + yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: DivOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1125: @@ -19429,29 +19561,29 @@ yydefault: var yyLOCAL Expr //line sql.y:5873 { - yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: BitXorOp, Right: yyDollar[3].exprUnion()} + yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: IntDivOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1127: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr //line sql.y:5877 { - yyLOCAL = yyDollar[1].exprUnion() + yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: ModOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1128: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5883 +//line sql.y:5881 { - yyLOCAL = yyDollar[1].exprUnion() + yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: BitXorOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1129: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5887 +//line sql.y:5885 { yyLOCAL = yyDollar[1].exprUnion() } @@ -19473,11 +19605,11 @@ yydefault: } yyVAL.union = yyLOCAL case 1132: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr //line sql.y:5899 { - yyLOCAL = &CollateExpr{Expr: yyDollar[1].exprUnion(), Collation: yyDollar[3].str} + yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL case 1133: @@ -19489,11 +19621,11 @@ yydefault: } yyVAL.union = yyLOCAL case 1134: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr //line sql.y:5907 { - yyLOCAL = yyDollar[1].exprUnion() + yyLOCAL = &CollateExpr{Expr: yyDollar[1].exprUnion(), Collation: yyDollar[3].str} } yyVAL.union = yyLOCAL case 1135: @@ -19501,23 +19633,23 @@ yydefault: var yyLOCAL Expr //line sql.y:5911 { - yyLOCAL = yyDollar[1].variableUnion() + yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL case 1136: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr //line sql.y:5915 { - yyLOCAL = yyDollar[2].exprUnion() // TODO: do we really want to ignore unary '+' before any kind of literals? + yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL case 1137: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr //line sql.y:5919 { - yyLOCAL = &UnaryExpr{Operator: UMinusOp, Expr: yyDollar[2].exprUnion()} + yyLOCAL = yyDollar[1].variableUnion() } yyVAL.union = yyLOCAL case 1138: @@ -19525,7 +19657,7 @@ yydefault: var yyLOCAL Expr //line sql.y:5923 { - yyLOCAL = &UnaryExpr{Operator: TildaOp, Expr: yyDollar[2].exprUnion()} + yyLOCAL = yyDollar[2].exprUnion() // TODO: do we really want to ignore unary '+' before any kind of literals? } yyVAL.union = yyLOCAL case 1139: @@ -19533,69 +19665,85 @@ yydefault: var yyLOCAL Expr //line sql.y:5927 { - yyLOCAL = &UnaryExpr{Operator: BangOp, Expr: yyDollar[2].exprUnion()} + yyLOCAL = &UnaryExpr{Operator: UMinusOp, Expr: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL case 1140: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr //line sql.y:5931 { - yyLOCAL = yyDollar[1].subqueryUnion() + yyLOCAL = &UnaryExpr{Operator: TildaOp, Expr: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL case 1141: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr //line sql.y:5935 { - yyLOCAL = yyDollar[1].exprUnion() + yyLOCAL = &UnaryExpr{Operator: BangOp, Expr: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL case 1142: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr //line sql.y:5939 { - yyLOCAL = &ExistsExpr{Subquery: yyDollar[2].subqueryUnion()} + yyLOCAL = yyDollar[1].subqueryUnion() } yyVAL.union = yyLOCAL case 1143: - yyDollar = yyS[yypt-7 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr //line sql.y:5943 { - yyLOCAL = &MatchExpr{Columns: yyDollar[2].colNamesUnion(), Expr: yyDollar[5].exprUnion(), Option: yyDollar[6].matchExprOptionUnion()} + yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL case 1144: - yyDollar = yyS[yypt-7 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr //line sql.y:5947 { - yyLOCAL = &CastExpr{Expr: yyDollar[3].exprUnion(), Type: yyDollar[5].convertTypeUnion(), Array: yyDollar[6].booleanUnion()} + yyLOCAL = &ExistsExpr{Subquery: yyDollar[2].subqueryUnion()} } yyVAL.union = yyLOCAL case 1145: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Expr //line sql.y:5951 { - yyLOCAL = &ConvertExpr{Expr: yyDollar[3].exprUnion(), Type: yyDollar[5].convertTypeUnion()} + yyLOCAL = &MatchExpr{Columns: yyDollar[2].colNamesUnion(), Expr: yyDollar[5].exprUnion(), Option: yyDollar[6].matchExprOptionUnion()} } yyVAL.union = yyLOCAL case 1146: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Expr //line sql.y:5955 { - yyLOCAL = &ConvertUsingExpr{Expr: yyDollar[3].exprUnion(), Type: yyDollar[5].str} + yyLOCAL = &CastExpr{Expr: yyDollar[3].exprUnion(), Type: yyDollar[5].convertTypeUnion(), Array: yyDollar[6].booleanUnion()} } yyVAL.union = yyLOCAL case 1147: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:5959 + { + yyLOCAL = &ConvertExpr{Expr: yyDollar[3].exprUnion(), Type: yyDollar[5].convertTypeUnion()} + } + yyVAL.union = yyLOCAL + case 1148: + yyDollar = yyS[yypt-6 : yypt+1] + var yyLOCAL Expr +//line sql.y:5963 + { + yyLOCAL = &ConvertUsingExpr{Expr: yyDollar[3].exprUnion(), Type: yyDollar[5].str} + } + yyVAL.union = yyLOCAL + case 1149: + yyDollar = yyS[yypt-2 : yypt+1] + var yyLOCAL Expr +//line sql.y:5967 { // From: https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#operator_binary // To convert a string expression to a binary string, these constructs are equivalent: @@ -19604,658 +19752,642 @@ yydefault: yyLOCAL = &ConvertExpr{Expr: yyDollar[2].exprUnion(), Type: &ConvertType{Type: yyDollar[1].str}} } yyVAL.union = yyLOCAL - case 1148: + case 1150: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5967 +//line sql.y:5975 { yyLOCAL = &Default{ColName: yyDollar[2].str} } yyVAL.union = yyLOCAL - case 1149: + case 1151: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:5971 +//line sql.y:5979 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprBinaryAddLeft, Date: yyDollar[5].exprUnion(), Unit: yyDollar[3].intervalTypeUnion(), Interval: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 1150: + case 1152: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5975 +//line sql.y:5983 { yyLOCAL = &IntervalFuncExpr{Expr: yyDollar[3].exprUnion(), Exprs: yyDollar[5].exprsUnion()} } yyVAL.union = yyLOCAL - case 1151: + case 1153: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5979 +//line sql.y:5987 { yyLOCAL = &JSONExtractExpr{JSONDoc: yyDollar[1].exprUnion(), PathList: []Expr{yyDollar[3].exprUnion()}} } yyVAL.union = yyLOCAL - case 1152: + case 1154: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5983 +//line sql.y:5991 { yyLOCAL = &JSONUnquoteExpr{JSONValue: &JSONExtractExpr{JSONDoc: yyDollar[1].exprUnion(), PathList: []Expr{yyDollar[3].exprUnion()}}} } yyVAL.union = yyLOCAL - case 1153: + case 1155: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*ColName -//line sql.y:5989 +//line sql.y:5997 { yyLOCAL = yyDollar[1].colNamesUnion() } yyVAL.union = yyLOCAL - case 1154: + case 1156: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*ColName -//line sql.y:5993 +//line sql.y:6001 { yyLOCAL = yyDollar[2].colNamesUnion() } yyVAL.union = yyLOCAL - case 1155: + case 1157: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*ColName -//line sql.y:5999 +//line sql.y:6007 { yyLOCAL = []*ColName{yyDollar[1].colNameUnion()} } yyVAL.union = yyLOCAL - case 1156: + case 1158: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:6003 +//line sql.y:6011 { yySLICE := (*[]*ColName)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].colNameUnion()) } - case 1157: + case 1159: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TrimType -//line sql.y:6009 +//line sql.y:6017 { yyLOCAL = BothTrimType } yyVAL.union = yyLOCAL - case 1158: + case 1160: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TrimType -//line sql.y:6013 +//line sql.y:6021 { yyLOCAL = LeadingTrimType } yyVAL.union = yyLOCAL - case 1159: + case 1161: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TrimType -//line sql.y:6017 +//line sql.y:6025 { yyLOCAL = TrailingTrimType } yyVAL.union = yyLOCAL - case 1160: + case 1162: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL FrameUnitType -//line sql.y:6023 +//line sql.y:6031 { yyLOCAL = FrameRowsType } yyVAL.union = yyLOCAL - case 1161: + case 1163: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL FrameUnitType -//line sql.y:6027 +//line sql.y:6035 { yyLOCAL = FrameRangeType } yyVAL.union = yyLOCAL - case 1162: + case 1164: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ArgumentLessWindowExprType -//line sql.y:6034 +//line sql.y:6042 { yyLOCAL = CumeDistExprType } yyVAL.union = yyLOCAL - case 1163: + case 1165: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ArgumentLessWindowExprType -//line sql.y:6038 +//line sql.y:6046 { yyLOCAL = DenseRankExprType } yyVAL.union = yyLOCAL - case 1164: + case 1166: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ArgumentLessWindowExprType -//line sql.y:6042 +//line sql.y:6050 { yyLOCAL = PercentRankExprType } yyVAL.union = yyLOCAL - case 1165: + case 1167: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ArgumentLessWindowExprType -//line sql.y:6046 +//line sql.y:6054 { yyLOCAL = RankExprType } yyVAL.union = yyLOCAL - case 1166: + case 1168: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ArgumentLessWindowExprType -//line sql.y:6050 +//line sql.y:6058 { yyLOCAL = RowNumberExprType } yyVAL.union = yyLOCAL - case 1167: + case 1169: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *FramePoint -//line sql.y:6056 +//line sql.y:6064 { yyLOCAL = &FramePoint{Type: CurrentRowType} } yyVAL.union = yyLOCAL - case 1168: + case 1170: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *FramePoint -//line sql.y:6060 +//line sql.y:6068 { yyLOCAL = &FramePoint{Type: UnboundedPrecedingType} } yyVAL.union = yyLOCAL - case 1169: + case 1171: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *FramePoint -//line sql.y:6064 +//line sql.y:6072 { yyLOCAL = &FramePoint{Type: UnboundedFollowingType} } yyVAL.union = yyLOCAL - case 1170: + case 1172: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *FramePoint -//line sql.y:6068 +//line sql.y:6076 { yyLOCAL = &FramePoint{Type: ExprPrecedingType, Expr: yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1171: + case 1173: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *FramePoint -//line sql.y:6072 +//line sql.y:6080 { yyLOCAL = &FramePoint{Type: ExprPrecedingType, Expr: yyDollar[2].exprUnion(), Unit: yyDollar[3].intervalTypeUnion()} } yyVAL.union = yyLOCAL - case 1172: + case 1174: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *FramePoint -//line sql.y:6076 +//line sql.y:6084 { yyLOCAL = &FramePoint{Type: ExprFollowingType, Expr: yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1173: + case 1175: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *FramePoint -//line sql.y:6080 +//line sql.y:6088 { yyLOCAL = &FramePoint{Type: ExprFollowingType, Expr: yyDollar[2].exprUnion(), Unit: yyDollar[3].intervalTypeUnion()} } yyVAL.union = yyLOCAL - case 1174: + case 1176: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *FrameClause -//line sql.y:6085 +//line sql.y:6093 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1175: + case 1177: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *FrameClause -//line sql.y:6089 +//line sql.y:6097 { yyLOCAL = yyDollar[1].frameClauseUnion() } yyVAL.union = yyLOCAL - case 1176: + case 1178: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *FrameClause -//line sql.y:6095 +//line sql.y:6103 { yyLOCAL = &FrameClause{Unit: yyDollar[1].frameUnitTypeUnion(), Start: yyDollar[2].framePointUnion()} } yyVAL.union = yyLOCAL - case 1177: + case 1179: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *FrameClause -//line sql.y:6099 +//line sql.y:6107 { yyLOCAL = &FrameClause{Unit: yyDollar[1].frameUnitTypeUnion(), Start: yyDollar[3].framePointUnion(), End: yyDollar[5].framePointUnion()} } yyVAL.union = yyLOCAL - case 1178: + case 1180: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []Expr -//line sql.y:6104 +//line sql.y:6112 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1179: + case 1181: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []Expr -//line sql.y:6108 +//line sql.y:6116 { yyLOCAL = yyDollar[3].exprsUnion() } yyVAL.union = yyLOCAL - case 1180: + case 1182: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:6113 +//line sql.y:6121 { yyVAL.identifierCI = IdentifierCI{} } - case 1181: + case 1183: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:6117 +//line sql.y:6125 { yyVAL.identifierCI = yyDollar[1].identifierCI } - case 1182: + case 1184: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *WindowSpecification -//line sql.y:6123 +//line sql.y:6131 { yyLOCAL = &WindowSpecification{Name: yyDollar[1].identifierCI, PartitionClause: yyDollar[2].exprsUnion(), OrderClause: yyDollar[3].orderByUnion(), FrameClause: yyDollar[4].frameClauseUnion()} } yyVAL.union = yyLOCAL - case 1183: + case 1185: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *OverClause -//line sql.y:6129 +//line sql.y:6137 { yyLOCAL = &OverClause{WindowSpec: yyDollar[3].windowSpecificationUnion()} } yyVAL.union = yyLOCAL - case 1184: + case 1186: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *OverClause -//line sql.y:6133 +//line sql.y:6141 { yyLOCAL = &OverClause{WindowName: yyDollar[2].identifierCI} } yyVAL.union = yyLOCAL - case 1185: + case 1187: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *OverClause -//line sql.y:6139 +//line sql.y:6147 { yyLOCAL = yyDollar[1].overClauseUnion() } yyVAL.union = yyLOCAL - case 1186: + case 1188: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *OverClause -//line sql.y:6143 +//line sql.y:6151 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1187: + case 1189: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *NullTreatmentClause -//line sql.y:6148 +//line sql.y:6156 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1189: + case 1191: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *NullTreatmentClause -//line sql.y:6155 +//line sql.y:6163 { yyLOCAL = &NullTreatmentClause{yyDollar[1].nullTreatmentTypeUnion()} } yyVAL.union = yyLOCAL - case 1190: + case 1192: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL NullTreatmentType -//line sql.y:6161 +//line sql.y:6169 { yyLOCAL = RespectNullsType } yyVAL.union = yyLOCAL - case 1191: + case 1193: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL NullTreatmentType -//line sql.y:6165 +//line sql.y:6173 { yyLOCAL = IgnoreNullsType } yyVAL.union = yyLOCAL - case 1192: + case 1194: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL FirstOrLastValueExprType -//line sql.y:6171 +//line sql.y:6179 { yyLOCAL = FirstValueExprType } yyVAL.union = yyLOCAL - case 1193: + case 1195: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL FirstOrLastValueExprType -//line sql.y:6175 +//line sql.y:6183 { yyLOCAL = LastValueExprType } yyVAL.union = yyLOCAL - case 1194: + case 1196: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL FromFirstLastType -//line sql.y:6181 +//line sql.y:6189 { yyLOCAL = FromFirstType } yyVAL.union = yyLOCAL - case 1195: + case 1197: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL FromFirstLastType -//line sql.y:6185 +//line sql.y:6193 { yyLOCAL = FromLastType } yyVAL.union = yyLOCAL - case 1196: + case 1198: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *FromFirstLastClause -//line sql.y:6190 +//line sql.y:6198 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1198: + case 1200: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *FromFirstLastClause -//line sql.y:6197 +//line sql.y:6205 { yyLOCAL = &FromFirstLastClause{yyDollar[1].fromFirstLastTypeUnion()} } yyVAL.union = yyLOCAL - case 1199: + case 1201: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL LagLeadExprType -//line sql.y:6203 +//line sql.y:6211 { yyLOCAL = LagExprType } yyVAL.union = yyLOCAL - case 1200: + case 1202: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL LagLeadExprType -//line sql.y:6207 +//line sql.y:6215 { yyLOCAL = LeadExprType } yyVAL.union = yyLOCAL - case 1201: + case 1203: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *WindowDefinition -//line sql.y:6213 +//line sql.y:6221 { yyLOCAL = &WindowDefinition{Name: yyDollar[1].identifierCI, WindowSpec: yyDollar[4].windowSpecificationUnion()} } yyVAL.union = yyLOCAL - case 1202: + case 1204: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL WindowDefinitions -//line sql.y:6219 +//line sql.y:6227 { yyLOCAL = WindowDefinitions{yyDollar[1].windowDefinitionUnion()} } yyVAL.union = yyLOCAL - case 1203: + case 1205: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:6223 +//line sql.y:6231 { yySLICE := (*WindowDefinitions)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].windowDefinitionUnion()) } - case 1204: + case 1206: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:6229 +//line sql.y:6237 { yyVAL.str = "" } - case 1205: + case 1207: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:6233 +//line sql.y:6241 { yyVAL.str = string(yyDollar[2].identifierCI.String()) } - case 1206: + case 1208: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL BoolVal -//line sql.y:6239 +//line sql.y:6247 { yyLOCAL = BoolVal(true) } yyVAL.union = yyLOCAL - case 1207: + case 1209: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL BoolVal -//line sql.y:6243 +//line sql.y:6251 { yyLOCAL = BoolVal(false) } yyVAL.union = yyLOCAL - case 1208: + case 1210: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IsExprOperator -//line sql.y:6250 +//line sql.y:6258 { yyLOCAL = IsTrueOp } yyVAL.union = yyLOCAL - case 1209: + case 1211: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL IsExprOperator -//line sql.y:6254 +//line sql.y:6262 { yyLOCAL = IsNotTrueOp } yyVAL.union = yyLOCAL - case 1210: + case 1212: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IsExprOperator -//line sql.y:6258 +//line sql.y:6266 { yyLOCAL = IsFalseOp } yyVAL.union = yyLOCAL - case 1211: + case 1213: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL IsExprOperator -//line sql.y:6262 +//line sql.y:6270 { yyLOCAL = IsNotFalseOp } yyVAL.union = yyLOCAL - case 1212: + case 1214: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:6268 +//line sql.y:6276 { yyLOCAL = yyDollar[1].comparisonExprOperatorUnion() } yyVAL.union = yyLOCAL - case 1213: + case 1215: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:6272 +//line sql.y:6280 { yyLOCAL = NullSafeEqualOp } yyVAL.union = yyLOCAL - case 1214: + case 1216: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:6278 +//line sql.y:6286 { yyLOCAL = EqualOp } yyVAL.union = yyLOCAL - case 1215: + case 1217: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:6282 +//line sql.y:6290 { yyLOCAL = LessThanOp } yyVAL.union = yyLOCAL - case 1216: + case 1218: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:6286 +//line sql.y:6294 { yyLOCAL = GreaterThanOp } yyVAL.union = yyLOCAL - case 1217: + case 1219: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:6290 +//line sql.y:6298 { yyLOCAL = LessEqualOp } yyVAL.union = yyLOCAL - case 1218: + case 1220: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:6294 +//line sql.y:6302 { yyLOCAL = GreaterEqualOp } yyVAL.union = yyLOCAL - case 1219: + case 1221: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:6298 +//line sql.y:6306 { yyLOCAL = NotEqualOp } yyVAL.union = yyLOCAL - case 1220: + case 1222: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColTuple -//line sql.y:6304 +//line sql.y:6312 { yyLOCAL = yyDollar[1].valTupleUnion() } yyVAL.union = yyLOCAL - case 1221: + case 1223: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColTuple -//line sql.y:6308 +//line sql.y:6316 { yyLOCAL = yyDollar[1].subqueryUnion() } yyVAL.union = yyLOCAL - case 1222: + case 1224: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColTuple -//line sql.y:6312 +//line sql.y:6320 { yyLOCAL = ListArg(yyDollar[1].str[2:]) markBindVariable(yylex, yyDollar[1].str[2:]) } yyVAL.union = yyLOCAL - case 1223: + case 1225: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Subquery -//line sql.y:6319 +//line sql.y:6327 { yyLOCAL = &Subquery{yyDollar[1].tableStmtUnion()} } yyVAL.union = yyLOCAL - case 1224: + case 1226: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []Expr -//line sql.y:6325 +//line sql.y:6333 { yyLOCAL = []Expr{yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1225: + case 1227: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:6329 +//line sql.y:6337 { yySLICE := (*[]Expr)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].exprUnion()) } - case 1226: + case 1228: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6339 +//line sql.y:6347 { yyLOCAL = &FuncExpr{Name: yyDollar[1].identifierCI, Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1227: + case 1229: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6343 +//line sql.y:6351 { yyLOCAL = &FuncExpr{Qualifier: yyDollar[1].identifierCS, Name: yyDollar[3].identifierCI, Exprs: yyDollar[5].exprsUnion()} } yyVAL.union = yyLOCAL - case 1228: - yyDollar = yyS[yypt-4 : yypt+1] - var yyLOCAL Expr -//line sql.y:6353 - { - yyLOCAL = &FuncExpr{Name: NewIdentifierCI("left"), Exprs: yyDollar[3].exprsUnion()} - } - yyVAL.union = yyLOCAL - case 1229: - yyDollar = yyS[yypt-4 : yypt+1] - var yyLOCAL Expr -//line sql.y:6357 - { - yyLOCAL = &FuncExpr{Name: NewIdentifierCI("right"), Exprs: yyDollar[3].exprsUnion()} - } - yyVAL.union = yyLOCAL case 1230: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6361 { - yyLOCAL = &SubstrExpr{Name: yyDollar[3].exprUnion(), From: yyDollar[5].exprUnion(), To: yyDollar[7].exprUnion()} + yyLOCAL = &FuncExpr{Name: NewIdentifierCI("left"), Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL case 1231: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6365 { - yyLOCAL = &SubstrExpr{Name: yyDollar[3].exprUnion(), From: yyDollar[5].exprUnion(), To: yyDollar[7].exprUnion()} + yyLOCAL = &FuncExpr{Name: NewIdentifierCI("right"), Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL case 1232: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6369 { - yyLOCAL = &SubstrExpr{Name: yyDollar[3].exprUnion(), From: yyDollar[5].exprUnion()} + yyLOCAL = &SubstrExpr{Name: yyDollar[3].exprUnion(), From: yyDollar[5].exprUnion(), To: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1233: @@ -20275,67 +20407,67 @@ yydefault: } yyVAL.union = yyLOCAL case 1235: - yyDollar = yyS[yypt-5 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6381 { - yyLOCAL = &CaseExpr{Expr: yyDollar[2].exprUnion(), Whens: yyDollar[3].whensUnion(), Else: yyDollar[4].exprUnion()} + yyLOCAL = &SubstrExpr{Name: yyDollar[3].exprUnion(), From: yyDollar[5].exprUnion(), To: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1236: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6385 { - yyLOCAL = &ValuesFuncExpr{Name: yyDollar[3].colNameUnion()} + yyLOCAL = &SubstrExpr{Name: yyDollar[3].exprUnion(), From: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1237: - yyDollar = yyS[yypt-10 : yypt+1] + yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr //line sql.y:6389 { - yyLOCAL = &InsertExpr{Str: yyDollar[3].exprUnion(), Pos: yyDollar[5].exprUnion(), Len: yyDollar[7].exprUnion(), NewStr: yyDollar[9].exprUnion()} + yyLOCAL = &CaseExpr{Expr: yyDollar[2].exprUnion(), Whens: yyDollar[3].whensUnion(), Else: yyDollar[4].exprUnion()} } yyVAL.union = yyLOCAL case 1238: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6393 { - yyLOCAL = &FuncExpr{Name: NewIdentifierCI(yyDollar[1].str)} + yyLOCAL = &ValuesFuncExpr{Name: yyDollar[3].colNameUnion()} } yyVAL.union = yyLOCAL case 1239: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL Expr -//line sql.y:6404 +//line sql.y:6397 { - yyLOCAL = &FuncExpr{Name: NewIdentifierCI("utc_date")} + yyLOCAL = &InsertExpr{Str: yyDollar[3].exprUnion(), Pos: yyDollar[5].exprUnion(), Len: yyDollar[7].exprUnion(), NewStr: yyDollar[9].exprUnion()} } yyVAL.union = yyLOCAL case 1240: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:6408 +//line sql.y:6401 { - yyLOCAL = yyDollar[1].exprUnion() + yyLOCAL = &FuncExpr{Name: NewIdentifierCI(yyDollar[1].str)} } yyVAL.union = yyLOCAL case 1241: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:6414 +//line sql.y:6412 { - yyLOCAL = &FuncExpr{Name: NewIdentifierCI("current_date")} + yyLOCAL = &FuncExpr{Name: NewIdentifierCI("utc_date")} } yyVAL.union = yyLOCAL case 1242: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:6418 +//line sql.y:6416 { - yyLOCAL = &FuncExpr{Name: NewIdentifierCI("curdate")} + yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL case 1243: @@ -20343,47 +20475,47 @@ yydefault: var yyLOCAL Expr //line sql.y:6422 { - yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("utc_time"), Fsp: yyDollar[2].integerUnion()} + yyLOCAL = &FuncExpr{Name: NewIdentifierCI("current_date")} } yyVAL.union = yyLOCAL case 1244: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:6427 +//line sql.y:6426 { - yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("curtime"), Fsp: yyDollar[2].integerUnion()} + yyLOCAL = &FuncExpr{Name: NewIdentifierCI("curdate")} } yyVAL.union = yyLOCAL case 1245: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:6432 +//line sql.y:6430 { - yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("current_time"), Fsp: yyDollar[2].integerUnion()} + yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("utc_time"), Fsp: yyDollar[2].integerUnion()} } yyVAL.union = yyLOCAL case 1246: - yyDollar = yyS[yypt-5 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:6436 +//line sql.y:6435 { - yyLOCAL = &CountStar{OverClause: yyDollar[5].overClauseUnion()} + yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("curtime"), Fsp: yyDollar[2].integerUnion()} } yyVAL.union = yyLOCAL case 1247: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr //line sql.y:6440 { - yyLOCAL = &Count{Distinct: yyDollar[3].booleanUnion(), Args: yyDollar[4].exprsUnion(), OverClause: yyDollar[6].overClauseUnion()} + yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("current_time"), Fsp: yyDollar[2].integerUnion()} } yyVAL.union = yyLOCAL case 1248: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr //line sql.y:6444 { - yyLOCAL = &Max{Distinct: yyDollar[3].booleanUnion(), Arg: yyDollar[4].exprUnion(), OverClause: yyDollar[6].overClauseUnion()} + yyLOCAL = &CountStar{OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL case 1249: @@ -20391,7 +20523,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6448 { - yyLOCAL = &Min{Distinct: yyDollar[3].booleanUnion(), Arg: yyDollar[4].exprUnion(), OverClause: yyDollar[6].overClauseUnion()} + yyLOCAL = &Count{Distinct: yyDollar[3].booleanUnion(), Args: yyDollar[4].exprsUnion(), OverClause: yyDollar[6].overClauseUnion()} } yyVAL.union = yyLOCAL case 1250: @@ -20399,7 +20531,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6452 { - yyLOCAL = &Sum{Distinct: yyDollar[3].booleanUnion(), Arg: yyDollar[4].exprUnion(), OverClause: yyDollar[6].overClauseUnion()} + yyLOCAL = &Max{Distinct: yyDollar[3].booleanUnion(), Arg: yyDollar[4].exprUnion(), OverClause: yyDollar[6].overClauseUnion()} } yyVAL.union = yyLOCAL case 1251: @@ -20407,23 +20539,23 @@ yydefault: var yyLOCAL Expr //line sql.y:6456 { - yyLOCAL = &Avg{Distinct: yyDollar[3].booleanUnion(), Arg: yyDollar[4].exprUnion(), OverClause: yyDollar[6].overClauseUnion()} + yyLOCAL = &Min{Distinct: yyDollar[3].booleanUnion(), Arg: yyDollar[4].exprUnion(), OverClause: yyDollar[6].overClauseUnion()} } yyVAL.union = yyLOCAL case 1252: - yyDollar = yyS[yypt-5 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6460 { - yyLOCAL = &BitAnd{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} + yyLOCAL = &Sum{Distinct: yyDollar[3].booleanUnion(), Arg: yyDollar[4].exprUnion(), OverClause: yyDollar[6].overClauseUnion()} } yyVAL.union = yyLOCAL case 1253: - yyDollar = yyS[yypt-5 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6464 { - yyLOCAL = &BitOr{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} + yyLOCAL = &Avg{Distinct: yyDollar[3].booleanUnion(), Arg: yyDollar[4].exprUnion(), OverClause: yyDollar[6].overClauseUnion()} } yyVAL.union = yyLOCAL case 1254: @@ -20431,7 +20563,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6468 { - yyLOCAL = &BitXor{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} + yyLOCAL = &BitAnd{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL case 1255: @@ -20439,7 +20571,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6472 { - yyLOCAL = &Std{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} + yyLOCAL = &BitOr{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL case 1256: @@ -20447,7 +20579,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6476 { - yyLOCAL = &StdDev{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} + yyLOCAL = &BitXor{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL case 1257: @@ -20455,7 +20587,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6480 { - yyLOCAL = &StdPop{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} + yyLOCAL = &Std{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL case 1258: @@ -20463,7 +20595,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6484 { - yyLOCAL = &StdSamp{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} + yyLOCAL = &StdDev{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL case 1259: @@ -20471,7 +20603,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6488 { - yyLOCAL = &VarPop{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} + yyLOCAL = &StdPop{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL case 1260: @@ -20479,7 +20611,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6492 { - yyLOCAL = &VarSamp{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} + yyLOCAL = &StdSamp{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL case 1261: @@ -20487,23 +20619,23 @@ yydefault: var yyLOCAL Expr //line sql.y:6496 { - yyLOCAL = &Variance{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} + yyLOCAL = &VarPop{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL case 1262: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr //line sql.y:6500 { - yyLOCAL = &GroupConcatExpr{Distinct: yyDollar[3].booleanUnion(), Exprs: yyDollar[4].exprsUnion(), OrderBy: yyDollar[5].orderByUnion(), Separator: yyDollar[6].str, Limit: yyDollar[7].limitUnion()} + yyLOCAL = &VarSamp{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL case 1263: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr //line sql.y:6504 { - yyLOCAL = &AnyValue{Arg: yyDollar[3].exprUnion()} + yyLOCAL = &Variance{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL case 1264: @@ -20511,47 +20643,47 @@ yydefault: var yyLOCAL Expr //line sql.y:6508 { - yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprTimestampadd, Date: yyDollar[7].exprUnion(), Interval: yyDollar[5].exprUnion(), Unit: yyDollar[3].intervalTypeUnion()} + yyLOCAL = &GroupConcatExpr{Distinct: yyDollar[3].booleanUnion(), Exprs: yyDollar[4].exprsUnion(), OrderBy: yyDollar[5].orderByUnion(), Separator: yyDollar[6].str, Limit: yyDollar[7].limitUnion()} } yyVAL.union = yyLOCAL case 1265: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6512 { - yyLOCAL = &TimestampDiffExpr{Unit: yyDollar[3].intervalTypeUnion(), Expr1: yyDollar[5].exprUnion(), Expr2: yyDollar[7].exprUnion()} + yyLOCAL = &AnyValue{Arg: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1266: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6516 { - yyLOCAL = &ExtractFuncExpr{IntervalType: yyDollar[3].intervalTypeUnion(), Expr: yyDollar[5].exprUnion()} + yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprTimestampadd, Date: yyDollar[7].exprUnion(), Interval: yyDollar[5].exprUnion(), Unit: yyDollar[3].intervalTypeUnion()} } yyVAL.union = yyLOCAL case 1267: - yyDollar = yyS[yypt-5 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6520 { - yyLOCAL = &WeightStringFuncExpr{Expr: yyDollar[3].exprUnion(), As: yyDollar[4].convertTypeUnion()} + yyLOCAL = &TimestampDiffExpr{Unit: yyDollar[3].intervalTypeUnion(), Expr1: yyDollar[5].exprUnion(), Expr2: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1268: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6524 { - yyLOCAL = &JSONPrettyExpr{JSONVal: yyDollar[3].exprUnion()} + yyLOCAL = &ExtractFuncExpr{IntervalType: yyDollar[3].intervalTypeUnion(), Expr: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1269: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr //line sql.y:6528 { - yyLOCAL = &JSONStorageFreeExpr{JSONVal: yyDollar[3].exprUnion()} + yyLOCAL = &WeightStringFuncExpr{Expr: yyDollar[3].exprUnion(), As: yyDollar[4].convertTypeUnion()} } yyVAL.union = yyLOCAL case 1270: @@ -20559,47 +20691,47 @@ yydefault: var yyLOCAL Expr //line sql.y:6532 { - yyLOCAL = &JSONStorageSizeExpr{JSONVal: yyDollar[3].exprUnion()} + yyLOCAL = &JSONPrettyExpr{JSONVal: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1271: - yyDollar = yyS[yypt-5 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6536 { - yyLOCAL = &JSONArrayAgg{Expr: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} + yyLOCAL = &JSONStorageFreeExpr{JSONVal: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1272: - yyDollar = yyS[yypt-7 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6540 { - yyLOCAL = &JSONObjectAgg{Key: yyDollar[3].exprUnion(), Value: yyDollar[5].exprUnion(), OverClause: yyDollar[7].overClauseUnion()} + yyLOCAL = &JSONStorageSizeExpr{JSONVal: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1273: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr //line sql.y:6544 { - yyLOCAL = &TrimFuncExpr{TrimFuncType: LTrimType, Type: LeadingTrimType, StringArg: yyDollar[3].exprUnion()} + yyLOCAL = &JSONArrayAgg{Expr: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL case 1274: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Expr //line sql.y:6548 { - yyLOCAL = &TrimFuncExpr{TrimFuncType: RTrimType, Type: TrailingTrimType, StringArg: yyDollar[3].exprUnion()} + yyLOCAL = &JSONObjectAgg{Key: yyDollar[3].exprUnion(), Value: yyDollar[5].exprUnion(), OverClause: yyDollar[7].overClauseUnion()} } yyVAL.union = yyLOCAL case 1275: - yyDollar = yyS[yypt-7 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6552 { - yyLOCAL = &TrimFuncExpr{Type: yyDollar[3].trimTypeUnion(), TrimArg: yyDollar[4].exprUnion(), StringArg: yyDollar[6].exprUnion()} + yyLOCAL = &TrimFuncExpr{TrimFuncType: LTrimType, Type: LeadingTrimType, StringArg: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1276: @@ -20607,31 +20739,31 @@ yydefault: var yyLOCAL Expr //line sql.y:6556 { - yyLOCAL = &TrimFuncExpr{StringArg: yyDollar[3].exprUnion()} + yyLOCAL = &TrimFuncExpr{TrimFuncType: RTrimType, Type: TrailingTrimType, StringArg: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1277: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Expr //line sql.y:6560 { - yyLOCAL = &CharExpr{Exprs: yyDollar[3].exprsUnion()} + yyLOCAL = &TrimFuncExpr{Type: yyDollar[3].trimTypeUnion(), TrimArg: yyDollar[4].exprUnion(), StringArg: yyDollar[6].exprUnion()} } yyVAL.union = yyLOCAL case 1278: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6564 { - yyLOCAL = &CharExpr{Exprs: yyDollar[3].exprsUnion(), Charset: yyDollar[5].str} + yyLOCAL = &TrimFuncExpr{StringArg: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1279: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6568 { - yyLOCAL = &TrimFuncExpr{TrimArg: yyDollar[3].exprUnion(), StringArg: yyDollar[5].exprUnion()} + yyLOCAL = &CharExpr{Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL case 1280: @@ -20639,15 +20771,15 @@ yydefault: var yyLOCAL Expr //line sql.y:6572 { - yyLOCAL = &LocateExpr{SubStr: yyDollar[3].exprUnion(), Str: yyDollar[5].exprUnion()} + yyLOCAL = &CharExpr{Exprs: yyDollar[3].exprsUnion(), Charset: yyDollar[5].str} } yyVAL.union = yyLOCAL case 1281: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6576 { - yyLOCAL = &LocateExpr{SubStr: yyDollar[3].exprUnion(), Str: yyDollar[5].exprUnion(), Pos: yyDollar[7].exprUnion()} + yyLOCAL = &TrimFuncExpr{TrimArg: yyDollar[3].exprUnion(), StringArg: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1282: @@ -20659,35 +20791,35 @@ yydefault: } yyVAL.union = yyLOCAL case 1283: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6584 { - yyLOCAL = &LockingFunc{Type: GetLock, Name: yyDollar[3].exprUnion(), Timeout: yyDollar[5].exprUnion()} + yyLOCAL = &LocateExpr{SubStr: yyDollar[3].exprUnion(), Str: yyDollar[5].exprUnion(), Pos: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1284: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6588 { - yyLOCAL = &LockingFunc{Type: IsFreeLock, Name: yyDollar[3].exprUnion()} + yyLOCAL = &LocateExpr{SubStr: yyDollar[3].exprUnion(), Str: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1285: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6592 { - yyLOCAL = &LockingFunc{Type: IsUsedLock, Name: yyDollar[3].exprUnion()} + yyLOCAL = &LockingFunc{Type: GetLock, Name: yyDollar[3].exprUnion(), Timeout: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1286: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6596 { - yyLOCAL = &LockingFunc{Type: ReleaseAllLocks} + yyLOCAL = &LockingFunc{Type: IsFreeLock, Name: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1287: @@ -20695,47 +20827,47 @@ yydefault: var yyLOCAL Expr //line sql.y:6600 { - yyLOCAL = &LockingFunc{Type: ReleaseLock, Name: yyDollar[3].exprUnion()} + yyLOCAL = &LockingFunc{Type: IsUsedLock, Name: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1288: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr //line sql.y:6604 { - yyLOCAL = &JSONSchemaValidFuncExpr{Schema: yyDollar[3].exprUnion(), Document: yyDollar[5].exprUnion()} + yyLOCAL = &LockingFunc{Type: ReleaseAllLocks} } yyVAL.union = yyLOCAL case 1289: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6608 { - yyLOCAL = &JSONSchemaValidationReportFuncExpr{Schema: yyDollar[3].exprUnion(), Document: yyDollar[5].exprUnion()} + yyLOCAL = &LockingFunc{Type: ReleaseLock, Name: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1290: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6612 { - yyLOCAL = &JSONArrayExpr{Params: yyDollar[3].exprsUnion()} + yyLOCAL = &JSONSchemaValidFuncExpr{Schema: yyDollar[3].exprUnion(), Document: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1291: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6616 { - yyLOCAL = &GeomFormatExpr{FormatType: BinaryFormat, Geom: yyDollar[3].exprUnion()} + yyLOCAL = &JSONSchemaValidationReportFuncExpr{Schema: yyDollar[3].exprUnion(), Document: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1292: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6620 { - yyLOCAL = &GeomFormatExpr{FormatType: BinaryFormat, Geom: yyDollar[3].exprUnion(), AxisOrderOpt: yyDollar[5].exprUnion()} + yyLOCAL = &JSONArrayExpr{Params: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL case 1293: @@ -20743,7 +20875,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6624 { - yyLOCAL = &GeomFormatExpr{FormatType: TextFormat, Geom: yyDollar[3].exprUnion()} + yyLOCAL = &GeomFormatExpr{FormatType: BinaryFormat, Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1294: @@ -20751,7 +20883,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6628 { - yyLOCAL = &GeomFormatExpr{FormatType: TextFormat, Geom: yyDollar[3].exprUnion(), AxisOrderOpt: yyDollar[5].exprUnion()} + yyLOCAL = &GeomFormatExpr{FormatType: BinaryFormat, Geom: yyDollar[3].exprUnion(), AxisOrderOpt: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1295: @@ -20759,15 +20891,15 @@ yydefault: var yyLOCAL Expr //line sql.y:6632 { - yyLOCAL = &GeomPropertyFuncExpr{Property: IsEmpty, Geom: yyDollar[3].exprUnion()} + yyLOCAL = &GeomFormatExpr{FormatType: TextFormat, Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1296: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6636 { - yyLOCAL = &GeomPropertyFuncExpr{Property: IsSimple, Geom: yyDollar[3].exprUnion()} + yyLOCAL = &GeomFormatExpr{FormatType: TextFormat, Geom: yyDollar[3].exprUnion(), AxisOrderOpt: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1297: @@ -20775,7 +20907,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6640 { - yyLOCAL = &GeomPropertyFuncExpr{Property: Dimension, Geom: yyDollar[3].exprUnion()} + yyLOCAL = &GeomPropertyFuncExpr{Property: IsEmpty, Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1298: @@ -20783,7 +20915,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6644 { - yyLOCAL = &GeomPropertyFuncExpr{Property: Envelope, Geom: yyDollar[3].exprUnion()} + yyLOCAL = &GeomPropertyFuncExpr{Property: IsSimple, Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1299: @@ -20791,7 +20923,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6648 { - yyLOCAL = &GeomPropertyFuncExpr{Property: GeometryType, Geom: yyDollar[3].exprUnion()} + yyLOCAL = &GeomPropertyFuncExpr{Property: Dimension, Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1300: @@ -20799,15 +20931,15 @@ yydefault: var yyLOCAL Expr //line sql.y:6652 { - yyLOCAL = &PointPropertyFuncExpr{Property: Latitude, Point: yyDollar[3].exprUnion()} + yyLOCAL = &GeomPropertyFuncExpr{Property: Envelope, Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1301: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6656 { - yyLOCAL = &PointPropertyFuncExpr{Property: Latitude, Point: yyDollar[3].exprUnion(), ValueToSet: yyDollar[5].exprUnion()} + yyLOCAL = &GeomPropertyFuncExpr{Property: GeometryType, Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1302: @@ -20815,7 +20947,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6660 { - yyLOCAL = &PointPropertyFuncExpr{Property: Longitude, Point: yyDollar[3].exprUnion()} + yyLOCAL = &PointPropertyFuncExpr{Property: Latitude, Point: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1303: @@ -20823,7 +20955,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6664 { - yyLOCAL = &PointPropertyFuncExpr{Property: Longitude, Point: yyDollar[3].exprUnion(), ValueToSet: yyDollar[5].exprUnion()} + yyLOCAL = &PointPropertyFuncExpr{Property: Latitude, Point: yyDollar[3].exprUnion(), ValueToSet: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1304: @@ -20831,15 +20963,15 @@ yydefault: var yyLOCAL Expr //line sql.y:6668 { - yyLOCAL = &LinestrPropertyFuncExpr{Property: EndPoint, Linestring: yyDollar[3].exprUnion()} + yyLOCAL = &PointPropertyFuncExpr{Property: Longitude, Point: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1305: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6672 { - yyLOCAL = &LinestrPropertyFuncExpr{Property: IsClosed, Linestring: yyDollar[3].exprUnion()} + yyLOCAL = &PointPropertyFuncExpr{Property: Longitude, Point: yyDollar[3].exprUnion(), ValueToSet: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1306: @@ -20847,15 +20979,15 @@ yydefault: var yyLOCAL Expr //line sql.y:6676 { - yyLOCAL = &LinestrPropertyFuncExpr{Property: Length, Linestring: yyDollar[3].exprUnion()} + yyLOCAL = &LinestrPropertyFuncExpr{Property: EndPoint, Linestring: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1307: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6680 { - yyLOCAL = &LinestrPropertyFuncExpr{Property: Length, Linestring: yyDollar[3].exprUnion(), PropertyDefArg: yyDollar[5].exprUnion()} + yyLOCAL = &LinestrPropertyFuncExpr{Property: IsClosed, Linestring: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1308: @@ -20863,7 +20995,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6684 { - yyLOCAL = &LinestrPropertyFuncExpr{Property: NumPoints, Linestring: yyDollar[3].exprUnion()} + yyLOCAL = &LinestrPropertyFuncExpr{Property: Length, Linestring: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1309: @@ -20871,7 +21003,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6688 { - yyLOCAL = &LinestrPropertyFuncExpr{Property: PointN, Linestring: yyDollar[3].exprUnion(), PropertyDefArg: yyDollar[5].exprUnion()} + yyLOCAL = &LinestrPropertyFuncExpr{Property: Length, Linestring: yyDollar[3].exprUnion(), PropertyDefArg: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1310: @@ -20879,23 +21011,23 @@ yydefault: var yyLOCAL Expr //line sql.y:6692 { - yyLOCAL = &LinestrPropertyFuncExpr{Property: StartPoint, Linestring: yyDollar[3].exprUnion()} + yyLOCAL = &LinestrPropertyFuncExpr{Property: NumPoints, Linestring: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1311: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6696 { - yyLOCAL = &PointPropertyFuncExpr{Property: XCordinate, Point: yyDollar[3].exprUnion()} + yyLOCAL = &LinestrPropertyFuncExpr{Property: PointN, Linestring: yyDollar[3].exprUnion(), PropertyDefArg: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1312: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6700 { - yyLOCAL = &PointPropertyFuncExpr{Property: XCordinate, Point: yyDollar[3].exprUnion(), ValueToSet: yyDollar[5].exprUnion()} + yyLOCAL = &LinestrPropertyFuncExpr{Property: StartPoint, Linestring: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1313: @@ -20903,7 +21035,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6704 { - yyLOCAL = &PointPropertyFuncExpr{Property: YCordinate, Point: yyDollar[3].exprUnion()} + yyLOCAL = &PointPropertyFuncExpr{Property: XCordinate, Point: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1314: @@ -20911,7 +21043,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6708 { - yyLOCAL = &PointPropertyFuncExpr{Property: YCordinate, Point: yyDollar[3].exprUnion(), ValueToSet: yyDollar[5].exprUnion()} + yyLOCAL = &PointPropertyFuncExpr{Property: XCordinate, Point: yyDollar[3].exprUnion(), ValueToSet: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1315: @@ -20919,7 +21051,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6712 { - yyLOCAL = &GeomFromTextExpr{Type: GeometryFromText, WktText: yyDollar[3].exprUnion()} + yyLOCAL = &PointPropertyFuncExpr{Property: YCordinate, Point: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1316: @@ -20927,391 +21059,391 @@ yydefault: var yyLOCAL Expr //line sql.y:6716 { - yyLOCAL = &GeomFromTextExpr{Type: GeometryFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} + yyLOCAL = &PointPropertyFuncExpr{Property: YCordinate, Point: yyDollar[3].exprUnion(), ValueToSet: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1317: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6720 { - yyLOCAL = &GeomFromTextExpr{Type: GeometryFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: GeometryFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1318: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6724 { - yyLOCAL = &GeomFromTextExpr{Type: GeometryCollectionFromText, WktText: yyDollar[3].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: GeometryFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1319: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6728 { - yyLOCAL = &GeomFromTextExpr{Type: GeometryCollectionFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: GeometryFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1320: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6732 { - yyLOCAL = &GeomFromTextExpr{Type: GeometryCollectionFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: GeometryCollectionFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1321: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6736 { - yyLOCAL = &GeomFromTextExpr{Type: LineStringFromText, WktText: yyDollar[3].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: GeometryCollectionFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1322: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6740 { - yyLOCAL = &GeomFromTextExpr{Type: LineStringFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: GeometryCollectionFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1323: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6744 { - yyLOCAL = &GeomFromTextExpr{Type: LineStringFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: LineStringFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1324: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6748 { - yyLOCAL = &GeomFromTextExpr{Type: MultiLinestringFromText, WktText: yyDollar[3].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: LineStringFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1325: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6752 { - yyLOCAL = &GeomFromTextExpr{Type: MultiLinestringFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: LineStringFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1326: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6756 { - yyLOCAL = &GeomFromTextExpr{Type: MultiLinestringFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: MultiLinestringFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1327: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6760 { - yyLOCAL = &GeomFromTextExpr{Type: MultiPointFromText, WktText: yyDollar[3].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: MultiLinestringFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1328: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6764 { - yyLOCAL = &GeomFromTextExpr{Type: MultiPointFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: MultiLinestringFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1329: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6768 { - yyLOCAL = &GeomFromTextExpr{Type: MultiPointFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: MultiPointFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1330: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6772 { - yyLOCAL = &GeomFromTextExpr{Type: MultiPolygonFromText, WktText: yyDollar[3].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: MultiPointFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1331: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6776 { - yyLOCAL = &GeomFromTextExpr{Type: MultiPolygonFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: MultiPointFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1332: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6780 { - yyLOCAL = &GeomFromTextExpr{Type: MultiPolygonFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: MultiPolygonFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1333: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6784 { - yyLOCAL = &GeomFromTextExpr{Type: PointFromText, WktText: yyDollar[3].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: MultiPolygonFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1334: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6788 { - yyLOCAL = &GeomFromTextExpr{Type: PointFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: MultiPolygonFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1335: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6792 { - yyLOCAL = &GeomFromTextExpr{Type: PointFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: PointFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1336: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6796 { - yyLOCAL = &GeomFromTextExpr{Type: PolygonFromText, WktText: yyDollar[3].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: PointFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1337: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6800 { - yyLOCAL = &GeomFromTextExpr{Type: PolygonFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: PointFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1338: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6804 { - yyLOCAL = &GeomFromTextExpr{Type: PolygonFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: PolygonFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1339: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6808 { - yyLOCAL = &GeomFromWKBExpr{Type: GeometryFromWKB, WkbBlob: yyDollar[3].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: PolygonFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1340: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6812 { - yyLOCAL = &GeomFromWKBExpr{Type: GeometryFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} + yyLOCAL = &GeomFromTextExpr{Type: PolygonFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1341: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6816 { - yyLOCAL = &GeomFromWKBExpr{Type: GeometryFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: GeometryFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1342: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6820 { - yyLOCAL = &GeomFromWKBExpr{Type: GeometryCollectionFromWKB, WkbBlob: yyDollar[3].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: GeometryFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1343: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6824 { - yyLOCAL = &GeomFromWKBExpr{Type: GeometryCollectionFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: GeometryFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1344: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6828 { - yyLOCAL = &GeomFromWKBExpr{Type: GeometryCollectionFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: GeometryCollectionFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1345: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6832 { - yyLOCAL = &GeomFromWKBExpr{Type: LineStringFromWKB, WkbBlob: yyDollar[3].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: GeometryCollectionFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1346: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6836 { - yyLOCAL = &GeomFromWKBExpr{Type: LineStringFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: GeometryCollectionFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1347: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6840 { - yyLOCAL = &GeomFromWKBExpr{Type: LineStringFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: LineStringFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1348: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6844 { - yyLOCAL = &GeomFromWKBExpr{Type: MultiLinestringFromWKB, WkbBlob: yyDollar[3].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: LineStringFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1349: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6848 { - yyLOCAL = &GeomFromWKBExpr{Type: MultiLinestringFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: LineStringFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1350: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6852 { - yyLOCAL = &GeomFromWKBExpr{Type: MultiLinestringFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: MultiLinestringFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1351: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6856 { - yyLOCAL = &GeomFromWKBExpr{Type: MultiPointFromWKB, WkbBlob: yyDollar[3].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: MultiLinestringFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1352: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6860 { - yyLOCAL = &GeomFromWKBExpr{Type: MultiPointFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: MultiLinestringFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1353: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6864 { - yyLOCAL = &GeomFromWKBExpr{Type: MultiPointFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: MultiPointFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1354: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6868 { - yyLOCAL = &GeomFromWKBExpr{Type: MultiPolygonFromWKB, WkbBlob: yyDollar[3].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: MultiPointFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1355: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6872 { - yyLOCAL = &GeomFromWKBExpr{Type: MultiPolygonFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: MultiPointFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1356: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6876 { - yyLOCAL = &GeomFromWKBExpr{Type: MultiPolygonFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: MultiPolygonFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1357: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6880 { - yyLOCAL = &GeomFromWKBExpr{Type: PointFromWKB, WkbBlob: yyDollar[3].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: MultiPolygonFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1358: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6884 { - yyLOCAL = &GeomFromWKBExpr{Type: PointFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: MultiPolygonFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1359: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6888 { - yyLOCAL = &GeomFromWKBExpr{Type: PointFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: PointFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1360: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6892 { - yyLOCAL = &GeomFromWKBExpr{Type: PolygonFromWKB, WkbBlob: yyDollar[3].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: PointFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1361: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6896 { - yyLOCAL = &GeomFromWKBExpr{Type: PolygonFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: PointFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1362: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6900 { - yyLOCAL = &GeomFromWKBExpr{Type: PolygonFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: PolygonFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1363: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6904 { - yyLOCAL = &PolygonPropertyFuncExpr{Property: Area, Polygon: yyDollar[3].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: PolygonFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1364: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6908 { - yyLOCAL = &PolygonPropertyFuncExpr{Property: Centroid, Polygon: yyDollar[3].exprUnion()} + yyLOCAL = &GeomFromWKBExpr{Type: PolygonFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1365: @@ -21319,15 +21451,15 @@ yydefault: var yyLOCAL Expr //line sql.y:6912 { - yyLOCAL = &PolygonPropertyFuncExpr{Property: ExteriorRing, Polygon: yyDollar[3].exprUnion()} + yyLOCAL = &PolygonPropertyFuncExpr{Property: Area, Polygon: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1366: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6916 { - yyLOCAL = &PolygonPropertyFuncExpr{Property: InteriorRingN, Polygon: yyDollar[3].exprUnion(), PropertyDefArg: yyDollar[5].exprUnion()} + yyLOCAL = &PolygonPropertyFuncExpr{Property: Centroid, Polygon: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1367: @@ -21335,7 +21467,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6920 { - yyLOCAL = &PolygonPropertyFuncExpr{Property: NumInteriorRings, Polygon: yyDollar[3].exprUnion()} + yyLOCAL = &PolygonPropertyFuncExpr{Property: ExteriorRing, Polygon: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1368: @@ -21343,7 +21475,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6924 { - yyLOCAL = &GeomCollPropertyFuncExpr{Property: GeometryN, GeomColl: yyDollar[3].exprUnion(), PropertyDefArg: yyDollar[5].exprUnion()} + yyLOCAL = &PolygonPropertyFuncExpr{Property: InteriorRingN, Polygon: yyDollar[3].exprUnion(), PropertyDefArg: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1369: @@ -21351,47 +21483,47 @@ yydefault: var yyLOCAL Expr //line sql.y:6928 { - yyLOCAL = &GeomCollPropertyFuncExpr{Property: NumGeometries, GeomColl: yyDollar[3].exprUnion()} + yyLOCAL = &PolygonPropertyFuncExpr{Property: NumInteriorRings, Polygon: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1370: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6932 { - yyLOCAL = &GeoHashFromLatLongExpr{Longitude: yyDollar[3].exprUnion(), Latitude: yyDollar[5].exprUnion(), MaxLength: yyDollar[7].exprUnion()} + yyLOCAL = &GeomCollPropertyFuncExpr{Property: GeometryN, GeomColl: yyDollar[3].exprUnion(), PropertyDefArg: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1371: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6936 { - yyLOCAL = &GeoHashFromPointExpr{Point: yyDollar[3].exprUnion(), MaxLength: yyDollar[5].exprUnion()} + yyLOCAL = &GeomCollPropertyFuncExpr{Property: NumGeometries, GeomColl: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1372: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6940 { - yyLOCAL = &GeomFromGeoHashExpr{GeomType: LatitudeFromHash, GeoHash: yyDollar[3].exprUnion()} + yyLOCAL = &GeoHashFromLatLongExpr{Longitude: yyDollar[3].exprUnion(), Latitude: yyDollar[5].exprUnion(), MaxLength: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1373: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6944 { - yyLOCAL = &GeomFromGeoHashExpr{GeomType: LongitudeFromHash, GeoHash: yyDollar[3].exprUnion()} + yyLOCAL = &GeoHashFromPointExpr{Point: yyDollar[3].exprUnion(), MaxLength: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1374: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6948 { - yyLOCAL = &GeomFromGeoHashExpr{GeomType: PointFromHash, GeoHash: yyDollar[3].exprUnion(), SridOpt: yyDollar[5].exprUnion()} + yyLOCAL = &GeomFromGeoHashExpr{GeomType: LatitudeFromHash, GeoHash: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1375: @@ -21399,7 +21531,7 @@ yydefault: var yyLOCAL Expr //line sql.y:6952 { - yyLOCAL = &GeomFromGeoJSONExpr{GeoJSON: yyDollar[3].exprUnion()} + yyLOCAL = &GeomFromGeoHashExpr{GeomType: LongitudeFromHash, GeoHash: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1376: @@ -21407,71 +21539,71 @@ yydefault: var yyLOCAL Expr //line sql.y:6956 { - yyLOCAL = &GeomFromGeoJSONExpr{GeoJSON: yyDollar[3].exprUnion(), HigherDimHandlerOpt: yyDollar[5].exprUnion()} + yyLOCAL = &GeomFromGeoHashExpr{GeomType: PointFromHash, GeoHash: yyDollar[3].exprUnion(), SridOpt: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1377: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6960 { - yyLOCAL = &GeomFromGeoJSONExpr{GeoJSON: yyDollar[3].exprUnion(), HigherDimHandlerOpt: yyDollar[5].exprUnion(), Srid: yyDollar[7].exprUnion()} + yyLOCAL = &GeomFromGeoJSONExpr{GeoJSON: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1378: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6964 { - yyLOCAL = &GeoJSONFromGeomExpr{Geom: yyDollar[3].exprUnion()} + yyLOCAL = &GeomFromGeoJSONExpr{GeoJSON: yyDollar[3].exprUnion(), HigherDimHandlerOpt: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1379: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6968 { - yyLOCAL = &GeoJSONFromGeomExpr{Geom: yyDollar[3].exprUnion(), MaxDecimalDigits: yyDollar[5].exprUnion()} + yyLOCAL = &GeomFromGeoJSONExpr{GeoJSON: yyDollar[3].exprUnion(), HigherDimHandlerOpt: yyDollar[5].exprUnion(), Srid: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1380: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6972 { - yyLOCAL = &GeoJSONFromGeomExpr{Geom: yyDollar[3].exprUnion(), MaxDecimalDigits: yyDollar[5].exprUnion(), Bitmask: yyDollar[7].exprUnion()} + yyLOCAL = &GeoJSONFromGeomExpr{Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1381: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:6976 { - yyLOCAL = &JSONObjectExpr{Params: yyDollar[3].jsonObjectParamsUnion()} + yyLOCAL = &GeoJSONFromGeomExpr{Geom: yyDollar[3].exprUnion(), MaxDecimalDigits: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1382: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6980 { - yyLOCAL = &JSONQuoteExpr{StringArg: yyDollar[3].exprUnion()} + yyLOCAL = &GeoJSONFromGeomExpr{Geom: yyDollar[3].exprUnion(), MaxDecimalDigits: yyDollar[5].exprUnion(), Bitmask: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1383: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6984 { - yyLOCAL = &JSONContainsExpr{Target: yyDollar[3].exprUnion(), Candidate: yyDollar[5].exprsUnion()[0], PathList: yyDollar[5].exprsUnion()[1:]} + yyLOCAL = &JSONObjectExpr{Params: yyDollar[3].jsonObjectParamsUnion()} } yyVAL.union = yyLOCAL case 1384: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:6988 { - yyLOCAL = &JSONContainsPathExpr{JSONDoc: yyDollar[3].exprUnion(), OneOrAll: yyDollar[5].exprUnion(), PathList: yyDollar[7].exprsUnion()} + yyLOCAL = &JSONQuoteExpr{StringArg: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1385: @@ -21479,15 +21611,15 @@ yydefault: var yyLOCAL Expr //line sql.y:6992 { - yyLOCAL = &JSONExtractExpr{JSONDoc: yyDollar[3].exprUnion(), PathList: yyDollar[5].exprsUnion()} + yyLOCAL = &JSONContainsExpr{Target: yyDollar[3].exprUnion(), Candidate: yyDollar[5].exprsUnion()[0], PathList: yyDollar[5].exprsUnion()[1:]} } yyVAL.union = yyLOCAL case 1386: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:6996 { - yyLOCAL = &JSONKeysExpr{JSONDoc: yyDollar[3].exprUnion()} + yyLOCAL = &JSONContainsPathExpr{JSONDoc: yyDollar[3].exprUnion(), OneOrAll: yyDollar[5].exprUnion(), PathList: yyDollar[7].exprsUnion()} } yyVAL.union = yyLOCAL case 1387: @@ -21495,79 +21627,79 @@ yydefault: var yyLOCAL Expr //line sql.y:7000 { - yyLOCAL = &JSONKeysExpr{JSONDoc: yyDollar[3].exprUnion(), Path: yyDollar[5].exprUnion()} + yyLOCAL = &JSONExtractExpr{JSONDoc: yyDollar[3].exprUnion(), PathList: yyDollar[5].exprsUnion()} } yyVAL.union = yyLOCAL case 1388: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:7004 { - yyLOCAL = &JSONOverlapsExpr{JSONDoc1: yyDollar[3].exprUnion(), JSONDoc2: yyDollar[5].exprUnion()} + yyLOCAL = &JSONKeysExpr{JSONDoc: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1389: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:7008 { - yyLOCAL = &JSONSearchExpr{JSONDoc: yyDollar[3].exprUnion(), OneOrAll: yyDollar[5].exprUnion(), SearchStr: yyDollar[7].exprUnion()} + yyLOCAL = &JSONKeysExpr{JSONDoc: yyDollar[3].exprUnion(), Path: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1390: - yyDollar = yyS[yypt-10 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:7012 { - yyLOCAL = &JSONSearchExpr{JSONDoc: yyDollar[3].exprUnion(), OneOrAll: yyDollar[5].exprUnion(), SearchStr: yyDollar[7].exprUnion(), EscapeChar: yyDollar[9].exprsUnion()[0], PathList: yyDollar[9].exprsUnion()[1:]} + yyLOCAL = &JSONOverlapsExpr{JSONDoc1: yyDollar[3].exprUnion(), JSONDoc2: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1391: - yyDollar = yyS[yypt-7 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:7016 { - yyLOCAL = &JSONValueExpr{JSONDoc: yyDollar[3].exprUnion(), Path: yyDollar[5].exprUnion(), ReturningType: yyDollar[6].convertTypeUnion()} + yyLOCAL = &JSONSearchExpr{JSONDoc: yyDollar[3].exprUnion(), OneOrAll: yyDollar[5].exprUnion(), SearchStr: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL case 1392: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL Expr //line sql.y:7020 { - yyLOCAL = &JSONValueExpr{JSONDoc: yyDollar[3].exprUnion(), Path: yyDollar[5].exprUnion(), ReturningType: yyDollar[6].convertTypeUnion(), EmptyOnResponse: yyDollar[7].jtOnResponseUnion()} + yyLOCAL = &JSONSearchExpr{JSONDoc: yyDollar[3].exprUnion(), OneOrAll: yyDollar[5].exprUnion(), SearchStr: yyDollar[7].exprUnion(), EscapeChar: yyDollar[9].exprsUnion()[0], PathList: yyDollar[9].exprsUnion()[1:]} } yyVAL.union = yyLOCAL case 1393: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Expr //line sql.y:7024 { - yyLOCAL = &JSONValueExpr{JSONDoc: yyDollar[3].exprUnion(), Path: yyDollar[5].exprUnion(), ReturningType: yyDollar[6].convertTypeUnion(), ErrorOnResponse: yyDollar[7].jtOnResponseUnion()} + yyLOCAL = &JSONValueExpr{JSONDoc: yyDollar[3].exprUnion(), Path: yyDollar[5].exprUnion(), ReturningType: yyDollar[6].convertTypeUnion()} } yyVAL.union = yyLOCAL case 1394: - yyDollar = yyS[yypt-9 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:7028 { - yyLOCAL = &JSONValueExpr{JSONDoc: yyDollar[3].exprUnion(), Path: yyDollar[5].exprUnion(), ReturningType: yyDollar[6].convertTypeUnion(), EmptyOnResponse: yyDollar[7].jtOnResponseUnion(), ErrorOnResponse: yyDollar[8].jtOnResponseUnion()} + yyLOCAL = &JSONValueExpr{JSONDoc: yyDollar[3].exprUnion(), Path: yyDollar[5].exprUnion(), ReturningType: yyDollar[6].convertTypeUnion(), EmptyOnResponse: yyDollar[7].jtOnResponseUnion()} } yyVAL.union = yyLOCAL case 1395: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr //line sql.y:7032 { - yyLOCAL = &JSONAttributesExpr{Type: DepthAttributeType, JSONDoc: yyDollar[3].exprUnion()} + yyLOCAL = &JSONValueExpr{JSONDoc: yyDollar[3].exprUnion(), Path: yyDollar[5].exprUnion(), ReturningType: yyDollar[6].convertTypeUnion(), ErrorOnResponse: yyDollar[7].jtOnResponseUnion()} } yyVAL.union = yyLOCAL case 1396: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL Expr //line sql.y:7036 { - yyLOCAL = &JSONAttributesExpr{Type: ValidAttributeType, JSONDoc: yyDollar[3].exprUnion()} + yyLOCAL = &JSONValueExpr{JSONDoc: yyDollar[3].exprUnion(), Path: yyDollar[5].exprUnion(), ReturningType: yyDollar[6].convertTypeUnion(), EmptyOnResponse: yyDollar[7].jtOnResponseUnion(), ErrorOnResponse: yyDollar[8].jtOnResponseUnion()} } yyVAL.union = yyLOCAL case 1397: @@ -21575,7 +21707,7 @@ yydefault: var yyLOCAL Expr //line sql.y:7040 { - yyLOCAL = &JSONAttributesExpr{Type: TypeAttributeType, JSONDoc: yyDollar[3].exprUnion()} + yyLOCAL = &JSONAttributesExpr{Type: DepthAttributeType, JSONDoc: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1398: @@ -21583,23 +21715,23 @@ yydefault: var yyLOCAL Expr //line sql.y:7044 { - yyLOCAL = &JSONAttributesExpr{Type: LengthAttributeType, JSONDoc: yyDollar[3].exprUnion()} + yyLOCAL = &JSONAttributesExpr{Type: ValidAttributeType, JSONDoc: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1399: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:7048 { - yyLOCAL = &JSONAttributesExpr{Type: LengthAttributeType, JSONDoc: yyDollar[3].exprUnion(), Path: yyDollar[5].exprUnion()} + yyLOCAL = &JSONAttributesExpr{Type: TypeAttributeType, JSONDoc: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1400: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:7052 { - yyLOCAL = &JSONValueModifierExpr{Type: JSONArrayAppendType, JSONDoc: yyDollar[3].exprUnion(), Params: yyDollar[5].jsonObjectParamsUnion()} + yyLOCAL = &JSONAttributesExpr{Type: LengthAttributeType, JSONDoc: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1401: @@ -21607,7 +21739,7 @@ yydefault: var yyLOCAL Expr //line sql.y:7056 { - yyLOCAL = &JSONValueModifierExpr{Type: JSONArrayInsertType, JSONDoc: yyDollar[3].exprUnion(), Params: yyDollar[5].jsonObjectParamsUnion()} + yyLOCAL = &JSONAttributesExpr{Type: LengthAttributeType, JSONDoc: yyDollar[3].exprUnion(), Path: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1402: @@ -21615,7 +21747,7 @@ yydefault: var yyLOCAL Expr //line sql.y:7060 { - yyLOCAL = &JSONValueModifierExpr{Type: JSONInsertType, JSONDoc: yyDollar[3].exprUnion(), Params: yyDollar[5].jsonObjectParamsUnion()} + yyLOCAL = &JSONValueModifierExpr{Type: JSONArrayAppendType, JSONDoc: yyDollar[3].exprUnion(), Params: yyDollar[5].jsonObjectParamsUnion()} } yyVAL.union = yyLOCAL case 1403: @@ -21623,7 +21755,7 @@ yydefault: var yyLOCAL Expr //line sql.y:7064 { - yyLOCAL = &JSONValueModifierExpr{Type: JSONReplaceType, JSONDoc: yyDollar[3].exprUnion(), Params: yyDollar[5].jsonObjectParamsUnion()} + yyLOCAL = &JSONValueModifierExpr{Type: JSONArrayInsertType, JSONDoc: yyDollar[3].exprUnion(), Params: yyDollar[5].jsonObjectParamsUnion()} } yyVAL.union = yyLOCAL case 1404: @@ -21631,7 +21763,7 @@ yydefault: var yyLOCAL Expr //line sql.y:7068 { - yyLOCAL = &JSONValueModifierExpr{Type: JSONSetType, JSONDoc: yyDollar[3].exprUnion(), Params: yyDollar[5].jsonObjectParamsUnion()} + yyLOCAL = &JSONValueModifierExpr{Type: JSONInsertType, JSONDoc: yyDollar[3].exprUnion(), Params: yyDollar[5].jsonObjectParamsUnion()} } yyVAL.union = yyLOCAL case 1405: @@ -21639,7 +21771,7 @@ yydefault: var yyLOCAL Expr //line sql.y:7072 { - yyLOCAL = &JSONValueMergeExpr{Type: JSONMergeType, JSONDoc: yyDollar[3].exprUnion(), JSONDocList: yyDollar[5].exprsUnion()} + yyLOCAL = &JSONValueModifierExpr{Type: JSONReplaceType, JSONDoc: yyDollar[3].exprUnion(), Params: yyDollar[5].jsonObjectParamsUnion()} } yyVAL.union = yyLOCAL case 1406: @@ -21647,7 +21779,7 @@ yydefault: var yyLOCAL Expr //line sql.y:7076 { - yyLOCAL = &JSONValueMergeExpr{Type: JSONMergePatchType, JSONDoc: yyDollar[3].exprUnion(), JSONDocList: yyDollar[5].exprsUnion()} + yyLOCAL = &JSONValueModifierExpr{Type: JSONSetType, JSONDoc: yyDollar[3].exprUnion(), Params: yyDollar[5].jsonObjectParamsUnion()} } yyVAL.union = yyLOCAL case 1407: @@ -21655,7 +21787,7 @@ yydefault: var yyLOCAL Expr //line sql.y:7080 { - yyLOCAL = &JSONValueMergeExpr{Type: JSONMergePreserveType, JSONDoc: yyDollar[3].exprUnion(), JSONDocList: yyDollar[5].exprsUnion()} + yyLOCAL = &JSONValueMergeExpr{Type: JSONMergeType, JSONDoc: yyDollar[3].exprUnion(), JSONDocList: yyDollar[5].exprsUnion()} } yyVAL.union = yyLOCAL case 1408: @@ -21663,23 +21795,23 @@ yydefault: var yyLOCAL Expr //line sql.y:7084 { - yyLOCAL = &JSONRemoveExpr{JSONDoc: yyDollar[3].exprUnion(), PathList: yyDollar[5].exprsUnion()} + yyLOCAL = &JSONValueMergeExpr{Type: JSONMergePatchType, JSONDoc: yyDollar[3].exprUnion(), JSONDocList: yyDollar[5].exprsUnion()} } yyVAL.union = yyLOCAL case 1409: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:7088 { - yyLOCAL = &JSONUnquoteExpr{JSONValue: yyDollar[3].exprUnion()} + yyLOCAL = &JSONValueMergeExpr{Type: JSONMergePreserveType, JSONDoc: yyDollar[3].exprUnion(), JSONDocList: yyDollar[5].exprsUnion()} } yyVAL.union = yyLOCAL case 1410: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:7092 { - yyLOCAL = &MultiPolygonExpr{PolygonParams: yyDollar[3].exprsUnion()} + yyLOCAL = &JSONRemoveExpr{JSONDoc: yyDollar[3].exprUnion(), PathList: yyDollar[5].exprsUnion()} } yyVAL.union = yyLOCAL case 1411: @@ -21687,7 +21819,7 @@ yydefault: var yyLOCAL Expr //line sql.y:7096 { - yyLOCAL = &MultiPointExpr{PointParams: yyDollar[3].exprsUnion()} + yyLOCAL = &JSONUnquoteExpr{JSONValue: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL case 1412: @@ -21695,7 +21827,7 @@ yydefault: var yyLOCAL Expr //line sql.y:7100 { - yyLOCAL = &MultiLinestringExpr{LinestringParams: yyDollar[3].exprsUnion()} + yyLOCAL = &MultiPolygonExpr{PolygonParams: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL case 1413: @@ -21703,7 +21835,7 @@ yydefault: var yyLOCAL Expr //line sql.y:7104 { - yyLOCAL = &PolygonExpr{LinestringParams: yyDollar[3].exprsUnion()} + yyLOCAL = &MultiPointExpr{PointParams: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL case 1414: @@ -21711,15 +21843,15 @@ yydefault: var yyLOCAL Expr //line sql.y:7108 { - yyLOCAL = &LineStringExpr{PointParams: yyDollar[3].exprsUnion()} + yyLOCAL = &MultiLinestringExpr{LinestringParams: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL case 1415: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:7112 { - yyLOCAL = &PointExpr{XCordinate: yyDollar[3].exprUnion(), YCordinate: yyDollar[5].exprUnion()} + yyLOCAL = &PolygonExpr{LinestringParams: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL case 1416: @@ -21727,7 +21859,7 @@ yydefault: var yyLOCAL Expr //line sql.y:7116 { - yyLOCAL = &ArgumentLessWindowExpr{Type: yyDollar[1].argumentLessWindowExprTypeUnion(), OverClause: yyDollar[4].overClauseUnion()} + yyLOCAL = &LineStringExpr{PointParams: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL case 1417: @@ -21735,31 +21867,31 @@ yydefault: var yyLOCAL Expr //line sql.y:7120 { - yyLOCAL = &FirstOrLastValueExpr{Type: yyDollar[1].firstOrLastValueExprTypeUnion(), Expr: yyDollar[3].exprUnion(), NullTreatmentClause: yyDollar[5].nullTreatmentClauseUnion(), OverClause: yyDollar[6].overClauseUnion()} + yyLOCAL = &PointExpr{XCordinate: yyDollar[3].exprUnion(), YCordinate: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL case 1418: - yyDollar = yyS[yypt-5 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr //line sql.y:7124 { - yyLOCAL = &NtileExpr{N: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} + yyLOCAL = &ArgumentLessWindowExpr{Type: yyDollar[1].argumentLessWindowExprTypeUnion(), OverClause: yyDollar[4].overClauseUnion()} } yyVAL.union = yyLOCAL case 1419: - yyDollar = yyS[yypt-9 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:7128 { - yyLOCAL = &NTHValueExpr{Expr: yyDollar[3].exprUnion(), N: yyDollar[5].exprUnion(), FromFirstLastClause: yyDollar[7].fromFirstLastClauseUnion(), NullTreatmentClause: yyDollar[8].nullTreatmentClauseUnion(), OverClause: yyDollar[9].overClauseUnion()} + yyLOCAL = &FirstOrLastValueExpr{Type: yyDollar[1].firstOrLastValueExprTypeUnion(), Expr: yyDollar[3].exprUnion(), NullTreatmentClause: yyDollar[5].nullTreatmentClauseUnion(), OverClause: yyDollar[6].overClauseUnion()} } yyVAL.union = yyLOCAL case 1420: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr //line sql.y:7132 { - yyLOCAL = &LagLeadExpr{Type: yyDollar[1].lagLeadExprTypeUnion(), Expr: yyDollar[3].exprUnion(), NullTreatmentClause: yyDollar[5].nullTreatmentClauseUnion(), OverClause: yyDollar[6].overClauseUnion()} + yyLOCAL = &NtileExpr{N: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL case 1421: @@ -21767,370 +21899,370 @@ yydefault: var yyLOCAL Expr //line sql.y:7136 { - yyLOCAL = &LagLeadExpr{Type: yyDollar[1].lagLeadExprTypeUnion(), Expr: yyDollar[3].exprUnion(), N: yyDollar[5].exprUnion(), Default: yyDollar[6].exprUnion(), NullTreatmentClause: yyDollar[8].nullTreatmentClauseUnion(), OverClause: yyDollar[9].overClauseUnion()} + yyLOCAL = &NTHValueExpr{Expr: yyDollar[3].exprUnion(), N: yyDollar[5].exprUnion(), FromFirstLastClause: yyDollar[7].fromFirstLastClauseUnion(), NullTreatmentClause: yyDollar[8].nullTreatmentClauseUnion(), OverClause: yyDollar[9].overClauseUnion()} } yyVAL.union = yyLOCAL case 1422: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr //line sql.y:7140 { - yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprAdddate, Date: yyDollar[3].exprUnion(), Interval: yyDollar[6].exprUnion(), Unit: yyDollar[7].intervalTypeUnion()} + yyLOCAL = &LagLeadExpr{Type: yyDollar[1].lagLeadExprTypeUnion(), Expr: yyDollar[3].exprUnion(), NullTreatmentClause: yyDollar[5].nullTreatmentClauseUnion(), OverClause: yyDollar[6].overClauseUnion()} } yyVAL.union = yyLOCAL case 1423: - yyDollar = yyS[yypt-6 : yypt+1] + yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL Expr //line sql.y:7144 + { + yyLOCAL = &LagLeadExpr{Type: yyDollar[1].lagLeadExprTypeUnion(), Expr: yyDollar[3].exprUnion(), N: yyDollar[5].exprUnion(), Default: yyDollar[6].exprUnion(), NullTreatmentClause: yyDollar[8].nullTreatmentClauseUnion(), OverClause: yyDollar[9].overClauseUnion()} + } + yyVAL.union = yyLOCAL + case 1424: + yyDollar = yyS[yypt-8 : yypt+1] + var yyLOCAL Expr +//line sql.y:7148 + { + yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprAdddate, Date: yyDollar[3].exprUnion(), Interval: yyDollar[6].exprUnion(), Unit: yyDollar[7].intervalTypeUnion()} + } + yyVAL.union = yyLOCAL + case 1425: + yyDollar = yyS[yypt-6 : yypt+1] + var yyLOCAL Expr +//line sql.y:7152 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprAdddate, Date: yyDollar[3].exprUnion(), Interval: yyDollar[5].exprUnion(), Unit: IntervalNone} } yyVAL.union = yyLOCAL - case 1424: + case 1426: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:7148 +//line sql.y:7156 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprDateAdd, Date: yyDollar[3].exprUnion(), Interval: yyDollar[6].exprUnion(), Unit: yyDollar[7].intervalTypeUnion()} } yyVAL.union = yyLOCAL - case 1425: + case 1427: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:7152 +//line sql.y:7160 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprDateSub, Date: yyDollar[3].exprUnion(), Interval: yyDollar[6].exprUnion(), Unit: yyDollar[7].intervalTypeUnion()} } yyVAL.union = yyLOCAL - case 1426: + case 1428: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:7156 +//line sql.y:7164 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprSubdate, Date: yyDollar[3].exprUnion(), Interval: yyDollar[6].exprUnion(), Unit: yyDollar[7].intervalTypeUnion()} } yyVAL.union = yyLOCAL - case 1427: + case 1429: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:7160 +//line sql.y:7168 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprSubdate, Date: yyDollar[3].exprUnion(), Interval: yyDollar[5].exprUnion(), Unit: IntervalNone} } yyVAL.union = yyLOCAL - case 1432: + case 1434: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7170 +//line sql.y:7178 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1433: + case 1435: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7174 +//line sql.y:7182 { yyLOCAL = NewIntLiteral(yyDollar[1].str) } yyVAL.union = yyLOCAL - case 1434: + case 1436: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7178 +//line sql.y:7186 { yyLOCAL = yyDollar[1].variableUnion() } yyVAL.union = yyLOCAL - case 1435: + case 1437: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7182 +//line sql.y:7190 { yyLOCAL = parseBindVariable(yylex, yyDollar[1].str[1:]) } yyVAL.union = yyLOCAL - case 1436: + case 1438: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Expr -//line sql.y:7187 +//line sql.y:7195 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1437: + case 1439: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:7191 +//line sql.y:7199 { yyLOCAL = yyDollar[2].exprUnion() } yyVAL.union = yyLOCAL - case 1438: + case 1440: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:7197 +//line sql.y:7205 { yyLOCAL = &RegexpInstrExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1439: + case 1441: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:7201 +//line sql.y:7209 { yyLOCAL = &RegexpInstrExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Position: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1440: + case 1442: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL Expr -//line sql.y:7205 +//line sql.y:7213 { yyLOCAL = &RegexpInstrExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Position: yyDollar[7].exprUnion(), Occurrence: yyDollar[9].exprUnion()} } yyVAL.union = yyLOCAL - case 1441: + case 1443: yyDollar = yyS[yypt-12 : yypt+1] var yyLOCAL Expr -//line sql.y:7209 +//line sql.y:7217 { yyLOCAL = &RegexpInstrExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Position: yyDollar[7].exprUnion(), Occurrence: yyDollar[9].exprUnion(), ReturnOption: yyDollar[11].exprUnion()} } yyVAL.union = yyLOCAL - case 1442: + case 1444: yyDollar = yyS[yypt-14 : yypt+1] var yyLOCAL Expr -//line sql.y:7213 +//line sql.y:7221 { // Match type is kept expression as TRIM( ' m ') is accepted yyLOCAL = &RegexpInstrExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Position: yyDollar[7].exprUnion(), Occurrence: yyDollar[9].exprUnion(), ReturnOption: yyDollar[11].exprUnion(), MatchType: yyDollar[13].exprUnion()} } yyVAL.union = yyLOCAL - case 1443: + case 1445: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:7218 +//line sql.y:7226 { yyLOCAL = &RegexpLikeExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1444: + case 1446: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:7222 +//line sql.y:7230 { yyLOCAL = &RegexpLikeExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), MatchType: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1445: + case 1447: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:7226 +//line sql.y:7234 { yyLOCAL = &RegexpReplaceExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Repl: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1446: + case 1448: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL Expr -//line sql.y:7230 +//line sql.y:7238 { yyLOCAL = &RegexpReplaceExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Repl: yyDollar[7].exprUnion(), Position: yyDollar[9].exprUnion()} } yyVAL.union = yyLOCAL - case 1447: + case 1449: yyDollar = yyS[yypt-12 : yypt+1] var yyLOCAL Expr -//line sql.y:7234 +//line sql.y:7242 { yyLOCAL = &RegexpReplaceExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Repl: yyDollar[7].exprUnion(), Position: yyDollar[9].exprUnion(), Occurrence: yyDollar[11].exprUnion()} } yyVAL.union = yyLOCAL - case 1448: + case 1450: yyDollar = yyS[yypt-14 : yypt+1] var yyLOCAL Expr -//line sql.y:7238 +//line sql.y:7246 { // Match type is kept expression as TRIM( ' m ') is accepted yyLOCAL = &RegexpReplaceExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Repl: yyDollar[7].exprUnion(), Position: yyDollar[9].exprUnion(), Occurrence: yyDollar[11].exprUnion(), MatchType: yyDollar[13].exprUnion()} } yyVAL.union = yyLOCAL - case 1449: + case 1451: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:7243 +//line sql.y:7251 { yyLOCAL = &RegexpSubstrExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1450: + case 1452: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:7247 +//line sql.y:7255 { yyLOCAL = &RegexpSubstrExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Position: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1451: + case 1453: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL Expr -//line sql.y:7251 +//line sql.y:7259 { yyLOCAL = &RegexpSubstrExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Position: yyDollar[7].exprUnion(), Occurrence: yyDollar[9].exprUnion()} } yyVAL.union = yyLOCAL - case 1452: + case 1454: yyDollar = yyS[yypt-12 : yypt+1] var yyLOCAL Expr -//line sql.y:7255 +//line sql.y:7263 { // Match type is kept expression as TRIM( ' m ') is accepted yyLOCAL = &RegexpSubstrExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Position: yyDollar[7].exprUnion(), Occurrence: yyDollar[9].exprUnion(), MatchType: yyDollar[11].exprUnion()} } yyVAL.union = yyLOCAL - case 1453: + case 1455: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:7262 +//line sql.y:7270 { yyLOCAL = &ExtractValueExpr{Fragment: yyDollar[3].exprUnion(), XPathExpr: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1454: + case 1456: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:7266 +//line sql.y:7274 { yyLOCAL = &UpdateXMLExpr{Target: yyDollar[3].exprUnion(), XPathExpr: yyDollar[5].exprUnion(), NewXML: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1455: + case 1457: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:7272 +//line sql.y:7280 { yyLOCAL = &PerformanceSchemaFuncExpr{Type: FormatBytesType, Argument: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1456: + case 1458: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:7276 +//line sql.y:7284 { yyLOCAL = &PerformanceSchemaFuncExpr{Type: FormatPicoTimeType, Argument: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1457: + case 1459: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:7280 +//line sql.y:7288 { yyLOCAL = &PerformanceSchemaFuncExpr{Type: PsCurrentThreadIDType} } yyVAL.union = yyLOCAL - case 1458: + case 1460: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:7284 +//line sql.y:7292 { yyLOCAL = &PerformanceSchemaFuncExpr{Type: PsThreadIDType, Argument: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1459: + case 1461: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:7290 +//line sql.y:7298 { yyLOCAL = >IDFuncExpr{Type: GTIDSubsetType, Set1: yyDollar[3].exprUnion(), Set2: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1460: + case 1462: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:7294 +//line sql.y:7302 { yyLOCAL = >IDFuncExpr{Type: GTIDSubtractType, Set1: yyDollar[3].exprUnion(), Set2: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1461: + case 1463: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:7298 +//line sql.y:7306 { yyLOCAL = >IDFuncExpr{Type: WaitForExecutedGTIDSetType, Set1: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1462: + case 1464: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:7302 +//line sql.y:7310 { yyLOCAL = >IDFuncExpr{Type: WaitForExecutedGTIDSetType, Set1: yyDollar[3].exprUnion(), Timeout: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1463: + case 1465: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:7306 +//line sql.y:7314 { yyLOCAL = >IDFuncExpr{Type: WaitUntilSQLThreadAfterGTIDSType, Set1: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1464: + case 1466: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:7310 +//line sql.y:7318 { yyLOCAL = >IDFuncExpr{Type: WaitUntilSQLThreadAfterGTIDSType, Set1: yyDollar[3].exprUnion(), Timeout: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1465: + case 1467: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:7314 +//line sql.y:7322 { yyLOCAL = >IDFuncExpr{Type: WaitUntilSQLThreadAfterGTIDSType, Set1: yyDollar[3].exprUnion(), Timeout: yyDollar[5].exprUnion(), Channel: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1466: + case 1468: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7319 +//line sql.y:7327 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1467: + case 1469: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7323 +//line sql.y:7331 { yyLOCAL = yyDollar[2].convertTypeUnion() } yyVAL.union = yyLOCAL - case 1468: - yyDollar = yyS[yypt-1 : yypt+1] - var yyLOCAL IntervalType -//line sql.y:7329 - { - yyLOCAL = IntervalDayHour - } - yyVAL.union = yyLOCAL - case 1469: - yyDollar = yyS[yypt-1 : yypt+1] - var yyLOCAL IntervalType -//line sql.y:7333 - { - yyLOCAL = IntervalDayMicrosecond - } - yyVAL.union = yyLOCAL case 1470: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType //line sql.y:7337 { - yyLOCAL = IntervalDayMinute + yyLOCAL = IntervalDayHour } yyVAL.union = yyLOCAL case 1471: @@ -22138,7 +22270,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7341 { - yyLOCAL = IntervalDaySecond + yyLOCAL = IntervalDayMicrosecond } yyVAL.union = yyLOCAL case 1472: @@ -22146,7 +22278,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7345 { - yyLOCAL = IntervalHourMicrosecond + yyLOCAL = IntervalDayMinute } yyVAL.union = yyLOCAL case 1473: @@ -22154,7 +22286,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7349 { - yyLOCAL = IntervalHourMinute + yyLOCAL = IntervalDaySecond } yyVAL.union = yyLOCAL case 1474: @@ -22162,7 +22294,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7353 { - yyLOCAL = IntervalHourSecond + yyLOCAL = IntervalHourMicrosecond } yyVAL.union = yyLOCAL case 1475: @@ -22170,7 +22302,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7357 { - yyLOCAL = IntervalMinuteMicrosecond + yyLOCAL = IntervalHourMinute } yyVAL.union = yyLOCAL case 1476: @@ -22178,7 +22310,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7361 { - yyLOCAL = IntervalMinuteSecond + yyLOCAL = IntervalHourSecond } yyVAL.union = yyLOCAL case 1477: @@ -22186,7 +22318,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7365 { - yyLOCAL = IntervalSecondMicrosecond + yyLOCAL = IntervalMinuteMicrosecond } yyVAL.union = yyLOCAL case 1478: @@ -22194,7 +22326,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7369 { - yyLOCAL = IntervalYearMonth + yyLOCAL = IntervalMinuteSecond } yyVAL.union = yyLOCAL case 1479: @@ -22202,7 +22334,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7373 { - yyLOCAL = IntervalDay + yyLOCAL = IntervalSecondMicrosecond } yyVAL.union = yyLOCAL case 1480: @@ -22210,7 +22342,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7377 { - yyLOCAL = IntervalWeek + yyLOCAL = IntervalYearMonth } yyVAL.union = yyLOCAL case 1481: @@ -22218,7 +22350,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7381 { - yyLOCAL = IntervalHour + yyLOCAL = IntervalDay } yyVAL.union = yyLOCAL case 1482: @@ -22226,7 +22358,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7385 { - yyLOCAL = IntervalMinute + yyLOCAL = IntervalWeek } yyVAL.union = yyLOCAL case 1483: @@ -22234,7 +22366,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7389 { - yyLOCAL = IntervalMonth + yyLOCAL = IntervalHour } yyVAL.union = yyLOCAL case 1484: @@ -22242,7 +22374,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7393 { - yyLOCAL = IntervalQuarter + yyLOCAL = IntervalMinute } yyVAL.union = yyLOCAL case 1485: @@ -22250,7 +22382,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7397 { - yyLOCAL = IntervalSecond + yyLOCAL = IntervalMonth } yyVAL.union = yyLOCAL case 1486: @@ -22258,7 +22390,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7401 { - yyLOCAL = IntervalMicrosecond + yyLOCAL = IntervalQuarter } yyVAL.union = yyLOCAL case 1487: @@ -22266,23 +22398,23 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7405 { - yyLOCAL = IntervalYear + yyLOCAL = IntervalSecond } yyVAL.union = yyLOCAL case 1488: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:7411 +//line sql.y:7409 { - yyLOCAL = IntervalDay + yyLOCAL = IntervalMicrosecond } yyVAL.union = yyLOCAL case 1489: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:7415 +//line sql.y:7413 { - yyLOCAL = IntervalWeek + yyLOCAL = IntervalYear } yyVAL.union = yyLOCAL case 1490: @@ -22290,7 +22422,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7419 { - yyLOCAL = IntervalHour + yyLOCAL = IntervalDay } yyVAL.union = yyLOCAL case 1491: @@ -22298,7 +22430,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7423 { - yyLOCAL = IntervalMinute + yyLOCAL = IntervalWeek } yyVAL.union = yyLOCAL case 1492: @@ -22306,7 +22438,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7427 { - yyLOCAL = IntervalMonth + yyLOCAL = IntervalHour } yyVAL.union = yyLOCAL case 1493: @@ -22314,7 +22446,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7431 { - yyLOCAL = IntervalQuarter + yyLOCAL = IntervalMinute } yyVAL.union = yyLOCAL case 1494: @@ -22322,7 +22454,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7435 { - yyLOCAL = IntervalSecond + yyLOCAL = IntervalMonth } yyVAL.union = yyLOCAL case 1495: @@ -22330,7 +22462,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7439 { - yyLOCAL = IntervalMicrosecond + yyLOCAL = IntervalQuarter } yyVAL.union = yyLOCAL case 1496: @@ -22338,7 +22470,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7443 { - yyLOCAL = IntervalYear + yyLOCAL = IntervalSecond } yyVAL.union = yyLOCAL case 1497: @@ -22346,7 +22478,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7447 { - yyLOCAL = IntervalDay + yyLOCAL = IntervalMicrosecond } yyVAL.union = yyLOCAL case 1498: @@ -22354,7 +22486,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7451 { - yyLOCAL = IntervalWeek + yyLOCAL = IntervalYear } yyVAL.union = yyLOCAL case 1499: @@ -22362,7 +22494,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7455 { - yyLOCAL = IntervalHour + yyLOCAL = IntervalDay } yyVAL.union = yyLOCAL case 1500: @@ -22370,7 +22502,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7459 { - yyLOCAL = IntervalMinute + yyLOCAL = IntervalWeek } yyVAL.union = yyLOCAL case 1501: @@ -22378,7 +22510,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7463 { - yyLOCAL = IntervalMonth + yyLOCAL = IntervalHour } yyVAL.union = yyLOCAL case 1502: @@ -22386,7 +22518,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7467 { - yyLOCAL = IntervalQuarter + yyLOCAL = IntervalMinute } yyVAL.union = yyLOCAL case 1503: @@ -22394,7 +22526,7 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7471 { - yyLOCAL = IntervalSecond + yyLOCAL = IntervalMonth } yyVAL.union = yyLOCAL case 1504: @@ -22402,420 +22534,436 @@ yydefault: var yyLOCAL IntervalType //line sql.y:7475 { - yyLOCAL = IntervalMicrosecond + yyLOCAL = IntervalQuarter } yyVAL.union = yyLOCAL case 1505: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType //line sql.y:7479 + { + yyLOCAL = IntervalSecond + } + yyVAL.union = yyLOCAL + case 1506: + yyDollar = yyS[yypt-1 : yypt+1] + var yyLOCAL IntervalType +//line sql.y:7483 + { + yyLOCAL = IntervalMicrosecond + } + yyVAL.union = yyLOCAL + case 1507: + yyDollar = yyS[yypt-1 : yypt+1] + var yyLOCAL IntervalType +//line sql.y:7487 { yyLOCAL = IntervalYear } yyVAL.union = yyLOCAL - case 1508: + case 1510: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int -//line sql.y:7489 +//line sql.y:7497 { yyLOCAL = 0 } yyVAL.union = yyLOCAL - case 1509: + case 1511: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL int -//line sql.y:7493 +//line sql.y:7501 { yyLOCAL = 0 } yyVAL.union = yyLOCAL - case 1510: + case 1512: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int -//line sql.y:7497 +//line sql.y:7505 { yyLOCAL = convertStringToInt(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 1511: + case 1513: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:7507 +//line sql.y:7515 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("if"), Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1512: + case 1514: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:7511 +//line sql.y:7519 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("database"), Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1513: + case 1515: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:7515 +//line sql.y:7523 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("schema"), Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1514: + case 1516: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:7519 +//line sql.y:7527 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("mod"), Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1515: + case 1517: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:7523 +//line sql.y:7531 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("replace"), Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1516: + case 1518: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL MatchExprOption -//line sql.y:7529 +//line sql.y:7537 { yyLOCAL = NoOption } yyVAL.union = yyLOCAL - case 1517: + case 1519: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL MatchExprOption -//line sql.y:7533 +//line sql.y:7541 { yyLOCAL = BooleanModeOpt } yyVAL.union = yyLOCAL - case 1518: + case 1520: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL MatchExprOption -//line sql.y:7537 +//line sql.y:7545 { yyLOCAL = NaturalLanguageModeOpt } yyVAL.union = yyLOCAL - case 1519: + case 1521: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL MatchExprOption -//line sql.y:7541 +//line sql.y:7549 { yyLOCAL = NaturalLanguageModeWithQueryExpansionOpt } yyVAL.union = yyLOCAL - case 1520: + case 1522: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL MatchExprOption -//line sql.y:7545 +//line sql.y:7553 { yyLOCAL = QueryExpansionOpt } yyVAL.union = yyLOCAL - case 1521: + case 1523: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7551 +//line sql.y:7559 { yyVAL.str = string(yyDollar[1].identifierCI.String()) } - case 1522: + case 1524: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7555 +//line sql.y:7563 { yyVAL.str = string(yyDollar[1].str) } - case 1523: + case 1525: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7559 +//line sql.y:7567 { yyVAL.str = string(yyDollar[1].str) } - case 1524: + case 1526: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7565 +//line sql.y:7573 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1525: + case 1527: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7569 +//line sql.y:7577 { yyLOCAL = &ConvertType{Type: string(yyDollar[2].str), Length: ptr.Of(convertStringToInt(yyDollar[4].str))} } yyVAL.union = yyLOCAL - case 1526: + case 1528: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7573 +//line sql.y:7581 { yyLOCAL = &ConvertType{Type: string(yyDollar[2].str), Length: ptr.Of(convertStringToInt(yyDollar[4].str))} } yyVAL.union = yyLOCAL - case 1527: + case 1529: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7579 +//line sql.y:7587 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } yyVAL.union = yyLOCAL - case 1528: + case 1530: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7583 +//line sql.y:7591 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion(), Charset: yyDollar[3].columnCharset} } yyVAL.union = yyLOCAL - case 1529: + case 1531: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7587 +//line sql.y:7595 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1530: + case 1532: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7591 +//line sql.y:7599 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } yyVAL.union = yyLOCAL - case 1531: + case 1533: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7595 +//line sql.y:7603 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} yyLOCAL.Length = yyDollar[2].LengthScaleOption.Length yyLOCAL.Scale = yyDollar[2].LengthScaleOption.Scale } yyVAL.union = yyLOCAL - case 1532: + case 1534: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7601 +//line sql.y:7609 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1533: + case 1535: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7605 +//line sql.y:7613 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } yyVAL.union = yyLOCAL - case 1534: + case 1536: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7609 +//line sql.y:7617 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1535: + case 1537: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7613 +//line sql.y:7621 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1536: + case 1538: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7617 +//line sql.y:7625 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } yyVAL.union = yyLOCAL - case 1537: + case 1539: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7621 +//line sql.y:7629 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1538: + case 1540: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7625 +//line sql.y:7633 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1539: + case 1541: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7629 +//line sql.y:7637 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } yyVAL.union = yyLOCAL - case 1540: + case 1542: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7633 +//line sql.y:7641 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1541: + case 1543: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7637 +//line sql.y:7645 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1542: + case 1544: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:7643 +//line sql.y:7651 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1543: + case 1545: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:7647 +//line sql.y:7655 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1544: + case 1546: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Expr -//line sql.y:7652 +//line sql.y:7660 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1545: + case 1547: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7656 +//line sql.y:7664 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1546: + case 1548: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7661 +//line sql.y:7669 { yyVAL.str = string("") } - case 1547: + case 1549: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7665 +//line sql.y:7673 { yyVAL.str = encodeSQLString(yyDollar[2].str) } - case 1548: + case 1550: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*When -//line sql.y:7671 +//line sql.y:7679 { yyLOCAL = []*When{yyDollar[1].whenUnion()} } yyVAL.union = yyLOCAL - case 1549: + case 1551: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7675 +//line sql.y:7683 { yySLICE := (*[]*When)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[2].whenUnion()) } - case 1550: + case 1552: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *When -//line sql.y:7681 +//line sql.y:7689 { yyLOCAL = &When{Cond: yyDollar[2].exprUnion(), Val: yyDollar[4].exprUnion()} } yyVAL.union = yyLOCAL - case 1551: + case 1553: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Expr -//line sql.y:7686 +//line sql.y:7694 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1552: + case 1554: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:7690 +//line sql.y:7698 { yyLOCAL = yyDollar[2].exprUnion() } yyVAL.union = yyLOCAL - case 1553: + case 1555: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ColName -//line sql.y:7696 +//line sql.y:7704 { yyLOCAL = &ColName{Name: yyDollar[1].identifierCI} } yyVAL.union = yyLOCAL - case 1554: + case 1556: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ColName -//line sql.y:7700 +//line sql.y:7708 { yyLOCAL = &ColName{Name: NewIdentifierCI(string(yyDollar[1].str))} } yyVAL.union = yyLOCAL - case 1555: + case 1557: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColName -//line sql.y:7704 +//line sql.y:7712 { yyLOCAL = &ColName{Qualifier: TableName{Name: yyDollar[1].identifierCS}, Name: yyDollar[3].identifierCI} } yyVAL.union = yyLOCAL - case 1556: + case 1558: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *ColName -//line sql.y:7708 +//line sql.y:7716 { yyLOCAL = &ColName{Qualifier: TableName{Qualifier: yyDollar[1].identifierCS, Name: yyDollar[3].identifierCS}, Name: yyDollar[5].identifierCI} } yyVAL.union = yyLOCAL - case 1557: + case 1559: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7714 +//line sql.y:7722 { yyLOCAL = yyDollar[1].colNameUnion() } yyVAL.union = yyLOCAL - case 1558: + case 1560: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7718 +//line sql.y:7726 { yyLOCAL = &Offset{V: convertStringToInt(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1559: + case 1561: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7724 +//line sql.y:7732 { // TODO(sougou): Deprecate this construct. if yyDollar[1].identifierCI.Lowered() != "value" { @@ -22825,513 +22973,513 @@ yydefault: yyLOCAL = NewIntLiteral("1") } yyVAL.union = yyLOCAL - case 1560: + case 1562: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:7733 +//line sql.y:7741 { yyLOCAL = NewIntLiteral(yyDollar[1].str) } yyVAL.union = yyLOCAL - case 1561: + case 1563: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:7737 +//line sql.y:7745 { yyLOCAL = parseBindVariable(yylex, yyDollar[1].str[1:]) } yyVAL.union = yyLOCAL - case 1562: + case 1564: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *GroupBy -//line sql.y:7742 +//line sql.y:7750 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1563: + case 1565: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *GroupBy -//line sql.y:7746 +//line sql.y:7754 { yyLOCAL = &GroupBy{Exprs: yyDollar[3].exprsUnion(), WithRollup: yyDollar[4].booleanUnion()} } yyVAL.union = yyLOCAL - case 1564: + case 1566: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:7751 +//line sql.y:7759 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1565: + case 1567: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:7755 +//line sql.y:7763 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1566: + case 1568: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Expr -//line sql.y:7761 +//line sql.y:7769 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1567: + case 1569: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:7765 +//line sql.y:7773 { yyLOCAL = yyDollar[2].exprUnion() } yyVAL.union = yyLOCAL - case 1568: + case 1570: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *NamedWindow -//line sql.y:7771 +//line sql.y:7779 { yyLOCAL = &NamedWindow{yyDollar[2].windowDefinitionsUnion()} } yyVAL.union = yyLOCAL - case 1569: + case 1571: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL NamedWindows -//line sql.y:7777 +//line sql.y:7785 { yyLOCAL = NamedWindows{yyDollar[1].namedWindowUnion()} } yyVAL.union = yyLOCAL - case 1570: + case 1572: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7781 +//line sql.y:7789 { yySLICE := (*NamedWindows)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].namedWindowUnion()) } - case 1571: + case 1573: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL NamedWindows -//line sql.y:7786 +//line sql.y:7794 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1572: + case 1574: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL NamedWindows -//line sql.y:7790 +//line sql.y:7798 { yyLOCAL = yyDollar[1].namedWindowsUnion() } yyVAL.union = yyLOCAL - case 1573: + case 1575: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL OrderBy -//line sql.y:7795 +//line sql.y:7803 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1574: + case 1576: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL OrderBy -//line sql.y:7799 +//line sql.y:7807 { yyLOCAL = yyDollar[1].orderByUnion() } yyVAL.union = yyLOCAL - case 1575: + case 1577: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL OrderBy -//line sql.y:7805 +//line sql.y:7813 { yyLOCAL = yyDollar[3].orderByUnion() } yyVAL.union = yyLOCAL - case 1576: + case 1578: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL OrderBy -//line sql.y:7811 +//line sql.y:7819 { yyLOCAL = OrderBy{yyDollar[1].orderUnion()} } yyVAL.union = yyLOCAL - case 1577: + case 1579: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7815 +//line sql.y:7823 { yySLICE := (*OrderBy)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].orderUnion()) } - case 1578: + case 1580: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *Order -//line sql.y:7821 +//line sql.y:7829 { yyLOCAL = &Order{Expr: yyDollar[1].exprUnion(), Direction: yyDollar[2].orderDirectionUnion()} } yyVAL.union = yyLOCAL - case 1579: + case 1581: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL OrderDirection -//line sql.y:7826 +//line sql.y:7834 { yyLOCAL = AscOrder } yyVAL.union = yyLOCAL - case 1580: + case 1582: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL OrderDirection -//line sql.y:7830 +//line sql.y:7838 { yyLOCAL = AscOrder } yyVAL.union = yyLOCAL - case 1581: + case 1583: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL OrderDirection -//line sql.y:7834 +//line sql.y:7842 { yyLOCAL = DescOrder } yyVAL.union = yyLOCAL - case 1582: + case 1584: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *Limit -//line sql.y:7839 +//line sql.y:7847 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1583: + case 1585: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Limit -//line sql.y:7843 +//line sql.y:7851 { yyLOCAL = yyDollar[1].limitUnion() } yyVAL.union = yyLOCAL - case 1584: + case 1586: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *Limit -//line sql.y:7849 +//line sql.y:7857 { yyLOCAL = &Limit{Rowcount: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 1585: + case 1587: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *Limit -//line sql.y:7853 +//line sql.y:7861 { yyLOCAL = &Limit{Offset: yyDollar[2].exprUnion(), Rowcount: yyDollar[4].exprUnion()} } yyVAL.union = yyLOCAL - case 1586: + case 1588: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *Limit -//line sql.y:7857 +//line sql.y:7865 { yyLOCAL = &Limit{Offset: yyDollar[4].exprUnion(), Rowcount: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 1587: + case 1589: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:7862 +//line sql.y:7870 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1588: + case 1590: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:7866 +//line sql.y:7874 { yyLOCAL = []AlterOption{yyDollar[1].alterOptionUnion(), yyDollar[2].alterOptionUnion()} } yyVAL.union = yyLOCAL - case 1589: + case 1591: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:7870 +//line sql.y:7878 { yyLOCAL = []AlterOption{yyDollar[1].alterOptionUnion(), yyDollar[2].alterOptionUnion()} } yyVAL.union = yyLOCAL - case 1590: + case 1592: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:7874 +//line sql.y:7882 { yyLOCAL = []AlterOption{yyDollar[1].alterOptionUnion()} } yyVAL.union = yyLOCAL - case 1591: + case 1593: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:7878 +//line sql.y:7886 { yyLOCAL = []AlterOption{yyDollar[1].alterOptionUnion()} } yyVAL.union = yyLOCAL - case 1592: + case 1594: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7885 +//line sql.y:7893 { yyLOCAL = &LockOption{Type: DefaultType} } yyVAL.union = yyLOCAL - case 1593: + case 1595: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7889 +//line sql.y:7897 { yyLOCAL = &LockOption{Type: NoneType} } yyVAL.union = yyLOCAL - case 1594: + case 1596: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7893 +//line sql.y:7901 { yyLOCAL = &LockOption{Type: SharedType} } yyVAL.union = yyLOCAL - case 1595: + case 1597: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7897 +//line sql.y:7905 { yyLOCAL = &LockOption{Type: ExclusiveType} } yyVAL.union = yyLOCAL - case 1596: + case 1598: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7903 +//line sql.y:7911 { yyLOCAL = AlgorithmValue(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1597: + case 1599: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7907 +//line sql.y:7915 { yyLOCAL = AlgorithmValue(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1598: + case 1600: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7911 +//line sql.y:7919 { yyLOCAL = AlgorithmValue(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1599: + case 1601: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7915 +//line sql.y:7923 { yyLOCAL = AlgorithmValue(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1600: + case 1602: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7920 +//line sql.y:7928 { yyVAL.str = "" } - case 1602: + case 1604: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7927 +//line sql.y:7935 { yyVAL.str = string(yyDollar[3].str) } - case 1603: + case 1605: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7931 +//line sql.y:7939 { yyVAL.str = string(yyDollar[3].str) } - case 1604: + case 1606: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7935 +//line sql.y:7943 { yyVAL.str = string(yyDollar[3].str) } - case 1605: + case 1607: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7940 +//line sql.y:7948 { yyVAL.str = "" } - case 1606: + case 1608: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7944 +//line sql.y:7952 { yyVAL.str = yyDollar[3].str } - case 1607: + case 1609: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7950 +//line sql.y:7958 { yyVAL.str = string(yyDollar[1].str) } - case 1608: + case 1610: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7954 +//line sql.y:7962 { yyVAL.str = string(yyDollar[1].str) } - case 1609: + case 1611: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7959 +//line sql.y:7967 { yyVAL.str = "" } - case 1610: + case 1612: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:7963 +//line sql.y:7971 { yyVAL.str = yyDollar[2].str } - case 1611: + case 1613: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7968 +//line sql.y:7976 { yyVAL.str = "cascaded" } - case 1612: + case 1614: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7972 +//line sql.y:7980 { yyVAL.str = string(yyDollar[1].str) } - case 1613: + case 1615: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7976 +//line sql.y:7984 { yyVAL.str = string(yyDollar[1].str) } - case 1614: + case 1616: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*ProcParameter -//line sql.y:7981 +//line sql.y:7989 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1615: + case 1617: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*ProcParameter -//line sql.y:7985 +//line sql.y:7993 { yyLOCAL = yyDollar[1].procParamsUnion() } yyVAL.union = yyLOCAL - case 1616: + case 1618: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*ProcParameter -//line sql.y:7991 +//line sql.y:7999 { yyLOCAL = []*ProcParameter{yyDollar[1].procParamUnion()} } yyVAL.union = yyLOCAL - case 1617: + case 1619: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7995 +//line sql.y:8003 { yySLICE := (*[]*ProcParameter)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].procParamUnion()) } - case 1618: + case 1620: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ProcParameter -//line sql.y:8001 +//line sql.y:8009 { yyLOCAL = &ProcParameter{Mode: yyDollar[1].procParamModeUnion(), Name: yyDollar[2].identifierCI, Type: yyDollar[3].columnType} } yyVAL.union = yyLOCAL - case 1619: + case 1621: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL ProcParameterMode -//line sql.y:8006 +//line sql.y:8014 { yyLOCAL = InMode } yyVAL.union = yyLOCAL - case 1620: + case 1622: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ProcParameterMode -//line sql.y:8010 +//line sql.y:8018 { yyLOCAL = InMode } yyVAL.union = yyLOCAL - case 1621: + case 1623: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ProcParameterMode -//line sql.y:8014 +//line sql.y:8022 { yyLOCAL = InoutMode } yyVAL.union = yyLOCAL - case 1622: + case 1624: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ProcParameterMode -//line sql.y:8018 +//line sql.y:8026 { yyLOCAL = OutMode } yyVAL.union = yyLOCAL - case 1623: + case 1625: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *Definer -//line sql.y:8023 +//line sql.y:8031 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1625: + case 1627: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *Definer -//line sql.y:8030 +//line sql.y:8038 { yyLOCAL = yyDollar[3].definerUnion() } yyVAL.union = yyLOCAL - case 1626: + case 1628: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Definer -//line sql.y:8036 +//line sql.y:8044 { yyLOCAL = &Definer{ Name: string(yyDollar[1].str), } } yyVAL.union = yyLOCAL - case 1627: + case 1629: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *Definer -//line sql.y:8042 +//line sql.y:8050 { yyLOCAL = &Definer{ Name: string(yyDollar[1].str), } } yyVAL.union = yyLOCAL - case 1628: + case 1630: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *Definer -//line sql.y:8048 +//line sql.y:8056 { yyLOCAL = &Definer{ Name: yyDollar[1].str, @@ -23339,503 +23487,503 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1629: + case 1631: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8057 +//line sql.y:8065 { yyVAL.str = encodeSQLString(yyDollar[1].str) } - case 1630: + case 1632: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8061 +//line sql.y:8069 { yyVAL.str = formatIdentifier(yyDollar[1].str) } - case 1631: + case 1633: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:8066 +//line sql.y:8074 { yyVAL.str = "" } - case 1632: + case 1634: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8070 +//line sql.y:8078 { yyVAL.str = formatAddress(yyDollar[1].str) } - case 1633: + case 1635: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Lock -//line sql.y:8076 +//line sql.y:8084 { yyLOCAL = ForUpdateLock } yyVAL.union = yyLOCAL - case 1634: + case 1636: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Lock -//line sql.y:8080 +//line sql.y:8088 { yyLOCAL = ForUpdateLockNoWait } yyVAL.union = yyLOCAL - case 1635: + case 1637: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Lock -//line sql.y:8084 +//line sql.y:8092 { yyLOCAL = ForUpdateLockSkipLocked } yyVAL.union = yyLOCAL - case 1636: + case 1638: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Lock -//line sql.y:8088 +//line sql.y:8096 { yyLOCAL = ForShareLock } yyVAL.union = yyLOCAL - case 1637: + case 1639: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Lock -//line sql.y:8092 +//line sql.y:8100 { yyLOCAL = ForShareLockNoWait } yyVAL.union = yyLOCAL - case 1638: + case 1640: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Lock -//line sql.y:8096 +//line sql.y:8104 { yyLOCAL = ForShareLockSkipLocked } yyVAL.union = yyLOCAL - case 1639: + case 1641: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Lock -//line sql.y:8100 +//line sql.y:8108 { yyLOCAL = ShareModeLock } yyVAL.union = yyLOCAL - case 1640: + case 1642: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL *SelectInto -//line sql.y:8106 +//line sql.y:8114 { yyLOCAL = &SelectInto{Type: IntoOutfileS3, FileName: encodeSQLString(yyDollar[4].str), Charset: yyDollar[5].columnCharset, FormatOption: yyDollar[6].str, ExportOption: yyDollar[7].str, Manifest: yyDollar[8].str, Overwrite: yyDollar[9].str} } yyVAL.union = yyLOCAL - case 1641: + case 1643: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *SelectInto -//line sql.y:8110 +//line sql.y:8118 { yyLOCAL = &SelectInto{Type: IntoDumpfile, FileName: encodeSQLString(yyDollar[3].str), Charset: ColumnCharset{}, FormatOption: "", ExportOption: "", Manifest: "", Overwrite: ""} } yyVAL.union = yyLOCAL - case 1642: + case 1644: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *SelectInto -//line sql.y:8114 +//line sql.y:8122 { yyLOCAL = &SelectInto{Type: IntoOutfile, FileName: encodeSQLString(yyDollar[3].str), Charset: yyDollar[4].columnCharset, FormatOption: "", ExportOption: yyDollar[5].str, Manifest: "", Overwrite: ""} } yyVAL.union = yyLOCAL - case 1643: + case 1645: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *SelectInto -//line sql.y:8118 +//line sql.y:8126 { yyLOCAL = &SelectInto{Type: IntoVariables, VarList: yyDollar[2].variablesUnion()} } yyVAL.union = yyLOCAL - case 1644: + case 1646: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:8124 +//line sql.y:8132 { yySLICE := (*[]*Variable)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].variableUnion()) } - case 1645: + case 1647: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*Variable -//line sql.y:8128 +//line sql.y:8136 { yyLOCAL = []*Variable{yyDollar[1].variableUnion()} } yyVAL.union = yyLOCAL - case 1646: + case 1648: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Variable -//line sql.y:8134 +//line sql.y:8142 { yyLOCAL = yyDollar[1].variableUnion() } yyVAL.union = yyLOCAL - case 1647: + case 1649: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Variable -//line sql.y:8138 +//line sql.y:8146 { yyLOCAL = &Variable{Name: createIdentifierCI(yyDollar[1].str), Scope: NoScope} } yyVAL.union = yyLOCAL - case 1648: + case 1650: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:8143 +//line sql.y:8151 { yyVAL.str = "" } - case 1649: + case 1651: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:8147 +//line sql.y:8155 { yyVAL.str = " format csv" + yyDollar[3].str } - case 1650: + case 1652: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:8151 +//line sql.y:8159 { yyVAL.str = " format text" + yyDollar[3].str } - case 1651: + case 1653: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:8156 +//line sql.y:8164 { yyVAL.str = "" } - case 1652: + case 1654: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8160 +//line sql.y:8168 { yyVAL.str = " header" } - case 1653: + case 1655: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:8165 +//line sql.y:8173 { yyVAL.str = "" } - case 1654: + case 1656: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:8169 +//line sql.y:8177 { yyVAL.str = " manifest on" } - case 1655: + case 1657: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:8173 +//line sql.y:8181 { yyVAL.str = " manifest off" } - case 1656: + case 1658: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:8178 +//line sql.y:8186 { yyVAL.str = "" } - case 1657: + case 1659: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:8182 +//line sql.y:8190 { yyVAL.str = " overwrite on" } - case 1658: + case 1660: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:8186 +//line sql.y:8194 { yyVAL.str = " overwrite off" } - case 1659: + case 1661: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:8192 +//line sql.y:8200 { yyVAL.str = yyDollar[1].str + yyDollar[2].str } - case 1660: + case 1662: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:8197 +//line sql.y:8205 { yyVAL.str = "" } - case 1661: + case 1663: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:8201 +//line sql.y:8209 { yyVAL.str = " lines" + yyDollar[2].str } - case 1662: + case 1664: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8207 +//line sql.y:8215 { yyVAL.str = yyDollar[1].str } - case 1663: + case 1665: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:8211 +//line sql.y:8219 { yyVAL.str = yyDollar[1].str + yyDollar[2].str } - case 1664: + case 1666: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:8217 +//line sql.y:8225 { yyVAL.str = " starting by " + encodeSQLString(yyDollar[3].str) } - case 1665: + case 1667: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:8221 +//line sql.y:8229 { yyVAL.str = " terminated by " + encodeSQLString(yyDollar[3].str) } - case 1666: + case 1668: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:8226 +//line sql.y:8234 { yyVAL.str = "" } - case 1667: + case 1669: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:8230 +//line sql.y:8238 { yyVAL.str = " " + yyDollar[1].str + yyDollar[2].str } - case 1668: + case 1670: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8236 +//line sql.y:8244 { yyVAL.str = yyDollar[1].str } - case 1669: + case 1671: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:8240 +//line sql.y:8248 { yyVAL.str = yyDollar[1].str + yyDollar[2].str } - case 1670: + case 1672: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:8246 +//line sql.y:8254 { yyVAL.str = " terminated by " + encodeSQLString(yyDollar[3].str) } - case 1671: + case 1673: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:8250 +//line sql.y:8258 { yyVAL.str = yyDollar[1].str + " enclosed by " + encodeSQLString(yyDollar[4].str) } - case 1672: + case 1674: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:8254 +//line sql.y:8262 { yyVAL.str = " escaped by " + encodeSQLString(yyDollar[3].str) } - case 1673: + case 1675: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:8259 +//line sql.y:8267 { yyVAL.str = "" } - case 1674: + case 1676: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8263 +//line sql.y:8271 { yyVAL.str = " optionally" } - case 1675: + case 1677: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *Insert -//line sql.y:8276 +//line sql.y:8284 { yyLOCAL = &Insert{Rows: yyDollar[2].valuesUnion(), RowAlias: yyDollar[3].rowAliasUnion()} } yyVAL.union = yyLOCAL - case 1676: + case 1678: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Insert -//line sql.y:8280 +//line sql.y:8288 { yyLOCAL = &Insert{Rows: yyDollar[1].tableStmtUnion()} } yyVAL.union = yyLOCAL - case 1677: + case 1679: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *Insert -//line sql.y:8284 +//line sql.y:8292 { yyLOCAL = &Insert{Columns: yyDollar[2].columnsUnion(), Rows: yyDollar[5].valuesUnion(), RowAlias: yyDollar[6].rowAliasUnion()} } yyVAL.union = yyLOCAL - case 1678: + case 1680: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *Insert -//line sql.y:8288 +//line sql.y:8296 { yyLOCAL = &Insert{Columns: []IdentifierCI{}, Rows: yyDollar[4].valuesUnion(), RowAlias: yyDollar[5].rowAliasUnion()} } yyVAL.union = yyLOCAL - case 1679: + case 1681: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *Insert -//line sql.y:8292 +//line sql.y:8300 { yyLOCAL = &Insert{Columns: yyDollar[2].columnsUnion(), Rows: yyDollar[4].tableStmtUnion()} } yyVAL.union = yyLOCAL - case 1680: + case 1682: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Columns -//line sql.y:8298 +//line sql.y:8306 { yyLOCAL = Columns{yyDollar[1].identifierCI} } yyVAL.union = yyLOCAL - case 1681: + case 1683: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Columns -//line sql.y:8302 +//line sql.y:8310 { yyLOCAL = Columns{yyDollar[3].identifierCI} } yyVAL.union = yyLOCAL - case 1682: + case 1684: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:8306 +//line sql.y:8314 { yySLICE := (*Columns)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].identifierCI) } - case 1683: + case 1685: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:8310 +//line sql.y:8318 { yySLICE := (*Columns)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[5].identifierCI) } - case 1684: + case 1686: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *RowAlias -//line sql.y:8315 +//line sql.y:8323 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1685: + case 1687: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *RowAlias -//line sql.y:8319 +//line sql.y:8327 { yyLOCAL = &RowAlias{TableName: yyDollar[2].identifierCS} } yyVAL.union = yyLOCAL - case 1686: + case 1688: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *RowAlias -//line sql.y:8323 +//line sql.y:8331 { yyLOCAL = &RowAlias{TableName: yyDollar[2].identifierCS, Columns: yyDollar[4].columnsUnion()} } yyVAL.union = yyLOCAL - case 1687: + case 1689: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL UpdateExprs -//line sql.y:8328 +//line sql.y:8336 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1688: + case 1690: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL UpdateExprs -//line sql.y:8332 +//line sql.y:8340 { yyLOCAL = yyDollar[5].updateExprsUnion() } yyVAL.union = yyLOCAL - case 1689: + case 1691: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Values -//line sql.y:8338 +//line sql.y:8346 { yyLOCAL = Values{yyDollar[1].valTupleUnion()} } yyVAL.union = yyLOCAL - case 1690: + case 1692: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:8342 +//line sql.y:8350 { yySLICE := (*Values)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].valTupleUnion()) } - case 1691: + case 1693: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Values -//line sql.y:8348 +//line sql.y:8356 { yyLOCAL = Values{yyDollar[1].valTupleUnion()} } yyVAL.union = yyLOCAL - case 1692: + case 1694: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:8352 +//line sql.y:8360 { yySLICE := (*Values)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].valTupleUnion()) } - case 1693: + case 1695: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ValTuple -//line sql.y:8358 +//line sql.y:8366 { yyLOCAL = yyDollar[1].valTupleUnion() } yyVAL.union = yyLOCAL - case 1694: + case 1696: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL ValTuple -//line sql.y:8362 +//line sql.y:8370 { yyLOCAL = ValTuple{} } yyVAL.union = yyLOCAL - case 1695: + case 1697: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ValTuple -//line sql.y:8368 +//line sql.y:8376 { yyLOCAL = yyDollar[1].valTupleUnion() } yyVAL.union = yyLOCAL - case 1696: + case 1698: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL ValTuple -//line sql.y:8372 +//line sql.y:8380 { yyLOCAL = ValTuple{} } yyVAL.union = yyLOCAL - case 1697: + case 1699: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL ValTuple -//line sql.y:8378 +//line sql.y:8386 { yyLOCAL = ValTuple(yyDollar[2].exprsUnion()) } yyVAL.union = yyLOCAL - case 1698: + case 1700: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL ValTuple -//line sql.y:8384 +//line sql.y:8392 { yyLOCAL = ValTuple(yyDollar[3].exprsUnion()) } yyVAL.union = yyLOCAL - case 1701: + case 1703: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:8394 +//line sql.y:8402 { if len(yyDollar[1].valTupleUnion()) == 1 { yyLOCAL = yyDollar[1].valTupleUnion()[0] @@ -23844,300 +23992,300 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1702: + case 1704: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL UpdateExprs -//line sql.y:8404 +//line sql.y:8412 { yyLOCAL = UpdateExprs{yyDollar[1].updateExprUnion()} } yyVAL.union = yyLOCAL - case 1703: + case 1705: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:8408 +//line sql.y:8416 { yySLICE := (*UpdateExprs)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].updateExprUnion()) } - case 1704: + case 1706: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *UpdateExpr -//line sql.y:8414 +//line sql.y:8422 { yyLOCAL = &UpdateExpr{Name: yyDollar[1].colNameUnion(), Expr: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1706: + case 1708: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:8421 +//line sql.y:8429 { yyVAL.str = "charset" } - case 1709: + case 1711: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:8431 +//line sql.y:8439 { yyLOCAL = NewStrLiteral(yyDollar[1].identifierCI.String()) } yyVAL.union = yyLOCAL - case 1710: + case 1712: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:8435 +//line sql.y:8443 { yyLOCAL = NewStrLiteral(yyDollar[1].str) } yyVAL.union = yyLOCAL - case 1711: + case 1713: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:8439 +//line sql.y:8447 { yyLOCAL = &Default{} } yyVAL.union = yyLOCAL - case 1714: + case 1716: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:8448 +//line sql.y:8456 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1715: + case 1717: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:8450 +//line sql.y:8458 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1716: + case 1718: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:8453 +//line sql.y:8461 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1717: + case 1719: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:8455 +//line sql.y:8463 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1718: + case 1720: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:8458 +//line sql.y:8466 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1719: + case 1721: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL bool -//line sql.y:8460 +//line sql.y:8468 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1720: + case 1722: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Ignore -//line sql.y:8463 +//line sql.y:8471 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1721: + case 1723: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Ignore -//line sql.y:8465 +//line sql.y:8473 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1722: + case 1724: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:8468 +//line sql.y:8476 { yyVAL.empty = struct{}{} } - case 1723: + case 1725: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8470 +//line sql.y:8478 { yyVAL.empty = struct{}{} } - case 1724: + case 1726: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8472 +//line sql.y:8480 { yyVAL.empty = struct{}{} } - case 1725: + case 1727: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:8476 +//line sql.y:8484 { yyLOCAL = &CallProc{Name: yyDollar[2].tableName, Params: yyDollar[4].exprsUnion()} } yyVAL.union = yyLOCAL - case 1726: + case 1728: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []Expr -//line sql.y:8481 +//line sql.y:8489 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1727: + case 1729: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []Expr -//line sql.y:8485 +//line sql.y:8493 { yyLOCAL = yyDollar[1].exprsUnion() } yyVAL.union = yyLOCAL - case 1728: + case 1730: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*IndexOption -//line sql.y:8490 +//line sql.y:8498 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1729: + case 1731: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*IndexOption -//line sql.y:8492 +//line sql.y:8500 { yyLOCAL = []*IndexOption{yyDollar[1].indexOptionUnion()} } yyVAL.union = yyLOCAL - case 1730: + case 1732: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *IndexOption -//line sql.y:8496 +//line sql.y:8504 { yyLOCAL = &IndexOption{Name: string(yyDollar[1].str), String: string(yyDollar[2].identifierCI.String())} } yyVAL.union = yyLOCAL - case 1731: + case 1733: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8502 +//line sql.y:8510 { yyVAL.identifierCI = yyDollar[1].identifierCI } - case 1732: + case 1734: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8506 +//line sql.y:8514 { yyVAL.identifierCI = NewIdentifierCI(string(yyDollar[1].str)) } - case 1734: + case 1736: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8513 +//line sql.y:8521 { yyVAL.identifierCI = NewIdentifierCI(string(yyDollar[1].str)) } - case 1735: + case 1737: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8519 +//line sql.y:8527 { yyVAL.identifierCS = NewIdentifierCS(string(yyDollar[1].str)) } - case 1736: + case 1738: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8523 +//line sql.y:8531 { yyVAL.identifierCS = NewIdentifierCS(string(yyDollar[1].str)) } - case 1737: + case 1739: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:8529 +//line sql.y:8537 { yyVAL.identifierCS = NewIdentifierCS("") } - case 1738: + case 1740: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8533 +//line sql.y:8541 { yyVAL.identifierCS = yyDollar[1].identifierCS } - case 1740: + case 1742: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8540 +//line sql.y:8548 { yyVAL.identifierCS = NewIdentifierCS(string(yyDollar[1].str)) } - case 1741: + case 1743: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:8546 +//line sql.y:8554 { yyLOCAL = &Kill{Type: yyDollar[2].killTypeUnion(), ProcesslistID: convertStringToUInt64(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 1742: + case 1744: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL KillType -//line sql.y:8552 +//line sql.y:8560 { yyLOCAL = ConnectionType } yyVAL.union = yyLOCAL - case 1743: + case 1745: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL KillType -//line sql.y:8556 +//line sql.y:8564 { yyLOCAL = ConnectionType } yyVAL.union = yyLOCAL - case 1744: + case 1746: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL KillType -//line sql.y:8560 +//line sql.y:8568 { yyLOCAL = QueryType } yyVAL.union = yyLOCAL - case 2411: + case 2413: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:9255 +//line sql.y:9263 { } - case 2412: + case 2414: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:9260 +//line sql.y:9268 { } - case 2413: + case 2415: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:9264 +//line sql.y:9272 { skipToEnd(yylex) } - case 2414: + case 2416: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:9269 +//line sql.y:9277 { skipToEnd(yylex) } - case 2415: + case 2417: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:9273 +//line sql.y:9281 { skipToEnd(yylex) } - case 2416: + case 2418: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:9277 +//line sql.y:9285 { skipToEnd(yylex) } diff --git a/go/vt/sqlparser/sql.y b/go/vt/sqlparser/sql.y index a8ed0716422..b1341042e68 100644 --- a/go/vt/sqlparser/sql.y +++ b/go/vt/sqlparser/sql.y @@ -1235,13 +1235,21 @@ values_statement: } stream_statement: - STREAM comment_opt select_expression FROM table_name + STREAM comment_opt '*' FROM table_name + { + $$ = &Stream{Comments: Comments($2).Parsed(), SelectExpr: &StarExpr{}, Table: $5} + } +| STREAM comment_opt select_expression FROM table_name { $$ = &Stream{Comments: Comments($2).Parsed(), SelectExpr: $3, Table: $5} } vstream_statement: - VSTREAM comment_opt select_expression FROM table_name where_expression_opt limit_opt + VSTREAM comment_opt '*' FROM table_name where_expression_opt limit_opt + { + $$ = &VStream{Comments: Comments($2).Parsed(), SelectExpr: &StarExpr{}, Table: $5, Where: NewWhere(WhereClause, $6), Limit: $7} + } +| VSTREAM comment_opt select_expression FROM table_name where_expression_opt limit_opt { $$ = &VStream{Comments: Comments($2).Parsed(), SelectExpr: $3, Table: $5, Where: NewWhere(WhereClause, $6), Limit: $7} } @@ -3475,7 +3483,7 @@ alter_option: } | DROP CONSTRAINT sql_id { - $$ = &DropKey{Type:CheckKeyType, Name:$3} + $$ = &DropKey{Type:ConstraintType, Name:$3} } | FORCE { @@ -5288,7 +5296,11 @@ select_option: } select_expression_list: - select_expression + '*' + { + $$ = &SelectExprs{Exprs: []SelectExpr{&StarExpr{}}} + } +| select_expression { $$ = &SelectExprs{Exprs: []SelectExpr{$1}} } @@ -5300,11 +5312,7 @@ select_expression_list: } select_expression: - '*' - { - $$ = &StarExpr{} - } -| expression as_ci_opt + expression as_ci_opt { $$ = &AliasedExpr{Expr: $1, As: $2} } diff --git a/go/vt/topo/zk2topo/server_test.go b/go/vt/topo/zk2topo/server_test.go index 9fd36740913..836b55e4f5e 100644 --- a/go/vt/topo/zk2topo/server_test.go +++ b/go/vt/topo/zk2topo/server_test.go @@ -19,6 +19,7 @@ package zk2topo import ( "context" "fmt" + "os" "path" "testing" "time" @@ -34,9 +35,24 @@ import ( ) func TestZk2Topo(t *testing.T) { + if testing.Short() || os.Getenv("CI") == "true" { + t.Skip("skipping integration test in short mode and in CI (it's too flaky).") + } + // Start a real single ZK daemon, and close it after all tests are done. zkd, serverAddr := zkctl.StartLocalZk(testfiles.GoVtTopoZk2topoZkID, testfiles.GoVtTopoZk2topoPort) - defer zkd.Teardown() + defer func() { + var lastErr error + for range 3 { + if lastErr = zkd.Teardown(); lastErr == nil { + return + } + time.Sleep(1 * time.Second) + } + if lastErr != nil { + t.Logf("zkd.Teardown failed after retries: %v", lastErr) + } + }() // Run the test suite. testIndex := 0 diff --git a/go/vt/topo/zk2topo/zk_conn.go b/go/vt/topo/zk2topo/zk_conn.go index aa7ac13d281..eed4f2d8a15 100644 --- a/go/vt/topo/zk2topo/zk_conn.go +++ b/go/vt/topo/zk2topo/zk_conn.go @@ -32,6 +32,7 @@ import ( "github.com/z-division/go-zookeeper/zk" "golang.org/x/sync/semaphore" + "vitess.io/vitess/go/stats" "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/servenv" ) @@ -55,6 +56,16 @@ var ( baseTimeout = 30 * time.Second certPath, keyPath, caPath, authFile string + + zkLockAcquisition = stats.NewGaugeDuration( + "ZkLockAcquisition", + "Time to acquire a zookeeper lock") + zkConnAcquisitionRetry = stats.NewCounter( + "ZkConnAcquisitionRetry", + "Number of retries to acquire a zookeeper connection") + zkConnState = stats.NewCountersWithSingleLabel( + "ZkConnState", + "Number of times the zookeeper connection has entered each state", "state") ) func init() { @@ -236,14 +247,18 @@ func (c *ZkConn) Close() error { func (c *ZkConn) withRetry(ctx context.Context, action func(conn *zk.Conn) error) (err error) { // Handle concurrent access to a Zookeeper server here. + start := time.Now() err = c.sem.Acquire(ctx, 1) if err != nil { return err } + duration := time.Since(start) + zkLockAcquisition.Set(duration) defer c.sem.Release(1) for i := 0; i < maxAttempts; i++ { if i > 0 { + zkConnAcquisitionRetry.Add(1) // Add a bit of backoff time before retrying: // 1 second base + up to 5 seconds. time.Sleep(1*time.Second + time.Duration(rand.Int64N(5e9))) @@ -324,6 +339,7 @@ func (c *ZkConn) maybeAddAuth(ctx context.Context) { // clears out the connection record. func (c *ZkConn) handleSessionEvents(conn *zk.Conn, session <-chan zk.Event) { for event := range session { + zkConnState.Add(event.State.String(), 1) switch event.State { case zk.StateDisconnected, zk.StateExpired, zk.StateConnecting: diff --git a/go/vt/topo/zk2topo/zk_conn_test.go b/go/vt/topo/zk2topo/zk_conn_test.go index e79987b562f..2b953934c77 100644 --- a/go/vt/topo/zk2topo/zk_conn_test.go +++ b/go/vt/topo/zk2topo/zk_conn_test.go @@ -18,6 +18,7 @@ package zk2topo import ( "context" + "os" "testing" "time" @@ -29,8 +30,23 @@ import ( ) func TestZkConnClosedOnDisconnect(t *testing.T) { + if testing.Short() || os.Getenv("CI") == "true" { + t.Skip("skipping integration test in short mode and in CI (it's too flaky).") + } + zkd, serverAddr := zkctl.StartLocalZk(testfiles.GoVtTopoZk2topoZkID, testfiles.GoVtTopoZk2topoPort) - defer zkd.Teardown() + defer func() { + var lastErr error + for range 3 { + if lastErr = zkd.Teardown(); lastErr == nil { + return + } + time.Sleep(1 * time.Second) + } + if lastErr != nil { + t.Logf("zkd.Teardown failed after retries: %v", lastErr) + } + }() conn := Connect(serverAddr) defer conn.Close() diff --git a/go/vt/vtadmin/vtctldclient/proxy_test.go b/go/vt/vtadmin/vtctldclient/proxy_test.go index 520ab48ab1d..c164839ec50 100644 --- a/go/vt/vtadmin/vtctldclient/proxy_test.go +++ b/go/vt/vtadmin/vtctldclient/proxy_test.go @@ -123,6 +123,8 @@ func (d *testdisco) DiscoverVtctldAddrs(ctx context.Context, tags []string) ([]s // TestRedial tests that vtadmin-api is able to recover from a lost connection to // a vtctld by rediscovering and redialing a new one. func TestRedial(t *testing.T) { + t.Skip("flaky test, gRPC reconnection timing is unreliable") + // Initialize vtctld #1 listener1, server1, err := initVtctldServer() require.NoError(t, err) diff --git a/go/vt/vtcombo/tablet_map.go b/go/vt/vtcombo/tablet_map.go index e8c8935f989..8d04a2e559e 100644 --- a/go/vt/vtcombo/tablet_map.go +++ b/go/vt/vtcombo/tablet_map.go @@ -18,6 +18,7 @@ package vtcombo import ( "context" + "errors" "fmt" "os" "path" @@ -1009,8 +1010,8 @@ func (itmc *internalTabletManagerClient) ReadReparentJournalInfo(ctx context.Con return 0, fmt.Errorf("not implemented in vtcombo") } -func (itmc *internalTabletManagerClient) DemotePrimary(context.Context, *topodatapb.Tablet) (*replicationdatapb.PrimaryStatus, error) { - return nil, fmt.Errorf("not implemented in vtcombo") +func (itmc *internalTabletManagerClient) DemotePrimary(context.Context, *topodatapb.Tablet, bool) (*replicationdatapb.PrimaryStatus, error) { + return nil, errors.New("not implemented in vtcombo") } func (itmc *internalTabletManagerClient) UndoDemotePrimary(context.Context, *topodatapb.Tablet, bool) error { @@ -1091,6 +1092,7 @@ func (itmc *internalTabletManagerClient) ResetReplicationParameters(context.Cont func (itmc *internalTabletManagerClient) ReplicaWasRestarted(context.Context, *topodatapb.Tablet, *topodatapb.TabletAlias) error { return fmt.Errorf("not implemented in vtcombo") } + func (itmc *internalTabletManagerClient) ResetSequences(ctx context.Context, tablet *topodatapb.Tablet, tables []string) error { return fmt.Errorf("not implemented in vtcombo") } diff --git a/go/vt/vtctl/grpcvtctldserver/testutil/test_tmclient.go b/go/vt/vtctl/grpcvtctldserver/testutil/test_tmclient.go index 3b6af754d4e..e548d08cad5 100644 --- a/go/vt/vtctl/grpcvtctldserver/testutil/test_tmclient.go +++ b/go/vt/vtctl/grpcvtctldserver/testutil/test_tmclient.go @@ -549,7 +549,7 @@ func (fake *TabletManagerClient) ChangeType(ctx context.Context, tablet *topodat } // DemotePrimary is part of the tmclient.TabletManagerClient interface. -func (fake *TabletManagerClient) DemotePrimary(ctx context.Context, tablet *topodatapb.Tablet) (*replicationdatapb.PrimaryStatus, error) { +func (fake *TabletManagerClient) DemotePrimary(ctx context.Context, tablet *topodatapb.Tablet, force bool) (*replicationdatapb.PrimaryStatus, error) { if fake.DemotePrimaryResults == nil { return nil, assert.AnError } diff --git a/go/vt/vtctl/reparentutil/emergency_reparenter.go b/go/vt/vtctl/reparentutil/emergency_reparenter.go index 513076b8f68..b953d632ff3 100644 --- a/go/vt/vtctl/reparentutil/emergency_reparenter.go +++ b/go/vt/vtctl/reparentutil/emergency_reparenter.go @@ -151,6 +151,12 @@ func (erp *EmergencyReparenter) reparentShardLocked(ctx context.Context, ev *eve var ( stoppedReplicationSnapshot *replicationSnapshot + + // replicasToRestart is the list of replicas that need replication to be restarted + // in the case of an error after their IO threads have been stopped, but before + // the ERS restarts them as part of a successful reparent. + replicasToRestart []*topodatapb.Tablet + shardInfo *topo.ShardInfo prevPrimary *topodatapb.Tablet tabletMap map[string]*topo.TabletInfo @@ -163,6 +169,32 @@ func (erp *EmergencyReparenter) reparentShardLocked(ctx context.Context, ev *eve isGTIDBased bool ) + defer func() { + // If we succeeded, or there are no replicas that need replication restarted, + // we can return early. + if err == nil || len(replicasToRestart) == 0 { + return + } + + // We create a new context with a fresh timeout so that the parent context does not cancel early while + // we attempt to restart replication on the stopped replicas. + ctx, cancel := context.WithTimeout(context.WithoutCancel(ctx), topo.RemoteOperationTimeout) + defer cancel() + + // Make sure we still have the shard lock. + if lockErr := topo.CheckShardLocked(ctx, keyspace, shard); lockErr != nil { + erp.logger.Warningf("skipping replication restart cleanup because the shard lock was lost for %s/%s: %v", keyspace, shard, lockErr) + return + } + + cleanupErr := erp.restartReplicationOnStoppedReplicas(ctx, prevPrimary, replicasToRestart, opts.durability) + if cleanupErr == nil { + return + } + + err = fmt.Errorf("%w, and restart replication cleanup failed: %v", err, cleanupErr) + }() + shardInfo, err = erp.ts.GetShard(ctx, keyspace, shard) if err != nil { return err @@ -206,7 +238,17 @@ func (erp *EmergencyReparenter) reparentShardLocked(ctx context.Context, ev *eve } // Stop replication on all the tablets and build their status map - stoppedReplicationSnapshot, err = stopReplicationAndBuildStatusMaps(ctx, erp.tmc, ev, tabletMap, topo.RemoteOperationTimeout, opts.IgnoreReplicas, opts.NewPrimaryAlias, opts.durability, opts.WaitAllTablets, erp.logger) + stoppedReplicationSnapshot, err = stopReplicationAndBuildStatusMaps(ctx, erp.tmc, ev, tabletMap, shardInfo.PrimaryAlias, topo.RemoteOperationTimeout, opts.IgnoreReplicas, opts.NewPrimaryAlias, opts.durability, opts.WaitAllTablets, erp.logger) + + // If stoppedReplicationSnapshot is not nil, it means we have stopped replication on at + // least one replica. We'll keep track of the replicas that had their IO threads stopped + // so we can restart them later in case of an error that causes us to return early and + // leaves replication stopped. We do this before checking the error so that we ensure we + // handle partial failures (where we've stopped some replicas but failed on others) correctly. + if stoppedReplicationSnapshot != nil { + replicasToRestart = stoppedReplicationSnapshot.replicasWithStoppedIO(tabletMap) + } + if err != nil { return vterrors.Wrapf(err, "failed to stop replication and build status maps: %v", err) } @@ -277,6 +319,10 @@ func (erp *EmergencyReparenter) reparentShardLocked(ctx context.Context, ev *eve return vterrors.Wrap(err, lostTopologyLockMsg) } + // Relay logs have been successfully applied and we're ready to start repointing replicas, + // so we no longer need to restart replication manually in the event of an error. + replicasToRestart = nil + // initialize the newPrimary with the intermediate source, override this value if it is not the ideal candidate newPrimary := intermediateSource if !isIdeal { @@ -328,6 +374,49 @@ func (erp *EmergencyReparenter) reparentShardLocked(ctx context.Context, ev *eve return err } +// restartReplicationOnStoppedReplicas restarts replication on replicas whose IO threads were +// stopped by ERS before the operation aborted. +func (erp *EmergencyReparenter) restartReplicationOnStoppedReplicas( + ctx context.Context, + prevPrimary *topodatapb.Tablet, + replicas []*topodatapb.Tablet, + durability policy.Durabler, +) error { + erp.logger.Infof("restarting replication on %d replicas whose IO threads were stopped by ERS", len(replicas)) + + rec := concurrency.AllErrorRecorder{} + wg := sync.WaitGroup{} + + // Start replication on each stopped replica concurrently. + for _, replica := range replicas { + alias := topoproto.TabletAliasString(replica.Alias) + + semiSync := false + if prevPrimary != nil { + semiSync = policy.IsReplicaSemiSync(durability, prevPrimary, replica) + } + + wg.Add(1) + go func() { + defer wg.Done() + + erp.logger.Infof("restarting replication on %q after failed ERS", alias) + if err := erp.tmc.StartReplication(ctx, replica, semiSync); err != nil { + err := vterrors.Wrapf(err, "failed to restart replication on %q after failed ERS", alias) + rec.RecordError(err) + } + }() + } + + wg.Wait() + + if rec.HasErrors() { + return rec.Error() + } + + return nil +} + func (erp *EmergencyReparenter) waitForAllRelayLogsToApply( ctx context.Context, validCandidates map[string]replication.Position, diff --git a/go/vt/vtctl/reparentutil/emergency_reparenter_test.go b/go/vt/vtctl/reparentutil/emergency_reparenter_test.go index 529c2a8f366..c483d35bfaa 100644 --- a/go/vt/vtctl/reparentutil/emergency_reparenter_test.go +++ b/go/vt/vtctl/reparentutil/emergency_reparenter_test.go @@ -18,7 +18,7 @@ package reparentutil import ( "context" - "fmt" + "errors" "slices" "testing" "time" @@ -1563,6 +1563,7 @@ func TestEmergencyReparenter_reparentShardLocked(t *testing.T) { Cell: "zone2", Uid: 100, }, + Type: topodatapb.TabletType_PRIMARY, Keyspace: "testkeyspace", Shard: "-", Hostname: "failed previous primary", @@ -1688,6 +1689,7 @@ func TestEmergencyReparenter_reparentShardLocked(t *testing.T) { Cell: "zone2", Uid: 100, }, + Type: topodatapb.TabletType_PRIMARY, Keyspace: "testkeyspace", Shard: "-", Hostname: "failed previous primary", @@ -2017,7 +2019,7 @@ func TestEmergencyReparenter_promotionOfNewPrimary(t *testing.T) { Error error }{ "zone1-0000000100": { - Error: fmt.Errorf("primary position error"), + Error: errors.New("primary position error"), }, }, }, @@ -3143,7 +3145,7 @@ func TestEmergencyReparenter_reparentReplicas(t *testing.T) { Error error }{ "zone1-0000000100": { - Error: fmt.Errorf("primary position error"), + Error: errors.New("primary position error"), }, }, }, @@ -3799,7 +3801,7 @@ func TestEmergencyReparenter_promoteIntermediateSource(t *testing.T) { "zone1-0000000100": nil, }, SetReplicationSourceResults: map[string]error{ - "zone1-0000000101": fmt.Errorf("An error"), + "zone1-0000000101": errors.New("An error"), }, }, newSourceTabletAlias: "zone1-0000000100", @@ -4615,7 +4617,7 @@ func getRelayLogPosition(gtidSets ...string) string { res += "," } first = false - res += fmt.Sprintf("%s:%s", uuids[idx], set) + res += uuids[idx] + ":" + set } return res } diff --git a/go/vt/vtctl/reparentutil/planned_reparenter.go b/go/vt/vtctl/reparentutil/planned_reparenter.go index dcd6dc7c590..52b51b52b8f 100644 --- a/go/vt/vtctl/reparentutil/planned_reparenter.go +++ b/go/vt/vtctl/reparentutil/planned_reparenter.go @@ -275,7 +275,7 @@ func (pr *PlannedReparenter) performGracefulPromotion( demoteCtx, demoteCancel := context.WithTimeout(ctx, topo.RemoteOperationTimeout) defer demoteCancel() - primaryStatus, err := pr.tmc.DemotePrimary(demoteCtx, currentPrimary.Tablet) + primaryStatus, err := pr.tmc.DemotePrimary(demoteCtx, currentPrimary.Tablet, false) if err != nil { return vterrors.Wrapf(err, "failed to DemotePrimary on current primary %v: %v", currentPrimary.AliasString(), err) } @@ -426,7 +426,7 @@ func (pr *PlannedReparenter) performPotentialPromotion( // tablet type), that's already in read-only. pr.logger.Infof("demoting tablet %v", alias) - primaryStatus, err := pr.tmc.DemotePrimary(stopAllCtx, tablet) + primaryStatus, err := pr.tmc.DemotePrimary(stopAllCtx, tablet, false) if err != nil { rec.RecordError(vterrors.Wrapf(err, "DemotePrimary(%v) failed on contested primary", alias)) diff --git a/go/vt/vtctl/reparentutil/policy/durability.go b/go/vt/vtctl/reparentutil/policy/durability.go index bad6846ef29..1ff88267fbf 100644 --- a/go/vt/vtctl/reparentutil/policy/durability.go +++ b/go/vt/vtctl/reparentutil/policy/durability.go @@ -91,6 +91,8 @@ type Durabler interface { SemiSyncAckers(*topodatapb.Tablet) int // IsReplicaSemiSync returns whether the "replica" should send semi-sync acks if "primary" were to become the PRIMARY instance IsReplicaSemiSync(primary, replica *topodatapb.Tablet) bool + // HasSemiSync returns whether the durability policy uses semi-sync. + HasSemiSync() bool } func RegisterDurability(name string, newDurablerFunc NewDurabler) { @@ -142,6 +144,11 @@ func IsReplicaSemiSync(durability Durabler, primary, replica *topodatapb.Tablet) return durability.IsReplicaSemiSync(primary, replica) } +// HasSemiSync returns true if the durability policy uses semi-sync. +func HasSemiSync(durability Durabler) bool { + return durability.HasSemiSync() +} + //======================================================================= // durabilityNone has no semi-sync and returns NeutralPromoteRule for Primary and Replica tablet types, MustNotPromoteRule for everything else @@ -166,6 +173,11 @@ func (d *durabilityNone) IsReplicaSemiSync(primary, replica *topodatapb.Tablet) return false } +// HasSemiSync implements the Durabler interface +func (d *durabilityNone) HasSemiSync() bool { + return false +} + //======================================================================= // durabilitySemiSync has 1 semi-sync setup. It only allows Primary and Replica type servers to acknowledge semi sync @@ -199,6 +211,11 @@ func (d *durabilitySemiSync) IsReplicaSemiSync(primary, replica *topodatapb.Tabl return false } +// HasSemiSync implements the Durabler interface +func (d *durabilitySemiSync) HasSemiSync() bool { + return true +} + //======================================================================= // durabilityCrossCell has 1 semi-sync setup. It only allows Primary and Replica type servers from a different cell to acknowledge semi sync. @@ -233,6 +250,11 @@ func (d *durabilityCrossCell) IsReplicaSemiSync(primary, replica *topodatapb.Tab return false } +// HasSemiSync implements the Durabler interface +func (d *durabilityCrossCell) HasSemiSync() bool { + return true +} + //======================================================================= // durabilityTest is like durabilityNone. It overrides the type for a specific tablet to prefer. It is only meant to be used for testing purposes! @@ -260,3 +282,8 @@ func (d *durabilityTest) SemiSyncAckers(tablet *topodatapb.Tablet) int { func (d *durabilityTest) IsReplicaSemiSync(primary, replica *topodatapb.Tablet) bool { return false } + +// HasSemiSync implements the Durabler interface +func (d *durabilityTest) HasSemiSync() bool { + return false +} diff --git a/go/vt/vtctl/reparentutil/policy/durability_test.go b/go/vt/vtctl/reparentutil/policy/durability_test.go index 441275f29bf..e3a4710b2d1 100644 --- a/go/vt/vtctl/reparentutil/policy/durability_test.go +++ b/go/vt/vtctl/reparentutil/policy/durability_test.go @@ -331,3 +331,10 @@ func TestDurabilityTest(t *testing.T) { }) } } + +func TestHasSemiSync(t *testing.T) { + require.False(t, HasSemiSync(&durabilityNone{})) + require.False(t, HasSemiSync(&durabilityTest{})) + require.True(t, HasSemiSync(&durabilitySemiSync{})) + require.True(t, HasSemiSync(&durabilityCrossCell{})) +} diff --git a/go/vt/vtctl/reparentutil/replication.go b/go/vt/vtctl/reparentutil/replication.go index 81211fac4cd..d2ef5576374 100644 --- a/go/vt/vtctl/reparentutil/replication.go +++ b/go/vt/vtctl/reparentutil/replication.go @@ -18,6 +18,7 @@ package reparentutil import ( "context" + "errors" "sync" "time" @@ -160,6 +161,64 @@ type replicationSnapshot struct { tabletsBackupState map[string]bool } +// replicasWithStoppedIO returns the reachable replicas whose IO threads ERS +// stopped and should restart during cleanup. +func (rs *replicationSnapshot) replicasWithStoppedIO(tabletMap map[string]*topo.TabletInfo) []*topodatapb.Tablet { + replicas := make([]*topodatapb.Tablet, 0, len(rs.statusMap)) + + for alias, stopStatus := range rs.statusMap { + ioThreadWasRunning, err := replicaIOThreadWasRunning(stopStatus) + if err != nil || !ioThreadWasRunning { + continue + } + + tabletInfo := tabletMap[alias] + if tabletInfo == nil || tabletInfo.Tablet == nil { + continue + } + + replicas = append(replicas, tabletInfo.Tablet) + } + + return replicas +} + +// replicaIOThreadWasRunning returns true if a StopReplicationStatus indicates +// that ERS stopped a healthy IO thread that should restart during cleanup. +func replicaIOThreadWasRunning(stopStatus *replicationdatapb.StopReplicationStatus) (bool, error) { + if stopStatus == nil || stopStatus.Before == nil { + return false, vterrors.Errorf(vtrpc.Code_INVALID_ARGUMENT, "could not determine Before state of StopReplicationStatus %v", stopStatus) + } + + replStatus := replication.ProtoToReplicationStatus(stopStatus.Before) + + return replStatus.IOHealthy(), nil +} + +// tabletAliasError wraps an error with the tablet alias that produced it. +type tabletAliasError struct { + alias *topodatapb.TabletAlias + err error +} + +// Error returns the wrapped error. +func (e *tabletAliasError) Error() string { + if e.err == nil { + return "" + } + return e.err.Error() +} + +// GetAlias returns the tablet alias that produced the error. +func (e *tabletAliasError) GetAlias() *topodatapb.TabletAlias { + return e.alias +} + +// Unwrap returns the underlying error. +func (e *tabletAliasError) Unwrap() error { + return e.err +} + // stopReplicationAndBuildStatusMaps stops replication on all replicas, then // collects and returns a mapping of TabletAlias (as string) to their current // replication positions. @@ -169,6 +228,7 @@ func stopReplicationAndBuildStatusMaps( tmc tmclient.TabletManagerClient, ev *events.Reparent, tabletMap map[string]*topo.TabletInfo, + primaryAlias *topodatapb.TabletAlias, stopReplicationTimeout time.Duration, ignoredTablets sets.Set[string], tabletToWaitFor *topodatapb.TabletAlias, @@ -197,7 +257,12 @@ func stopReplicationAndBuildStatusMaps( var concurrencyErr concurrency.Error var err error defer func() { - concurrencyErr.Err = err + if err != nil { + concurrencyErr.Err = &tabletAliasError{ + alias: tabletInfo.GetAlias(), + err: err, + } + } concurrencyErr.MustWaitFor = mustWaitForTablet errChan <- concurrencyErr }() @@ -210,7 +275,7 @@ func stopReplicationAndBuildStatusMaps( if isSQLErr && sqlErr != nil && sqlErr.Number() == sqlerror.ERNotReplica { var primaryStatus *replicationdatapb.PrimaryStatus - primaryStatus, err = tmc.DemotePrimary(groupCtx, tabletInfo.Tablet) + primaryStatus, err = tmc.DemotePrimary(groupCtx, tabletInfo.Tablet, true /* force */) if err != nil { msg := "replica %v thinks it's primary but we failed to demote it: %v" err = vterrors.Wrapf(err, msg, alias, err) @@ -288,15 +353,33 @@ func stopReplicationAndBuildStatusMaps( // even in case of multiple failures. We rely on the revoke function below to determine if we have more failures than we can tolerate NumErrorsToWaitFor: numErrorsToWaitFor, } - errRecorder := errgroup.Wait(groupCancel, errChan) - if len(errRecorder.Errors) <= 1 { + + // Exit early if we encountered no errors. + if len(errRecorder.Errors) == 0 { return res, nil } + + // If there are recorded errors, confirm there is a single error from the PRIMARY. + // We intentionally do not check for specific error types here because the nature + // of ERS means we expect any number of possible errors from the PRIMARY we are + // abandoning (e.g. connection refused, context deadline, MySQL down, etc.) and + // we don't need to handle them differently — the goal is simply to confirm the + // error came from the PRIMARY tablet, not to diagnose why it failed. + if primaryAlias != nil && len(errRecorder.Errors) == 1 { + var tabletErr *tabletAliasError + if errors.As(errRecorder.Errors[0], &tabletErr) { + // Failure to reach the PRIMARY tablet is expected, return early. + if topoproto.TabletAliasEqual(primaryAlias, tabletErr.GetAlias()) { + return res, nil + } + } + } + // check that the tablets we were able to reach are sufficient for us to guarantee that no new write will be accepted by any tablet revokeSuccessful := haveRevoked(durability, res.reachableTablets, allTablets) if !revokeSuccessful { - return nil, vterrors.Wrapf(errRecorder.Error(), "could not reach sufficient tablets to guarantee safety: %v", errRecorder.Error()) + return res, vterrors.Wrapf(errRecorder.Error(), "could not reach sufficient tablets to guarantee safety: %v", errRecorder.Error()) } return res, nil diff --git a/go/vt/vtctl/reparentutil/replication_test.go b/go/vt/vtctl/reparentutil/replication_test.go index 3d124b7495b..136cd8f8a82 100644 --- a/go/vt/vtctl/reparentutil/replication_test.go +++ b/go/vt/vtctl/reparentutil/replication_test.go @@ -225,7 +225,7 @@ type stopReplicationAndBuildStatusMapsTestTMClient struct { stopReplicationAndGetStatusDelays map[string]time.Duration } -func (fake *stopReplicationAndBuildStatusMapsTestTMClient) DemotePrimary(ctx context.Context, tablet *topodatapb.Tablet) (*replicationdatapb.PrimaryStatus, error) { +func (fake *stopReplicationAndBuildStatusMapsTestTMClient) DemotePrimary(ctx context.Context, tablet *topodatapb.Tablet, force bool) (*replicationdatapb.PrimaryStatus, error) { if tablet.Alias == nil { return nil, assert.AnError } @@ -277,6 +277,7 @@ func Test_stopReplicationAndBuildStatusMaps(t *testing.T) { durability string tmc *stopReplicationAndBuildStatusMapsTestTMClient tabletMap map[string]*topo.TabletInfo + primaryAlias *topodatapb.TabletAlias stopReplicasTimeout time.Duration ignoredTablets sets.Set[string] tabletToWaitFor *topodatapb.TabletAlias @@ -427,8 +428,9 @@ func Test_stopReplicationAndBuildStatusMaps(t *testing.T) { }}, waitForAllTablets: true, shouldErr: false, - }, { - name: "timing check with wait for all tablets", + }, + { + name: "primary timeout with wait for all tablets", durability: policy.DurabilityNone, tmc: &stopReplicationAndBuildStatusMapsTestTMClient{ stopReplicationAndGetStatusResults: map[string]*struct { @@ -476,7 +478,7 @@ func Test_stopReplicationAndBuildStatusMaps(t *testing.T) { }, }, "zone1-0000000102": { Tablet: &topodatapb.Tablet{ - Type: topodatapb.TabletType_REPLICA, + Type: topodatapb.TabletType_PRIMARY, Alias: &topodatapb.TabletAlias{ Cell: "zone1", Uid: 102, @@ -484,6 +486,10 @@ func Test_stopReplicationAndBuildStatusMaps(t *testing.T) { }, }, }, + primaryAlias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 102, + }, ignoredTablets: sets.New[string](), expectedStatusMap: map[string]*replicationdatapb.StopReplicationStatus{ "zone1-0000000100": { @@ -812,6 +818,10 @@ func Test_stopReplicationAndBuildStatusMaps(t *testing.T) { }, }, }, + primaryAlias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 100, + }, ignoredTablets: sets.New[string](), expectedStatusMap: map[string]*replicationdatapb.StopReplicationStatus{ "zone1-0000000101": { @@ -887,6 +897,10 @@ func Test_stopReplicationAndBuildStatusMaps(t *testing.T) { }, }, }, + primaryAlias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 100, + }, ignoredTablets: sets.New[string](), expectedStatusMap: map[string]*replicationdatapb.StopReplicationStatus{ "zone1-0000000101": { @@ -952,6 +966,10 @@ func Test_stopReplicationAndBuildStatusMaps(t *testing.T) { }, }, }, + primaryAlias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 100, + }, ignoredTablets: sets.New[string](), expectedStatusMap: nil, expectedPrimaryStatusMap: nil, @@ -959,7 +977,7 @@ func Test_stopReplicationAndBuildStatusMaps(t *testing.T) { shouldErr: true, // we get multiple errors, so we fail }, { - name: "stopReplicasTimeout exceeded", + name: "primary timeout exceeds stopReplicasTimeout", durability: policy.DurabilityNone, tmc: &stopReplicationAndBuildStatusMapsTestTMClient{ stopReplicationAndGetStatusDelays: map[string]time.Duration{ @@ -986,7 +1004,7 @@ func Test_stopReplicationAndBuildStatusMaps(t *testing.T) { tabletMap: map[string]*topo.TabletInfo{ "zone1-0000000100": { Tablet: &topodatapb.Tablet{ - Type: topodatapb.TabletType_REPLICA, + Type: topodatapb.TabletType_PRIMARY, Alias: &topodatapb.TabletAlias{ Cell: "zone1", Uid: 100, @@ -1003,6 +1021,10 @@ func Test_stopReplicationAndBuildStatusMaps(t *testing.T) { }, }, }, + primaryAlias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 100, + }, stopReplicasTimeout: time.Millisecond * 5, ignoredTablets: sets.New[string](), expectedStatusMap: map[string]*replicationdatapb.StopReplicationStatus{ @@ -1023,7 +1045,7 @@ func Test_stopReplicationAndBuildStatusMaps(t *testing.T) { shouldErr: false, }, { - name: "one tablet fails to StopReplication", + name: "replica failure to StopReplication returns an error", durability: policy.DurabilityNone, tmc: &stopReplicationAndBuildStatusMapsTestTMClient{ stopReplicationAndGetStatusResults: map[string]*struct { @@ -1077,7 +1099,59 @@ func Test_stopReplicationAndBuildStatusMaps(t *testing.T) { Uid: 101, }, }}, - shouldErr: false, + shouldErr: true, + }, + { + // A single replica fails StopReplication, but primaryAlias points to a + // *different* tablet (the actual primary). The error doesn't match the + // primary alias, so we fall through to haveRevoked, which fails because + // the primary itself was not reached. + name: "single replica failure with primaryAlias set does not suppress error", + durability: policy.DurabilityNone, + tmc: &stopReplicationAndBuildStatusMapsTestTMClient{ + stopReplicationAndGetStatusResults: map[string]*struct { + StopStatus *replicationdatapb.StopReplicationStatus + Err error + }{ + "zone1-0000000100": { // replica fails + Err: assert.AnError, + }, + "zone1-0000000101": { // primary succeeds + StopStatus: &replicationdatapb.StopReplicationStatus{ + Before: &replicationdatapb.Status{Position: "MySQL56/3E11FA47-71CA-11E1-9E33-C80AA9429101:1-5", IoState: int32(replication.ReplicationStateRunning), SqlState: int32(replication.ReplicationStateRunning)}, + After: &replicationdatapb.Status{Position: "MySQL56/3E11FA47-71CA-11E1-9E33-C80AA9429101:1-9"}, + }, + }, + }, + }, + tabletMap: map[string]*topo.TabletInfo{ + "zone1-0000000100": { + Tablet: &topodatapb.Tablet{ + Type: topodatapb.TabletType_REPLICA, + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 100, + }, + }, + }, + "zone1-0000000101": { + Tablet: &topodatapb.Tablet{ + Type: topodatapb.TabletType_PRIMARY, + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 101, + }, + }, + }, + }, + // primaryAlias points to zone1-0000000101 (the primary), but the error + // came from zone1-0000000100 (a replica) — alias mismatch should not suppress. + primaryAlias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 101, + }, + ignoredTablets: sets.New[string](), + shouldErr: true, }, { name: "multiple tablets fail StopReplication", @@ -1300,7 +1374,7 @@ func Test_stopReplicationAndBuildStatusMaps(t *testing.T) { durability, err := policy.GetDurabilityPolicy(tt.durability) require.NoError(t, err) startTime := time.Now() - res, err := stopReplicationAndBuildStatusMaps(ctx, tt.tmc, &events.Reparent{}, tt.tabletMap, tt.stopReplicasTimeout, tt.ignoredTablets, tt.tabletToWaitFor, durability, tt.waitForAllTablets, logger) + res, err := stopReplicationAndBuildStatusMaps(ctx, tt.tmc, &events.Reparent{}, tt.tabletMap, tt.primaryAlias, tt.stopReplicasTimeout, tt.ignoredTablets, tt.tabletToWaitFor, durability, tt.waitForAllTablets, logger) totalTimeSpent := time.Since(startTime) if tt.timeSpent != 0 { assert.Greater(t, totalTimeSpent, tt.timeSpent) @@ -1408,6 +1482,97 @@ func TestReplicaWasRunning(t *testing.T) { } } +func TestReplicaIOThreadWasRunning(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + in *replicationdatapb.StopReplicationStatus + expected bool + shouldErr bool + }{ + { + name: "io thread running", + in: &replicationdatapb.StopReplicationStatus{ + Before: &replicationdatapb.Status{ + IoState: int32(replication.ReplicationStateRunning), + SqlState: int32(replication.ReplicationStateStopped), + }, + }, + expected: true, + }, + { + name: "io thread connecting without an io error", + in: &replicationdatapb.StopReplicationStatus{ + Before: &replicationdatapb.Status{ + IoState: int32(replication.ReplicationStateConnecting), + LastIoError: "", + SqlState: int32(replication.ReplicationStateStopped), + }, + }, + expected: true, + }, + { + name: "io thread connecting with an io error", + in: &replicationdatapb.StopReplicationStatus{ + Before: &replicationdatapb.Status{ + IoState: int32(replication.ReplicationStateConnecting), + LastIoError: "dial tcp 127.0.0.1:3306: connect: connection refused", + SqlState: int32(replication.ReplicationStateStopped), + }, + }, + expected: false, + }, + { + name: "only sql thread running", + in: &replicationdatapb.StopReplicationStatus{ + Before: &replicationdatapb.Status{ + IoState: int32(replication.ReplicationStateStopped), + SqlState: int32(replication.ReplicationStateRunning), + }, + }, + expected: false, + }, + { + name: "no replication threads running", + in: &replicationdatapb.StopReplicationStatus{ + Before: &replicationdatapb.Status{ + IoState: int32(replication.ReplicationStateStopped), + SqlState: int32(replication.ReplicationStateStopped), + }, + }, + expected: false, + }, + { + name: "passing nil pointer results in an error", + in: nil, + shouldErr: true, + }, + { + name: "status.Before is nil results in an error", + in: &replicationdatapb.StopReplicationStatus{ + Before: nil, + }, + shouldErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + actual, err := replicaIOThreadWasRunning(tt.in) + if tt.shouldErr { + require.Error(t, err) + return + } + + require.NoError(t, err) + require.Equal(t, tt.expected, actual) + }) + } +} + // waitForRelayLogsToApplyTestTMClient implements just the WaitForPosition // method of the tmclient.TabletManagerClient interface for // TestWaitForRelayLogsToApply, with the necessary trackers to facilitate diff --git a/go/vt/vtctl/workflow/framework_test.go b/go/vt/vtctl/workflow/framework_test.go index 0575965c433..a5f3f8b5410 100644 --- a/go/vt/vtctl/workflow/framework_test.go +++ b/go/vt/vtctl/workflow/framework_test.go @@ -72,9 +72,11 @@ type testKeyspace struct { } type queryResult struct { - query string - result *querypb.QueryResult - err error + query string + result *querypb.QueryResult + err error + beforeReturnHook func(context.Context, *topodatapb.Tablet, string) + returnContextErr bool } func TestMain(m *testing.M) { @@ -493,7 +495,16 @@ func (tmc *testTMClient) VReplicationExec(ctx context.Context, tablet *topodatap if !matched { return nil, fmt.Errorf("tablet %v:\nunexpected query\n%s\nwant:\n%s", tablet, query, qrs[0].query) } + if qrs[0].beforeReturnHook != nil { + qrs[0].beforeReturnHook(ctx, tablet, query) + } tmc.vrQueries[int(tablet.Alias.Uid)] = qrs[1:] + if qrs[0].returnContextErr && ctx.Err() != nil { + return nil, ctx.Err() + } + if strings.Contains(query, "set message = 'FROZEN'") { + tmc.frozen.Store(true) + } return qrs[0].result, qrs[0].err } diff --git a/go/vt/vtctl/workflow/materializer_test.go b/go/vt/vtctl/workflow/materializer_test.go index c28beb933e8..e16a6ab2515 100644 --- a/go/vt/vtctl/workflow/materializer_test.go +++ b/go/vt/vtctl/workflow/materializer_test.go @@ -20,6 +20,7 @@ import ( "context" "errors" "fmt" + "path" "slices" "strings" "testing" @@ -1014,6 +1015,210 @@ func TestMoveTablesNoRoutingRules(t *testing.T) { require.Zerof(t, len(rr.Rules), "routing rules should be empty, found %+v", rr.Rules) } +func TestMoveTablesCreateShardedVSchemaRollback(t *testing.T) { + ms := &vtctldatapb.MaterializeSettings{ + Workflow: "workflow", + SourceKeyspace: "sourceks", + TargetKeyspace: "targetks", + TableSettings: []*vtctldatapb.TableMaterializeSettings{{ + TargetTable: "t1", + SourceExpression: "select * from t1", + }}, + } + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + env := newTestMaterializerEnv(t, ctx, ms, []string{"-"}, []string{"-"}) + defer env.close() + + targetVSchema := &vschemapb.Keyspace{ + Sharded: true, + Vindexes: map[string]*vschemapb.Vindex{ + "hash": { + Type: "hash", + }, + }, + Tables: map[string]*vschemapb.Table{ + "t1": { + ColumnVindexes: []*vschemapb.ColumnVindex{{ + Name: "hash", + Column: "id", + }}, + }, + }, + } + err := env.ws.ts.SaveVSchema(ctx, &topo.KeyspaceVSchemaInfo{ + Name: ms.TargetKeyspace, + Keyspace: targetVSchema, + }) + require.NoError(t, err) + + env.tmc.expectFetchAsAllPrivsQuery(startingTargetTabletUID, getNonEmptyTable, &sqltypes.Result{}) + + sourceDeleteQuery := fmt.Sprintf(sqlDeleteWorkflow, encodeString("vt_sourceks"), encodeString(ReverseWorkflowName(ms.Workflow))) + targetDeleteQuery := fmt.Sprintf(sqlDeleteWorkflow, encodeString("vt_targetks"), encodeString(ms.Workflow)) + env.tmc.expectVRQuery(startingSourceTabletUID, sourceDeleteQuery, &sqltypes.Result{}) + env.tmc.expectVRQuery(startingTargetTabletUID, targetDeleteQuery, &sqltypes.Result{}) + + readCalls := 0 + env.tmc.readVReplicationWorkflow = func(ctx context.Context, tablet *topodatapb.Tablet, request *tabletmanagerdatapb.ReadVReplicationWorkflowRequest) (*tabletmanagerdatapb.ReadVReplicationWorkflowResponse, error) { + readCalls++ + if readCalls == 1 { + return &tabletmanagerdatapb.ReadVReplicationWorkflowResponse{ + Workflow: request.Workflow, + WorkflowType: binlogdatapb.VReplicationWorkflowType_MoveTables, + Streams: []*tabletmanagerdatapb.ReadVReplicationWorkflowResponse_Stream{ + { + Id: 1, + Bls: &binlogdatapb.BinlogSource{ + Keyspace: ms.SourceKeyspace, + Shard: "-", + Filter: &binlogdatapb.Filter{ + Rules: []*binlogdatapb.Rule{{ + Match: "t1", + Filter: "select * from t1", + }}, + }, + }, + }, + }, + }, nil + } + return nil, errors.New("read vreplication failed") + } + + _, err = env.ws.MoveTablesCreate(ctx, &vtctldatapb.MoveTablesCreateRequest{ + Workflow: ms.Workflow, + SourceKeyspace: ms.SourceKeyspace, + TargetKeyspace: ms.TargetKeyspace, + IncludeTables: []string{"t1"}, + }) + require.ErrorContains(t, err, "read vreplication failed") + + got, err := env.ws.ts.GetVSchema(ctx, ms.TargetKeyspace) + require.NoError(t, err) + require.True(t, proto.Equal(got.Keyspace, targetVSchema), "got: %v, want: %v", got.Keyspace, targetVSchema) +} + +func TestMoveTablesCreateUnshardedVSchemaRollback(t *testing.T) { + ms := &vtctldatapb.MaterializeSettings{ + Workflow: "workflow", + SourceKeyspace: "sourceks", + TargetKeyspace: "targetks", + TableSettings: []*vtctldatapb.TableMaterializeSettings{{ + TargetTable: "t1", + SourceExpression: "select * from t1", + }}, + } + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + env := newTestMaterializerEnv(t, ctx, ms, []string{"-"}, []string{"-"}) + defer env.close() + + originalVSchema := &vschemapb.Keyspace{ + Tables: map[string]*vschemapb.Table{ + "t0": {}, + }, + } + err := env.ws.ts.SaveVSchema(ctx, &topo.KeyspaceVSchemaInfo{ + Name: ms.TargetKeyspace, + Keyspace: originalVSchema, + }) + require.NoError(t, err) + + env.tmc.expectFetchAsAllPrivsQuery(startingTargetTabletUID, getNonEmptyTable, &sqltypes.Result{}) + + sourceDeleteQuery := fmt.Sprintf(sqlDeleteWorkflow, encodeString("vt_sourceks"), encodeString(ReverseWorkflowName(ms.Workflow))) + targetDeleteQuery := fmt.Sprintf(sqlDeleteWorkflow, encodeString("vt_targetks"), encodeString(ms.Workflow)) + env.tmc.expectVRQuery(startingSourceTabletUID, sourceDeleteQuery, &sqltypes.Result{}) + env.tmc.expectVRQuery(startingTargetTabletUID, targetDeleteQuery, &sqltypes.Result{}) + + conn, err := env.ws.ts.ConnForCell(ctx, topo.GlobalCell) + require.NoError(t, err) + current, changes, err := conn.Watch(ctx, path.Join(topo.KeyspacesPath, ms.TargetKeyspace, topo.VSchemaFile)) + require.NoError(t, err) + initialVersion := "" + if current != nil && current.Version != nil { + initialVersion = current.Version.String() + } + + failCh := make(chan struct{}) + readCalls := 0 + env.tmc.readVReplicationWorkflow = func(ctx context.Context, tablet *topodatapb.Tablet, request *tabletmanagerdatapb.ReadVReplicationWorkflowRequest) (*tabletmanagerdatapb.ReadVReplicationWorkflowResponse, error) { + readCalls++ + if readCalls == 1 { + return &tabletmanagerdatapb.ReadVReplicationWorkflowResponse{ + Workflow: request.Workflow, + WorkflowType: binlogdatapb.VReplicationWorkflowType_MoveTables, + Streams: []*tabletmanagerdatapb.ReadVReplicationWorkflowResponse_Stream{ + { + Id: 1, + Bls: &binlogdatapb.BinlogSource{ + Keyspace: ms.SourceKeyspace, + Shard: "-", + Filter: &binlogdatapb.Filter{ + Rules: []*binlogdatapb.Rule{{ + Match: "t1", + Filter: "select * from t1", + }}, + }, + }, + }, + }, + }, nil + } + <-failCh + return nil, errors.New("read vreplication failed") + } + + errCh := make(chan error, 1) + go func() { + _, err := env.ws.MoveTablesCreate(ctx, &vtctldatapb.MoveTablesCreateRequest{ + Workflow: ms.Workflow, + SourceKeyspace: ms.SourceKeyspace, + TargetKeyspace: ms.TargetKeyspace, + IncludeTables: []string{"t1"}, + }) + errCh <- err + }() + + updatedVersion := "" + assert.Eventually(t, func() bool { + select { + case wd := <-changes: + if wd == nil || wd.Err != nil || wd.Contents == nil { + return false + } + ks := &vschemapb.Keyspace{} + if err := ks.UnmarshalVT(wd.Contents); err != nil { + return false + } + if ks.Tables["t1"] == nil { + return false + } + if wd.Version != nil { + updatedVersion = wd.Version.String() + } + return true + default: + return false + } + }, 5*time.Second, 50*time.Millisecond) + require.NotEmpty(t, updatedVersion) + if initialVersion != "" { + require.NotEqual(t, initialVersion, updatedVersion) + } + + close(failCh) + err = <-errCh + require.ErrorContains(t, err, "read vreplication failed") + + got, err := env.ws.ts.GetVSchema(ctx, ms.TargetKeyspace) + require.NoError(t, err) + require.True(t, proto.Equal(got.Keyspace, originalVSchema), "got: %v, want: %v", got.Keyspace, originalVSchema) +} + func TestCreateLookupVindexFull(t *testing.T) { ms := &vtctldatapb.MaterializeSettings{ Workflow: "lookup", diff --git a/go/vt/vtctl/workflow/sequences.go b/go/vt/vtctl/workflow/sequences.go index 5c1e2ca7fa6..e1a13b96b72 100644 --- a/go/vt/vtctl/workflow/sequences.go +++ b/go/vt/vtctl/workflow/sequences.go @@ -166,18 +166,21 @@ func (ts *trafficSwitcher) getMaxSequenceValue(ctx context.Context, seq *sequenc Query: []byte(query.Query), MaxRows: 1, }) - if terr != nil || len(qr.Rows) != 1 { + if terr != nil { return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "failed to get the max used sequence value for target table %s.%s on tablet %s in order to initialize the backing sequence table: %v", ts.targetKeyspace, seq.usingTableName, topoproto.TabletAliasString(primary.Alias), terr) } - rawVal := sqltypes.Proto3ToResult(qr).Rows[0][0] maxID := int64(0) - if !rawVal.IsNull() { // If it's NULL then there are no rows and 0 remains the max - maxID, terr = rawVal.ToInt64() - if terr != nil { - return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "failed to get the max used sequence value for target table %s.%s on tablet %s in order to initialize the backing sequence table: %v", - ts.targetKeyspace, seq.usingTableName, topoproto.TabletAliasString(primary.Alias), terr) + // If no rows are returned, max remains 0. + if len(qr.Rows) != 0 { + rawVal := sqltypes.Proto3ToResult(qr).Rows[0][0] + if !rawVal.IsNull() { // If it's NULL then 0 remains the max + maxID, terr = rawVal.ToInt64() + if terr != nil { + return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "failed to get the max used sequence value for target table %s.%s on tablet %s in order to initialize the backing sequence table: %v", + ts.targetKeyspace, seq.usingTableName, topoproto.TabletAliasString(primary.Alias), terr) + } } } setMaxSequenceValue(maxID) @@ -352,9 +355,6 @@ func (ts *trafficSwitcher) initializeTargetSequences(ctx context.Context, sequen } for _, sm := range sequencesByBackingTable { maxValue := maxValues[sm.backingTableName] - if maxValue == 0 { - continue - } if err := ts.updateSequenceValue(ctx, sm, maxValue); err != nil { return err } diff --git a/go/vt/vtctl/workflow/sequences_test.go b/go/vt/vtctl/workflow/sequences_test.go index 61b020c1e2a..3822e2822a3 100644 --- a/go/vt/vtctl/workflow/sequences_test.go +++ b/go/vt/vtctl/workflow/sequences_test.go @@ -28,12 +28,13 @@ import ( "vitess.io/vitess/go/sqlescape" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/mysqlctl/tmutils" - tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" "vitess.io/vitess/go/vt/proto/vschema" - vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/vttablet/tabletmanager/vreplication" + + tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" + vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" ) func TestInitializeTargetSequences(t *testing.T) { @@ -89,16 +90,48 @@ func TestInitializeTargetSequences(t *testing.T) { }, } - env.tmc.expectVRQuery(200, "/select max.*", sqltypes.MakeTestResult(sqltypes.MakeTestFields("maxval", "int64"), "34")) - // Expect the insert query to be executed with 35 as a params, since we provide a maxID of 34 in the last query - env.tmc.expectVRQuery(100, "/insert into.*35.*", &sqltypes.Result{RowsAffected: 1}) + type testCase struct { + name string + selectMaxQuery string + selectMaxResult *sqltypes.Result + insertQuery string + } - err = sw.initializeTargetSequences(ctx, sequencesByBackingTable) - assert.NoError(t, err) + testCases := []testCase{ + { + name: "initialize sequences", + selectMaxQuery: "/select max.*", + selectMaxResult: sqltypes.MakeTestResult( + sqltypes.MakeTestFields("maxval", "int64"), + "34", + ), + insertQuery: "/insert into.*35.*", + }, + { + name: "initialize sequences for empty tables", + selectMaxQuery: "/select max.*", + selectMaxResult: sqltypes.MakeTestResult( + sqltypes.MakeTestFields("maxval", "int64"), + ), + insertQuery: "/insert into.*1.*", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // Expect the select max query to be executed + env.tmc.expectVRQuery(200, tc.selectMaxQuery, tc.selectMaxResult) + // Expect the insert query to be executed + env.tmc.expectVRQuery(100, tc.insertQuery, &sqltypes.Result{RowsAffected: 1}) + + err = sw.initializeTargetSequences(ctx, sequencesByBackingTable) + assert.NoError(t, err) - // Expect the queries to be cleared - assert.Emptyf(t, env.tmc.vrQueries[100], "expected no queries to be executed, found: %q", env.tmc.vrQueries[100]) - assert.Empty(t, env.tmc.vrQueries[200], "expected no queries to be executed, found: %q", env.tmc.vrQueries[200]) + // Expect the queries to be cleared + assert.Emptyf(t, env.tmc.vrQueries[100], "expected no queries to be executed, found: %q", env.tmc.vrQueries[100]) + assert.Empty(t, env.tmc.vrQueries[200], "expected no queries to be executed, found: %q", env.tmc.vrQueries[200]) + }) + } } func TestGetTargetSequenceMetadata(t *testing.T) { diff --git a/go/vt/vtctl/workflow/server.go b/go/vt/vtctl/workflow/server.go index e37a6bf1504..511bce8c269 100644 --- a/go/vt/vtctl/workflow/server.go +++ b/go/vt/vtctl/workflow/server.go @@ -535,6 +535,17 @@ func (s *Server) getWorkflowState(ctx context.Context, targetKeyspace, workflowN return ts, state, nil } +func validateMoveTablesSourceKeyspace(ts *trafficSwitcher) error { + if ts.workflowType == binlogdatapb.VReplicationWorkflowType_MoveTables && + ts.externalCluster == "" && + ts.sourceKeyspace == ts.targetKeyspace { + return vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, + "workflow %s.%s is invalid: MoveTables source keyspace matches target keyspace (%s)", + ts.targetKeyspace, ts.workflow, ts.targetKeyspace) + } + return nil +} + // LookupVindexComplete checks if the lookup vindex has been externalized, // and if the vindex has an owner, it deletes the workflow. func (s *Server) LookupVindexComplete(ctx context.Context, req *vtctldatapb.LookupVindexCompleteRequest) (*vtctldatapb.LookupVindexCompleteResponse, error) { @@ -897,9 +908,7 @@ func (s *Server) moveTablesCreate(ctx context.Context, req *vtctldatapb.MoveTabl s.Logger().Infof("Successfully opened external topo: %+v", externalTopo) } - origVSchema := &topo.KeyspaceVSchemaInfo{ // If we need to rollback a failed create - Name: targetKeyspace, - } + var origVSchema *topo.KeyspaceVSchemaInfo // If we need to rollback a failed create vschema, err := s.ts.GetVSchema(ctx, targetKeyspace) if err != nil { return nil, err @@ -957,9 +966,11 @@ func (s *Server) moveTablesCreate(ctx context.Context, req *vtctldatapb.MoveTabl if !vschema.Sharded { // Save the original in case we need to restore it for a late failure in // the defer(). We do NOT want to clone the version field as we will - // intentionally be going back in time. So we only clone the internal - // vschemapb.Keyspace field. - origVSchema.Keyspace = vschema.Keyspace.CloneVT() + // intentionally be going back in time. + origVSchema = &topo.KeyspaceVSchemaInfo{ + Name: targetKeyspace, + Keyspace: vschema.Keyspace.CloneVT(), + } if err := s.addTablesToVSchema(ctx, sourceKeyspace, vschema.Keyspace, tables, externalTopo == nil); err != nil { return nil, err } @@ -1061,7 +1072,8 @@ func (s *Server) moveTablesCreate(ctx context.Context, req *vtctldatapb.MoveTabl if cerr := s.dropArtifacts(ctx, false, &switcher{s: s, ts: ts}); cerr != nil { err = vterrors.Wrapf(err, "failed to cleanup workflow artifacts: %v", cerr) } - if origVSchema == nil { // There's no previous version to restore + if vschema.Sharded || origVSchema == nil { + // We don't modify the vschema for sharded keyspaces, so there's nothing to restore. return } if cerr := s.ts.SaveVSchema(ctx, origVSchema); cerr != nil { @@ -2546,6 +2558,9 @@ func (s *Server) WorkflowSwitchTraffic(ctx context.Context, req *vtctldatapb.Wor if err != nil { return nil, err } + if err := validateMoveTablesSourceKeyspace(ts); err != nil { + return nil, err + } if startState.WorkflowType == TypeMigrate { return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "invalid action for Migrate workflow: SwitchTraffic") @@ -2892,9 +2907,14 @@ func (s *Server) switchWrites(ctx context.Context, req *vtctldatapb.WorkflowSwit // We need to hold the keyspace locks longer than waitTimeout*X -- where X // is the number of sub-steps where the waitTimeout value is used: stopping - // existing streams, waiting for replication to catch up, and initializing - // the target sequences -- to be sure the lock is not lost. - ksLockTTL := waitTimeout * 3 + // existing streams, waiting for replication to catch up, initializing the + // target sequences, and completing the detached post-journal tail -- to be + // sure the lock is not lost. + postJournalTimeout := max(waitTimeout, 30*time.Second) + ksLockTTL := waitTimeout*3 + postJournalTimeout + startPostJournalCtx := func(ctx context.Context) (context.Context, context.CancelFunc) { + return context.WithTimeout(context.WithoutCancel(ctx), postJournalTimeout) + } // Need to lock both source and target keyspaces. ctx, sourceUnlock, lockErr := sw.lockKeyspace(ctx, ts.SourceKeyspaceName(), "SwitchWrites", topo.WithTTL(ksLockTTL)) @@ -3082,21 +3102,30 @@ func (s *Server) switchWrites(ctx context.Context, req *vtctldatapb.WorkflowSwit return handleError(fmt.Sprintf("failed to initialize the sequences used in the %s keyspace", ts.TargetKeyspaceName()), err) } } + + // This is the point of no return. Once a journal is created, + // traffic can be redirected to target shards. + if err := confirmKeyspaceLocksHeld(); err != nil { + return handleError("locks were lost", err) + } + postJournalCtx, postJournalCancel := startPostJournalCtx(ctx) + defer postJournalCancel() + ctx = postJournalCtx } else { if cancel { return handleError("invalid cancel", vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "traffic switching has reached the point of no return, cannot cancel")) } + postJournalCtx, postJournalCancel := startPostJournalCtx(ctx) + defer postJournalCancel() + ctx = postJournalCtx ts.Logger().Infof("Journals were found. Completing the left over steps.") // Need to gather positions in case all journals were not created. if err := ts.gatherPositions(ctx); err != nil { return handleError("failed to gather replication positions", err) } - } - - // This is the point of no return. Once a journal is created, - // traffic can be redirected to target shards. - if err := confirmKeyspaceLocksHeld(); err != nil { - return handleError("locks were lost", err) + if err := confirmKeyspaceLocksHeld(); err != nil { + return handleError("locks were lost", err) + } } if err := sw.createJournals(ctx, sourceWorkflows); err != nil { return handleError("failed to create the journal", err) diff --git a/go/vt/vtctl/workflow/server_test.go b/go/vt/vtctl/workflow/server_test.go index a836df13123..855a4c46640 100644 --- a/go/vt/vtctl/workflow/server_test.go +++ b/go/vt/vtctl/workflow/server_test.go @@ -1608,6 +1608,164 @@ func TestMoveTablesTrafficSwitching(t *testing.T) { } } +func TestMoveTablesSwitchWritesCompletesAfterCancelOnFreeze(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + const ( + workflowName = "wf1" + tableName = "t1" + sourceKeyspaceName = "sourceks" + targetKeyspaceName = "targetks" + ) + + env := newTestEnv(t, ctx, defaultCellName, &testKeyspace{ + KeyspaceName: sourceKeyspaceName, + ShardNames: []string{"0"}, + }, &testKeyspace{ + KeyspaceName: targetKeyspaceName, + ShardNames: []string{"0"}, + }) + defer env.close() + + env.tmc.schema = map[string]*tabletmanagerdatapb.SchemaDefinition{ + tableName: { + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{{ + Name: tableName, + Schema: fmt.Sprintf("CREATE TABLE %s (id BIGINT, name VARCHAR(64), PRIMARY KEY (id))", tableName), + }}, + }, + } + + journalQR := &queryResult{ + query: "/select val from _vt.resharding_journal.*", + result: &querypb.QueryResult{}, + } + lockTableQR := &queryResult{ + query: fmt.Sprintf("LOCK TABLES `%s` READ", tableName), + result: &querypb.QueryResult{}, + } + cutoverQR := &queryResult{ + query: "/update _vt.vreplication set state='Stopped', message='stopped for cutover' where id=.*", + result: &querypb.QueryResult{}, + } + deleteReverseWFQR := &queryResult{ + query: fmt.Sprintf("delete from _vt.vreplication where db_name = 'vt_%s' and workflow = '%s'", sourceKeyspaceName, ReverseWorkflowName(workflowName)), + result: &querypb.QueryResult{}, + } + createReverseWFQR := &queryResult{ + query: "/insert into _vt.vreplication.*_reverse.*", + result: &querypb.QueryResult{}, + } + createJournalQR := &queryResult{ + query: "/insert into _vt.resharding_journal.*", + result: &querypb.QueryResult{}, + } + freezeWFQR := &queryResult{ + query: fmt.Sprintf("update _vt.vreplication set message = 'FROZEN' where db_name='vt_%s' and workflow='%s'", targetKeyspaceName, workflowName), + beforeReturnHook: func(context.Context, *topodatapb.Tablet, string) { + cancel() + }, + returnContextErr: true, + } + + env.tmc.expectVRQueryResultOnKeyspaceTablets(targetKeyspaceName, cutoverQR) + env.tmc.expectVRQueryResultOnKeyspaceTablets(sourceKeyspaceName, journalQR) + env.tmc.expectVRQueryResultOnKeyspaceTablets(sourceKeyspaceName, lockTableQR) + env.tmc.expectVRQueryResultOnKeyspaceTablets(sourceKeyspaceName, lockTableQR) + env.tmc.expectVRQueryResultOnKeyspaceTablets(sourceKeyspaceName, deleteReverseWFQR) + env.tmc.expectVRQueryResultOnKeyspaceTablets(sourceKeyspaceName, createReverseWFQR) + env.tmc.expectVRQueryResultOnKeyspaceTablets(sourceKeyspaceName, createJournalQR) + env.tmc.expectVRQueryResultOnKeyspaceTablets(targetKeyspaceName, freezeWFQR) + + ts, _, err := env.ws.getWorkflowState(ctx, targetKeyspaceName, workflowName) + require.NoError(t, err) + + _, _, err = env.ws.switchWrites(ctx, &vtctldatapb.WorkflowSwitchTrafficRequest{ + Keyspace: targetKeyspaceName, + Workflow: workflowName, + }, ts, time.Second, false) + require.NoError(t, err) + + rules, err := topotools.GetRoutingRules(context.Background(), env.ts) + require.NoError(t, err) + require.Equal(t, []string{targetKeyspaceName + "." + tableName}, rules[tableName]) + require.Equal(t, []string{targetKeyspaceName + "." + tableName}, rules[sourceKeyspaceName+"."+tableName]) + + sourceShard, err := env.ts.GetShard(context.Background(), sourceKeyspaceName, "0") + require.NoError(t, err) + require.Len(t, sourceShard.TabletControls, 1) + require.Equal(t, []string{tableName}, sourceShard.TabletControls[0].DeniedTables) + + targetShard, err := env.ts.GetShard(context.Background(), targetKeyspaceName, "0") + require.NoError(t, err) + require.Empty(t, targetShard.TabletControls) + + tsAfter, stateAfter, err := env.ws.getWorkflowState(context.Background(), targetKeyspaceName, workflowName) + require.NoError(t, err) + require.True(t, stateAfter.WritesSwitched, "expected writes to remain switched after the original context was canceled") + require.True(t, tsAfter.frozen, "expected the target workflow to be frozen even though the original context was canceled") +} + +func TestWorkflowSwitchTrafficFailsForInvalidMoveTablesSourceKeyspace(t *testing.T) { + ctx := context.Background() + + const ( + workflowName = "wf1" + tableName = "t1" + sourceKeyspaceName = "sourceks" + targetKeyspaceName = "targetks" + ) + + env := newTestEnv(t, ctx, defaultCellName, &testKeyspace{ + KeyspaceName: sourceKeyspaceName, + ShardNames: []string{"0"}, + }, &testKeyspace{ + KeyspaceName: targetKeyspaceName, + ShardNames: []string{"0"}, + }) + defer env.close() + + env.tmc.schema = map[string]*tabletmanagerdatapb.SchemaDefinition{ + tableName: { + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{{ + Name: tableName, + Schema: fmt.Sprintf("CREATE TABLE %s (id BIGINT, name VARCHAR(64), PRIMARY KEY (id))", tableName), + }}, + }, + } + + env.tmc.expectReadVReplicationWorkflowRequestOnTargetTablets(&readVReplicationWorkflowRequestResponse{ + req: &tabletmanagerdatapb.ReadVReplicationWorkflowRequest{ + Workflow: workflowName, + }, + res: &tabletmanagerdatapb.ReadVReplicationWorkflowResponse{ + Workflow: workflowName, + WorkflowType: binlogdatapb.VReplicationWorkflowType_MoveTables, + Streams: []*tabletmanagerdatapb.ReadVReplicationWorkflowResponse_Stream{{ + Id: 1, + Bls: &binlogdatapb.BinlogSource{ + Keyspace: targetKeyspaceName, + Shard: "0", + Filter: &binlogdatapb.Filter{ + Rules: []*binlogdatapb.Rule{{ + Match: tableName, + }}, + }, + }, + }}, + }, + }) + + _, err := env.ws.WorkflowSwitchTraffic(ctx, &vtctldatapb.WorkflowSwitchTrafficRequest{ + Keyspace: targetKeyspaceName, + Workflow: workflowName, + TabletTypes: []topodatapb.TabletType{topodatapb.TabletType_PRIMARY}, + Direction: int32(DirectionForward), + }) + require.EqualError(t, err, fmt.Sprintf("workflow %s.%s is invalid: MoveTables source keyspace matches target keyspace (%s)", targetKeyspaceName, workflowName, targetKeyspaceName)) +} + func TestMoveTablesTrafficSwitchingDryRun(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() @@ -1817,6 +1975,7 @@ func TestMirrorTraffic(t *testing.T) { sourceShards := []string{"-"} targetKs := "target" targetShards := []string{"-80", "80-"} + otherKs := "otherks" table1 := "table1" table2 := "table2" workflow := "src2target" @@ -2063,6 +2222,30 @@ func TestMirrorTraffic(t *testing.T) { }, }, }, + { + name: "percent zero preserves other mirror targets", + mirrorRules: map[string]map[string]float32{ + fmt.Sprintf("%s.%s", sourceKs, table1): { + fmt.Sprintf("%s.%s", targetKs, table1): 50.0, + fmt.Sprintf("%s.%s", otherKs, table1): 25.0, + }, + fmt.Sprintf("%s.%s", sourceKs, table2): { + fmt.Sprintf("%s.%s", targetKs, table2): 50.0, + }, + }, + req: &vtctldatapb.WorkflowMirrorTrafficRequest{ + Keyspace: targetKs, + Workflow: workflow, + TabletTypes: []topodatapb.TabletType{topodatapb.TabletType_PRIMARY}, + Percent: 0.0, + }, + routingRules: initialRoutingRules, + wantMirrorRules: map[string]map[string]float32{ + fmt.Sprintf("%s.%s", sourceKs, table1): { + fmt.Sprintf("%s.%s", otherKs, table1): 25.0, + }, + }, + }, { name: "does not overwrite unrelated mirror rules", mirrorRules: map[string]map[string]float32{ diff --git a/go/vt/vtctl/workflow/traffic_switcher.go b/go/vt/vtctl/workflow/traffic_switcher.go index db4df2ceb4d..2bdc9ffaebb 100644 --- a/go/vt/vtctl/workflow/traffic_switcher.go +++ b/go/vt/vtctl/workflow/traffic_switcher.go @@ -1571,7 +1571,10 @@ func (ts *trafficSwitcher) mirrorTableTraffic(ctx context.Context, types []topod if percent == 0 { // When percent is 0, remove mirror rule if it exists. if _, ok := mrs[fromTable][toTable]; ok { - delete(mrs, fromTable) + delete(mrs[fromTable], toTable) + if len(mrs[fromTable]) == 0 { + delete(mrs, fromTable) + } } } else { mrs[fromTable][toTable] = percent diff --git a/go/vt/vtctl/workflow/traffic_switcher_test.go b/go/vt/vtctl/workflow/traffic_switcher_test.go index d9b5e349630..24a0ce8014c 100644 --- a/go/vt/vtctl/workflow/traffic_switcher_test.go +++ b/go/vt/vtctl/workflow/traffic_switcher_test.go @@ -32,8 +32,10 @@ import ( tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" topodatapb "vitess.io/vitess/go/vt/proto/topodata" "vitess.io/vitess/go/vt/proto/vschema" + vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/topo" + "vitess.io/vitess/go/vt/topotools" "vitess.io/vitess/go/vt/vtgate/vindexes" ) @@ -450,3 +452,170 @@ func TestCancelMigration_SHARDS(t *testing.T) { assert.Empty(t, env.tmc.vrQueries[100]) assert.Empty(t, env.tmc.vrQueries[200]) } + +func TestDeleteRoutingRulesPreservesUnrelated(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + + workflowName := "wf1" + tableName := "t1" + sourceKeyspaceName := "sourceks" + targetKeyspaceName := "targetks" + + sourceKeyspace := &testKeyspace{ + KeyspaceName: sourceKeyspaceName, + ShardNames: []string{"0"}, + } + targetKeyspace := &testKeyspace{ + KeyspaceName: targetKeyspaceName, + ShardNames: []string{"0"}, + } + + schema := map[string]*tabletmanagerdatapb.SchemaDefinition{ + tableName: { + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ + { + Name: tableName, + Schema: fmt.Sprintf("CREATE TABLE %s (id BIGINT, name VARCHAR(64), PRIMARY KEY (id))", tableName), + }, + }, + }, + } + + env := newTestEnv(t, ctx, defaultCellName, sourceKeyspace, targetKeyspace) + defer env.close() + env.tmc.schema = schema + + ts, _, err := env.ws.getWorkflowState(ctx, targetKeyspaceName, workflowName) + require.NoError(t, err) + + rules := map[string][]string{ + tableName: {fmt.Sprintf("%s.%s", sourceKeyspaceName, tableName)}, + tableName + "@replica": {fmt.Sprintf("%s.%s", sourceKeyspaceName, tableName)}, + sourceKeyspaceName + "." + tableName: {fmt.Sprintf("%s.%s", sourceKeyspaceName, tableName)}, + targetKeyspaceName + "." + tableName: {fmt.Sprintf("%s.%s", sourceKeyspaceName, tableName)}, + "unrelated": {"otherks.unrelated"}, + } + require.NoError(t, topotools.SaveRoutingRules(ctx, env.ts, rules)) + + err = ts.deleteRoutingRules(ctx) + require.NoError(t, err) + + got, err := topotools.GetRoutingRules(ctx, env.ts) + require.NoError(t, err) + require.Equal(t, map[string][]string{ + "unrelated": {"otherks.unrelated"}, + }, got) +} + +func TestDeleteShardRoutingRulesPreservesUnrelated(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + + workflowName := "wf1" + tableName := "t1" + sourceKeyspaceName := "sourceks" + targetKeyspaceName := "targetks" + + sourceKeyspace := &testKeyspace{ + KeyspaceName: sourceKeyspaceName, + ShardNames: []string{"0"}, + } + targetKeyspace := &testKeyspace{ + KeyspaceName: targetKeyspaceName, + ShardNames: []string{"0"}, + } + + schema := map[string]*tabletmanagerdatapb.SchemaDefinition{ + tableName: { + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ + { + Name: tableName, + Schema: fmt.Sprintf("CREATE TABLE %s (id BIGINT, name VARCHAR(64), PRIMARY KEY (id))", tableName), + }, + }, + }, + } + + env := newTestEnv(t, ctx, defaultCellName, sourceKeyspace, targetKeyspace) + defer env.close() + env.tmc.schema = schema + + ts, _, err := env.ws.getWorkflowState(ctx, targetKeyspaceName, workflowName) + require.NoError(t, err) + ts.isPartialMigration = true + + require.NoError(t, topotools.SaveShardRoutingRules(ctx, env.ts, map[string]string{ + fmt.Sprintf("%s.%s", targetKeyspaceName, "0"): sourceKeyspaceName, + "otherks.0": "otherks", + })) + + err = ts.deleteShardRoutingRules(ctx) + require.NoError(t, err) + + got, err := topotools.GetShardRoutingRules(ctx, env.ts) + require.NoError(t, err) + require.Equal(t, map[string]string{ + "otherks.0": "otherks", + }, got) +} + +func TestDeleteKeyspaceRoutingRulesPreservesUnrelated(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + + workflowName := "wf1" + tableName := "t1" + sourceKeyspaceName := "sourceks" + targetKeyspaceName := "targetks" + + sourceKeyspace := &testKeyspace{ + KeyspaceName: sourceKeyspaceName, + ShardNames: []string{"0"}, + } + targetKeyspace := &testKeyspace{ + KeyspaceName: targetKeyspaceName, + ShardNames: []string{"0"}, + } + + schema := map[string]*tabletmanagerdatapb.SchemaDefinition{ + tableName: { + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ + { + Name: tableName, + Schema: fmt.Sprintf("CREATE TABLE %s (id BIGINT, name VARCHAR(64), PRIMARY KEY (id))", tableName), + }, + }, + }, + } + + env := newTestEnv(t, ctx, defaultCellName, sourceKeyspace, targetKeyspace) + defer env.close() + env.tmc.schema = schema + + ts, _, err := env.ws.getWorkflowState(ctx, targetKeyspaceName, workflowName) + require.NoError(t, err) + ts.options = &vtctldatapb.WorkflowOptions{TenantId: "tenant"} + + rules := map[string]string{ + sourceKeyspaceName: targetKeyspaceName, + sourceKeyspaceName + "@replica": targetKeyspaceName, + sourceKeyspaceName + "@rdonly": targetKeyspaceName, + "otherks": "otherks", + } + require.NoError(t, topotools.UpdateKeyspaceRoutingRules(ctx, env.ts, "test", func(ctx context.Context, existing *map[string]string) error { + for key, value := range rules { + (*existing)[key] = value + } + return nil + })) + + err = ts.deleteKeyspaceRoutingRules(ctx) + require.NoError(t, err) + + got, err := topotools.GetKeyspaceRoutingRules(ctx, env.ts) + require.NoError(t, err) + require.Equal(t, map[string]string{ + "otherks": "otherks", + }, got) +} diff --git a/go/vt/vtctl/workflow/utils_test.go b/go/vt/vtctl/workflow/utils_test.go index 99850639ac5..aa0f68c6cac 100644 --- a/go/vt/vtctl/workflow/utils_test.go +++ b/go/vt/vtctl/workflow/utils_test.go @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/require" clientv3 "go.etcd.io/etcd/client/v3" + "vitess.io/vitess/go/race" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/testfiles" "vitess.io/vitess/go/vt/log" @@ -119,10 +120,10 @@ func TestUpdateKeyspaceRoutingRule(t *testing.T) { // TestConcurrentKeyspaceRoutingRulesUpdates runs multiple keyspace routing rules updates concurrently to test // the locking mechanism. func TestConcurrentKeyspaceRoutingRulesUpdates(t *testing.T) { - if os.Getenv("GOCOVERDIR") != "" { - // While running this test in CI along with all other tests in for code coverage this test hangs very often. - // Possibly due to some resource constraints, since this test is one of the last. - // However just running this package by itself with code coverage works fine in CI. + if os.Getenv("GOCOVERDIR") != "" || race.Enabled { + // While running this test in CI along with all other tests in for code coverage or race enabled, + // this test hangs very often. Possibly due to some resource constraints, since this test is one + // of the last. However just running this package by itself with code coverage works fine in CI. t.Logf("Skipping TestConcurrentKeyspaceRoutingRulesUpdates test in code coverage mode") t.Skip() } diff --git a/go/vt/vtgate/engine/fake_vcursor_test.go b/go/vt/vtgate/engine/fake_vcursor_test.go index df7093a773f..994e543c61d 100644 --- a/go/vt/vtgate/engine/fake_vcursor_test.go +++ b/go/vt/vtgate/engine/fake_vcursor_test.go @@ -120,6 +120,10 @@ func (t *noopVCursor) CloneForReplicaWarming(ctx context.Context) VCursor { panic("implement me") } +func (t *noopVCursor) WarmingReadsContext(ctx context.Context) (context.Context, context.CancelFunc) { + panic("implement me") +} + func (t *noopVCursor) CloneForMirroring(ctx context.Context) VCursor { panic("implement me") } @@ -410,6 +414,7 @@ func (t *noopVCursor) DisableLogging() {} func (t *noopVCursor) GetVExplainLogs() []ExecuteEntry { return nil } + func (t *noopVCursor) GetLogs() ([]ExecuteEntry, error) { return nil, nil } @@ -463,10 +468,11 @@ type loggingVCursor struct { parser *sqlparser.Parser - onMirrorClonesFn func(context.Context) VCursor - onExecuteMultiShardFn func(context.Context, Primitive, []*srvtopo.ResolvedShard, []*querypb.BoundQuery, bool, bool) - onStreamExecuteMultiFn func(context.Context, Primitive, string, []*srvtopo.ResolvedShard, []map[string]*querypb.BindVariable, bool, bool, func(*sqltypes.Result) error) - onRecordMirrorStatsFn func(time.Duration, time.Duration, error) + onMirrorClonesFn func(context.Context) VCursor + onExecuteMultiShardFn func(context.Context, Primitive, []*srvtopo.ResolvedShard, []*querypb.BoundQuery, bool, bool) + onStreamExecuteMultiFn func(context.Context, Primitive, string, []*srvtopo.ResolvedShard, []map[string]*querypb.BindVariable, bool, bool, func(*sqltypes.Result) error) + onRecordMirrorStatsFn func(time.Duration, time.Duration, error) + onResolveDestinationsFn func(context.Context) } func (f *loggingVCursor) HasCreatedTempTable() { @@ -586,6 +592,10 @@ func (f *loggingVCursor) CloneForReplicaWarming(ctx context.Context) VCursor { return f } +func (f *loggingVCursor) WarmingReadsContext(ctx context.Context) (context.Context, context.CancelFunc) { + return ctx, func() {} +} + func (f *loggingVCursor) CloneForMirroring(ctx context.Context) VCursor { if f.onMirrorClonesFn != nil { return f.onMirrorClonesFn(ctx) @@ -649,6 +659,9 @@ func (f *loggingVCursor) StreamExecuteMulti(ctx context.Context, primitive Primi } func (f *loggingVCursor) ResolveDestinations(ctx context.Context, keyspace string, ids []*querypb.Value, destinations []key.ShardDestination) ([]*srvtopo.ResolvedShard, [][]*querypb.Value, error) { + if f.onResolveDestinationsFn != nil { + f.onResolveDestinationsFn(ctx) + } f.log = append(f.log, fmt.Sprintf("ResolveDestinations %v %v %v", keyspace, ids, key.DestinationsString(destinations))) if f.shardErr != nil { return nil, nil, f.shardErr diff --git a/go/vt/vtgate/engine/primitive.go b/go/vt/vtgate/engine/primitive.go index be65bcde831..b02be414d46 100644 --- a/go/vt/vtgate/engine/primitive.go +++ b/go/vt/vtgate/engine/primitive.go @@ -129,9 +129,16 @@ type ( // GetWarmingReadsChannel returns the channel for executing warming reads against replicas GetWarmingReadsChannel() chan bool - // CloneForReplicaWarming clones the VCursor for re-use in warming queries to replicas + // CloneForReplicaWarming clones the VCursor for re-use in warming queries to replicas. + // The clone must be created before launching the warming goroutine to avoid + // concurrent access to the original VCursor. Use WarmingReadsContext on the + // clone to obtain a timeout-bounded context for the warming query. CloneForReplicaWarming(ctx context.Context) VCursor + // WarmingReadsContext returns a timeout-bounded context for a warming query + // and a cancel function that must be called when the warming query completes. + WarmingReadsContext(ctx context.Context) (context.Context, context.CancelFunc) + // CloneForMirroring clones the VCursor for re-use in mirroring queries to other keyspaces CloneForMirroring(ctx context.Context) VCursor // diff --git a/go/vt/vtgate/engine/route.go b/go/vt/vtgate/engine/route.go index a43299961e6..dfa79b196b9 100644 --- a/go/vt/vtgate/engine/route.go +++ b/go/vt/vtgate/engine/route.go @@ -41,12 +41,10 @@ import ( var _ Primitive = (*Route)(nil) -var ( - replicaWarmingReadsMirrored = stats.NewCountersWithMultiLabels( - "ReplicaWarmingReadsMirrored", - "Number of reads mirrored to replicas to warm their bufferpools", - []string{"Keyspace"}) -) +var replicaWarmingReadsMirrored = stats.NewCountersWithMultiLabels( + "ReplicaWarmingReadsMirrored", + "Number of reads mirrored to replicas to warm their bufferpools", + []string{"Keyspace"}) // Route represents the instructions to route a read query to // one or many vttablets. @@ -106,9 +104,7 @@ func NewRoute(opcode Opcode, keyspace *vindexes.Keyspace, query, fieldQuery stri } } -var ( - partialSuccessScatterQueries = stats.NewCounter("PartialSuccessScatterQueries", "Count of partially successful scatter queries") -) +var partialSuccessScatterQueries = stats.NewCounter("PartialSuccessScatterQueries", "Count of partially successful scatter queries") // RouteType returns a description of the query routing type used by the primitive func (route *Route) RouteType() string { @@ -531,22 +527,25 @@ func (route *Route) executeWarmingReplicaRead(ctx context.Context, vcursor VCurs return } - replicaVCursor := vcursor.CloneForReplicaWarming(ctx) warmingReadsChannel := vcursor.GetWarmingReadsChannel() select { // if there's no more room in the channel, drop the warming read case warmingReadsChannel <- true: + replicaVCursor := vcursor.CloneForReplicaWarming(ctx) go func(replicaVCursor VCursor) { + warmingCtx, cancel := replicaVCursor.WarmingReadsContext(ctx) + // Defers run LIFO: channel slot is released first, then context is canceled. + defer cancel() defer func() { <-warmingReadsChannel }() - rss, _, err := route.findRoute(ctx, replicaVCursor, bindVars) + rss, _, err := route.findRoute(warmingCtx, replicaVCursor, bindVars) if err != nil { return } - _, errs := replicaVCursor.ExecuteMultiShard(ctx, route, rss, queries, false /*rollbackOnError*/, false /*canAutocommit*/, route.FetchLastInsertID) + _, errs := replicaVCursor.ExecuteMultiShard(warmingCtx, route, rss, queries, false /*rollbackOnError*/, false /*canAutocommit*/, route.FetchLastInsertID) if len(errs) > 0 { log.Warningf("Failed to execute warming replica read: %v", errs) } else { diff --git a/go/vt/vtgate/engine/route_warming_reads_test.go b/go/vt/vtgate/engine/route_warming_reads_test.go new file mode 100644 index 00000000000..ce3202ec005 --- /dev/null +++ b/go/vt/vtgate/engine/route_warming_reads_test.go @@ -0,0 +1,291 @@ +/* +Copyright 2026 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package engine + +import ( + "context" + "sync/atomic" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/vt/srvtopo" + "vitess.io/vitess/go/vt/vtgate/evalengine" + "vitess.io/vitess/go/vt/vtgate/vindexes" + + querypb "vitess.io/vitess/go/vt/proto/query" +) + +type warmingReadsVCursor struct { + *loggingVCursor + warmingReadsPercent int + warmingReadsChannel chan bool + warmingReadsTimeout time.Duration + warmingReadsExecuteFunc func(context.Context, Primitive, []*srvtopo.ResolvedShard, []*querypb.BoundQuery, bool, bool) +} + +func (vc *warmingReadsVCursor) GetWarmingReadsPercent() int { + return vc.warmingReadsPercent +} + +func (vc *warmingReadsVCursor) GetWarmingReadsChannel() chan bool { + return vc.warmingReadsChannel +} + +func (vc *warmingReadsVCursor) CloneForReplicaWarming(ctx context.Context) VCursor { + clonedLogging := &loggingVCursor{ + shards: vc.shards, + results: vc.results, + onResolveDestinationsFn: vc.onResolveDestinationsFn, + } + clone := &warmingReadsVCursor{ + loggingVCursor: clonedLogging, + warmingReadsPercent: vc.warmingReadsPercent, + warmingReadsChannel: vc.warmingReadsChannel, + warmingReadsTimeout: vc.warmingReadsTimeout, + warmingReadsExecuteFunc: vc.warmingReadsExecuteFunc, + } + clone.onExecuteMultiShardFn = vc.warmingReadsExecuteFunc + return clone +} + +func (vc *warmingReadsVCursor) WarmingReadsContext(ctx context.Context) (context.Context, context.CancelFunc) { + return context.WithTimeout(context.Background(), vc.warmingReadsTimeout) +} + +func TestWarmingReadsSkipsForUpdate(t *testing.T) { + vindex, _ := vindexes.CreateVindex("hash", "", nil) + testCases := []struct { + name string + query string + expectedWarmingQuery string + }{ + { + name: "SELECT FOR UPDATE", + query: "SELECT * FROM users WHERE id = 1 FOR UPDATE", + expectedWarmingQuery: "SELECT * FROM users WHERE id = 1 FOR UPDATE", + }, + { + name: "SELECT FOR UPDATE mixed case", + query: "SELECT * FROM users WHERE id = 1 FoR UpDaTe", + expectedWarmingQuery: "SELECT * FROM users WHERE id = 1 FoR UpDaTe", + }, + { + name: "SELECT FOR UPDATE with extra spaces", + query: "SELECT * FROM users WHERE id = 1 FOR UPDATE", + expectedWarmingQuery: "SELECT * FROM users WHERE id = 1 FOR UPDATE", + }, + { + name: "SELECT FOR UPDATE with comment", + query: "SELECT * FROM users WHERE id = 1 FOR /* comment */ UPDATE", + expectedWarmingQuery: "SELECT * FROM users WHERE id = 1 FOR /* comment */ UPDATE", + }, + { + name: "SELECT FOR UPDATE NOWAIT", + query: "SELECT * FROM users WHERE id = 1 FOR UPDATE NOWAIT", + expectedWarmingQuery: "SELECT * FROM users WHERE id = 1 FOR UPDATE NOWAIT", + }, + { + name: "SELECT FOR UPDATE SKIP LOCKED", + query: "SELECT * FROM users WHERE id = 1 FOR UPDATE SKIP LOCKED", + expectedWarmingQuery: "SELECT * FROM users WHERE id = 1 FOR UPDATE SKIP LOCKED", + }, + { + name: "UNION FOR UPDATE", + query: "SELECT * FROM users WHERE id = 1 UNION SELECT * FROM users WHERE id = 2 FOR UPDATE", + expectedWarmingQuery: "SELECT * FROM users WHERE id = 1 UNION SELECT * FROM users WHERE id = 2 FOR UPDATE", + }, + { + name: "Regular SELECT", + query: "SELECT * FROM users WHERE id = 1", + expectedWarmingQuery: "SELECT * FROM users WHERE id = 1", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + route := NewRoute( + EqualUnique, + &vindexes.Keyspace{ + Name: "ks", + Sharded: true, + }, + tc.query, + "dummy_select_field", + ) + route.Vindex = vindex.(vindexes.SingleColumn) + route.Values = []evalengine.Expr{ + evalengine.NewLiteralInt(1), + } + + var warmingReadExecuted atomic.Bool + var capturedQuery string + var capturedCtxHasDeadline atomic.Bool + var capturedCtxErr atomic.Pointer[error] + var resolveDestCtxHasDeadline atomic.Bool + // done is closed by the test to unblock the warming read goroutine + // after context assertions have been made. + done := make(chan struct{}) + vc := &warmingReadsVCursor{ + loggingVCursor: &loggingVCursor{ + shards: []string{"-20", "20-"}, + results: []*sqltypes.Result{defaultSelectResult}, + onResolveDestinationsFn: func(ctx context.Context) { + _, hasDeadline := ctx.Deadline() + resolveDestCtxHasDeadline.Store(hasDeadline) + }, + }, + warmingReadsPercent: 100, + warmingReadsChannel: make(chan bool, 1), + warmingReadsTimeout: 5 * time.Second, + } + vc.warmingReadsExecuteFunc = func(ctx context.Context, primitive Primitive, rss []*srvtopo.ResolvedShard, queries []*querypb.BoundQuery, rollbackOnError, canAutocommit bool) { + if len(queries) > 0 { + capturedQuery = queries[0].Sql + } + _, hasDeadline := ctx.Deadline() + capturedCtxHasDeadline.Store(hasDeadline) + ctxErr := ctx.Err() + capturedCtxErr.Store(&ctxErr) + warmingReadExecuted.Store(true) + // Block until the test has checked our context assertions, + // preventing defer cancel() from running. + select { + case <-done: + case <-t.Context().Done(): + } + } + + // Use a cancelable parent context to verify the warming read + // context is independent of the parent request context. + parentCtx, parentCancel := context.WithCancel(t.Context()) + _, err := route.TryExecute(parentCtx, vc, map[string]*querypb.BindVariable{}, false) + require.NoError(t, err) + + // Cancel the parent context to simulate the primary request completing. + parentCancel() + + require.Eventually(t, func() bool { + return warmingReadExecuted.Load() + }, time.Second, 10*time.Millisecond, "warming read should be executed") + + require.Equal(t, tc.expectedWarmingQuery, capturedQuery, "warming read query should match expected") + require.True(t, capturedCtxHasDeadline.Load(), "warming read context should have a deadline from the timeout") + + // The warming read context should still be active even though the + // parent request context was canceled. + require.NoError(t, *capturedCtxErr.Load(), "warming read context should not be canceled when parent context is canceled") + + // Verify findRoute received the warming context (with deadline), not the parent context. + require.True(t, resolveDestCtxHasDeadline.Load(), "ResolveDestinations should receive a context with deadline from the warming timeout") + + // Unblock the warming read goroutine. + close(done) + }) + } +} + +func TestWarmingReadsDroppedWhenChannelFull(t *testing.T) { + vindex, _ := vindexes.CreateVindex("hash", "", nil) + route := NewRoute( + EqualUnique, + &vindexes.Keyspace{ + Name: "ks", + Sharded: true, + }, + "SELECT * FROM users WHERE id = 1", + "dummy_select_field", + ) + route.Vindex = vindex.(vindexes.SingleColumn) + route.Values = []evalengine.Expr{ + evalengine.NewLiteralInt(1), + } + + var warmingReadExecuted atomic.Bool + vc := &warmingReadsVCursor{ + loggingVCursor: &loggingVCursor{ + shards: []string{"-20", "20-"}, + results: []*sqltypes.Result{defaultSelectResult}, + }, + warmingReadsPercent: 100, + warmingReadsChannel: make(chan bool, 1), + warmingReadsTimeout: 5 * time.Second, + } + vc.warmingReadsExecuteFunc = func(ctx context.Context, primitive Primitive, rss []*srvtopo.ResolvedShard, queries []*querypb.BoundQuery, rollbackOnError, canAutocommit bool) { + warmingReadExecuted.Store(true) + } + + // Pre-fill the channel to simulate a full pool. + vc.warmingReadsChannel <- true + + _, err := route.TryExecute(t.Context(), vc, map[string]*querypb.BindVariable{}, false) + require.NoError(t, err) + + // Verify over a short window that no warming read is executed while the channel is full. + require.Never(t, func() bool { + return warmingReadExecuted.Load() + }, 100*time.Millisecond, 5*time.Millisecond, "warming read should not execute when the channel is full") + // Drain the channel. + <-vc.warmingReadsChannel +} + +func TestWarmingReadsContextTimeout(t *testing.T) { + vindex, _ := vindexes.CreateVindex("hash", "", nil) + route := NewRoute( + EqualUnique, + &vindexes.Keyspace{ + Name: "ks", + Sharded: true, + }, + "SELECT * FROM users WHERE id = 1", + "dummy_select_field", + ) + route.Vindex = vindex.(vindexes.SingleColumn) + route.Values = []evalengine.Expr{ + evalengine.NewLiteralInt(1), + } + + var capturedCtxErr atomic.Pointer[error] + var warmingReadExecuted atomic.Bool + vc := &warmingReadsVCursor{ + loggingVCursor: &loggingVCursor{ + shards: []string{"-20", "20-"}, + results: []*sqltypes.Result{defaultSelectResult}, + }, + warmingReadsPercent: 100, + warmingReadsChannel: make(chan bool, 1), + warmingReadsTimeout: 1 * time.Millisecond, + } + vc.warmingReadsExecuteFunc = func(ctx context.Context, primitive Primitive, rss []*srvtopo.ResolvedShard, queries []*querypb.BoundQuery, rollbackOnError, canAutocommit bool) { + // Block until the warming context times out. + <-ctx.Done() + ctxErr := ctx.Err() + capturedCtxErr.Store(&ctxErr) + warmingReadExecuted.Store(true) + } + + _, err := route.TryExecute(t.Context(), vc, map[string]*querypb.BindVariable{}, false) + require.NoError(t, err) + + require.Eventually(t, func() bool { + return warmingReadExecuted.Load() + }, time.Second, 10*time.Millisecond, "warming read should have been executed and timed out") + + require.ErrorIs(t, *capturedCtxErr.Load(), context.DeadlineExceeded, "warming read context should have timed out") +} diff --git a/go/vt/vtgate/engine/set.go b/go/vt/vtgate/engine/set.go index 32a297404f3..f32584ca6f3 100644 --- a/go/vt/vtgate/engine/set.go +++ b/go/vt/vtgate/engine/set.go @@ -277,6 +277,7 @@ func (svs *SysVarReservedConn) Execute(ctx context.Context, vcursor VCursor, env return err } vcursor.Session().NeedsReservedConn() + vcursor.Session().SetSysVar(svs.Name, svs.Expr) return svs.execSetStatement(ctx, vcursor, rss, env) } needReservedConn, err := svs.checkAndUpdateSysVar(ctx, vcursor, env) @@ -292,22 +293,14 @@ func (svs *SysVarReservedConn) Execute(ctx context.Context, vcursor VCursor, env if len(rss) == 0 { return nil } - queries := make([]*querypb.BoundQuery, len(rss)) - for i := 0; i < len(rss); i++ { - queries[i] = &querypb.BoundQuery{ - Sql: fmt.Sprintf("set %s = %s", svs.Name, svs.Expr), - BindVariables: env.BindVars, - } - } - _, errs := vcursor.ExecuteMultiShard(ctx, nil /*primitive*/, rss, queries, false /*rollbackOnError*/, false /*canAutocommit*/, false /*fetchLastInsertID*/) - return vterrors.Aggregate(errs) + return svs.execSetStatement(ctx, vcursor, rss, env) } func (svs *SysVarReservedConn) execSetStatement(ctx context.Context, vcursor VCursor, rss []*srvtopo.ResolvedShard, env *evalengine.ExpressionEnv) error { queries := make([]*querypb.BoundQuery, len(rss)) for i := 0; i < len(rss); i++ { queries[i] = &querypb.BoundQuery{ - Sql: fmt.Sprintf("set @@%s = %s", svs.Name, svs.Expr), + Sql: fmt.Sprintf("set %s = %s", svs.Name, svs.Expr), BindVariables: env.BindVars, } } diff --git a/go/vt/vtgate/engine/set_test.go b/go/vt/vtgate/engine/set_test.go index 688c47c6f47..4f012fa4137 100644 --- a/go/vt/vtgate/engine/set_test.go +++ b/go/vt/vtgate/engine/set_test.go @@ -243,7 +243,8 @@ func TestSetTable(t *testing.T) { expectedQueryLog: []string{ `ResolveDestinations ks [] Destinations:DestinationAnyShard()`, `Needs Reserved Conn`, - `ExecuteMultiShard ks.-20: set @@x = dummy_expr {} false false`, + `SysVar set with (x,dummy_expr)`, + `ExecuteMultiShard ks.-20: set x = dummy_expr {} false false`, }, }, { testName: "sysvar set not modifying setting", @@ -609,7 +610,8 @@ func TestSysVarSetErr(t *testing.T) { expectedQueryLog := []string{ `ResolveDestinations ks [] Destinations:DestinationAnyShard()`, "Needs Reserved Conn", - `ExecuteMultiShard ks.-20: set @@x = dummy_expr {} false false`, + "SysVar set with (x,dummy_expr)", + `ExecuteMultiShard ks.-20: set x = dummy_expr {} false false`, } set := &Set{ diff --git a/go/vt/vtgate/evalengine/compiler.go b/go/vt/vtgate/evalengine/compiler.go index c69df3a300f..1718fb4b043 100644 --- a/go/vt/vtgate/evalengine/compiler.go +++ b/go/vt/vtgate/evalengine/compiler.go @@ -585,6 +585,8 @@ func (c *compiler) compileParseJSON(fn string, doct ctype, offset int) (ctype, e case sqltypes.TypeJSON: case sqltypes.VarChar, sqltypes.VarBinary: c.asm.Parse_j(offset) + case sqltypes.Null: + return ctype{Type: sqltypes.Null, Flag: flagNull | flagNullable, Col: collationNull}, nil default: return ctype{}, errJSONType(fn) } diff --git a/go/vt/vtgate/evalengine/compiler_asm.go b/go/vt/vtgate/evalengine/compiler_asm.go index d13d22e76cc..ff5573abcbc 100644 --- a/go/vt/vtgate/evalengine/compiler_asm.go +++ b/go/vt/vtgate/evalengine/compiler_asm.go @@ -47,7 +47,6 @@ import ( "vitess.io/vitess/go/mysql/hex" "vitess.io/vitess/go/mysql/icuregex" "vitess.io/vitess/go/mysql/json" - "vitess.io/vitess/go/slice" "vitess.io/vitess/go/sqltypes" querypb "vitess.io/vitess/go/vt/proto/query" "vitess.io/vitess/go/vt/proto/vtrpc" @@ -2215,40 +2214,89 @@ func (asm *assembler) Fn_JSON_CONTAINS_PATH(match jsonMatch, paths []*json.Path) } } -func (asm *assembler) Fn_JSON_EXTRACT0(jp []*json.Path) { - multi := len(jp) > 1 || slice.Any(jp, func(path *json.Path) bool { return path.ContainsWildcards() }) +type staticPath struct { + p *json.Path + err error +} - if multi { - asm.emit(func(env *ExpressionEnv) int { +func (asm *assembler) Fn_JSON_EXTRACT(args int, staticPaths []staticPath) { + asm.adjustStack(-args) + asm.emit(func(env *ExpressionEnv) int { + paths := make([]*json.Path, 0, args) + + multi := args > 1 + + doct := env.vm.stack[env.vm.sp-(args+1)].(*evalJSON) + + for i := args; i > 0; i-- { + arg := env.vm.stack[env.vm.sp-i] + + if arg == nil { + env.vm.sp -= args + env.vm.stack[env.vm.sp-1] = nil + return 1 + } + + staticPath := staticPaths[args-i] + if staticPath.err != nil { + env.vm.err = staticPath.err + return 1 + } + + var path *json.Path + if staticPath.p != nil { + path = staticPath.p + } else { + pathBytes, err := evalToVarchar(arg, collations.CollationUtf8mb4ID, true) + if err != nil { + env.vm.err = err + return 1 + } + + path, err = intoJSONPath(pathBytes) + if err != nil { + env.vm.err = err + return 1 + } + } + + if !multi { + multi = path.ContainsWildcards() + } + + paths = append(paths, path) + } + + env.vm.sp -= args + + if multi { matches := make([]*json.Value, 0, 4) - arg := env.vm.stack[env.vm.sp-1].(*evalJSON) - for _, jp := range jp { - jp.Match(arg, true, func(value *json.Value) { + for _, jp := range paths { + jp.Match(doct, true, func(value *json.Value) { matches = append(matches, value) }) } + if len(matches) == 0 { env.vm.stack[env.vm.sp-1] = nil } else { env.vm.stack[env.vm.sp-1] = json.NewArray(matches) } - return 1 - }, "FN JSON_EXTRACT, SP-1, [static]") - } else { - asm.emit(func(env *ExpressionEnv) int { + } else { var match *json.Value - arg := env.vm.stack[env.vm.sp-1].(*evalJSON) - jp[0].Match(arg, true, func(value *json.Value) { + paths[0].Match(doct, true, func(value *json.Value) { match = value }) + if match == nil { env.vm.stack[env.vm.sp-1] = nil } else { env.vm.stack[env.vm.sp-1] = match } - return 1 - }, "FN JSON_EXTRACT, SP-1, [static]") - } + } + + return 1 + }, "FN JSON_EXTRACT, SP-1, ..., SP-N") } func (asm *assembler) Fn_JSON_KEYS(jp *json.Path) { @@ -2271,6 +2319,15 @@ func (asm *assembler) Fn_JSON_KEYS(jp *json.Path) { return 1 }, "FN JSON_KEYS (SP-1)") } else { + if jp.ContainsWildcards() { + asm.emit(func(env *ExpressionEnv) int { + env.vm.err = errInvalidPathForTransform + return 1 + }, "FN JSON_KEYS (SP-1), %q", jp.String()) + + return + } + asm.emit(func(env *ExpressionEnv) int { doc := env.vm.stack[env.vm.sp-1] if doc == nil { diff --git a/go/vt/vtgate/evalengine/fn_json.go b/go/vt/vtgate/evalengine/fn_json.go index 54038e28339..93714dc3438 100644 --- a/go/vt/vtgate/evalengine/fn_json.go +++ b/go/vt/vtgate/evalengine/fn_json.go @@ -89,7 +89,7 @@ func (call *builtinJSONExtract) eval(env *ExpressionEnv) (eval, error) { } func builtin_JSON_EXTRACT(doc *json.Value, paths []eval) (eval, error) { - matches := make([]*json.Value, 0, 4) + matches := make([]*json.Value, 0, len(paths)) multi := len(paths) > 1 for _, p := range paths { @@ -125,27 +125,50 @@ func (call *builtinJSONExtract) compile(c *compiler) (ctype, error) { return ctype{}, err } - if slice.All(call.Arguments[1:], func(expr IR) bool { return expr.constant() }) { - paths := make([]*json.Path, 0, len(call.Arguments[1:])) + // Handle `NULL` arguments + nullable := doct.nullable() + skip := c.compileNullCheck1(doct) - for _, arg := range call.Arguments[1:] { - jp, err := c.jsonExtractPath(arg) + jt, err := c.compileParseJSON("JSON_EXTRACT", doct, 1) + if err != nil { + return ctype{}, err + } + + staticPaths := make([]staticPath, 0, len(call.Arguments[1:])) + + for _, arg := range call.Arguments[1:] { + argType, err := arg.compile(c) + if err != nil { + return ctype{}, err + } + + if !nullable { + nullable = argType.nullable() + } + + if arg.constant() { + staticEnv := EmptyExpressionEnv(c.env) + arg, err = simplifyExpr(staticEnv, arg) if err != nil { return ctype{}, err } - paths = append(paths, jp) - } - jt, err := c.compileParseJSON("JSON_EXTRACT", doct, 1) - if err != nil { - return ctype{}, err + p, err := c.jsonExtractPath(arg) + staticPaths = append(staticPaths, staticPath{p, err}) + } else { + staticPaths = append(staticPaths, staticPath{nil, nil}) } + } - c.asm.Fn_JSON_EXTRACT0(paths) - return jt, nil + c.asm.Fn_JSON_EXTRACT(len(call.Arguments[1:]), staticPaths) + c.asm.jumpDestination(skip) + + if nullable { + // If any argument is nullable, the result is nullable too + jt.Flag |= flagNullable } - return ctype{}, c.unsupported(call) + return jt, nil } func (call *builtinJSONUnquote) eval(env *ExpressionEnv) (eval, error) { @@ -381,6 +404,13 @@ func (call *builtinJSONContainsPath) compile(c *compiler) (ctype, error) { return ctype{}, c.unsupported(call) } + skip := c.compileNullCheck1(doct) + + _, err = c.compileParseJSON("JSON_CONTAINS_PATH", doct, 1) + if err != nil { + return ctype{}, err + } + match, err := c.jsonExtractOneOrAll("JSON_CONTAINS_PATH", call.Arguments[1]) if err != nil { return ctype{}, err @@ -396,12 +426,10 @@ func (call *builtinJSONContainsPath) compile(c *compiler) (ctype, error) { paths = append(paths, jp) } - _, err = c.compileParseJSON("JSON_CONTAINS_PATH", doct, 1) - if err != nil { - return ctype{}, err - } - c.asm.Fn_JSON_CONTAINS_PATH(match, paths) + + c.asm.jumpDestination(skip) + return ctype{Type: sqltypes.Int64, Col: collationNumeric, Flag: flagIsBoolean | flagNullable}, nil } @@ -492,6 +520,8 @@ func (call *builtinJSONKeys) compile(c *compiler) (ctype, error) { return ctype{}, err } + skip := c.compileNullCheck1(doc) + _, err = c.compileParseJSON("JSON_KEYS", doc, 1) if err != nil { return ctype{}, err @@ -503,11 +533,11 @@ func (call *builtinJSONKeys) compile(c *compiler) (ctype, error) { if err != nil { return ctype{}, err } - if jp.ContainsWildcards() { - return ctype{}, errInvalidPathForTransform - } } c.asm.Fn_JSON_KEYS(jp) + + c.asm.jumpDestination(skip) + return ctype{Type: sqltypes.TypeJSON, Flag: flagNullable, Col: collationJSON}, nil } diff --git a/go/vt/vtgate/evalengine/integration/fuzz_test.go b/go/vt/vtgate/evalengine/integration/fuzz_test.go index a16f6164b35..7c95870991f 100644 --- a/go/vt/vtgate/evalengine/integration/fuzz_test.go +++ b/go/vt/vtgate/evalengine/integration/fuzz_test.go @@ -102,6 +102,7 @@ var ( regexp.MustCompile(`Illegal argument to a regular expression`), regexp.MustCompile(`Incorrect arguments to regexp_substr`), regexp.MustCompile(`Incorrect arguments to regexp_replace`), + regexp.MustCompile(`Invalid JSON path expression\. The error is around character position (\d+)\.`), } ) diff --git a/go/vt/vtgate/evalengine/testcases/cases.go b/go/vt/vtgate/evalengine/testcases/cases.go index 1f34e6bfe0c..cc6c9e0ad12 100644 --- a/go/vt/vtgate/evalengine/testcases/cases.go +++ b/go/vt/vtgate/evalengine/testcases/cases.go @@ -30,7 +30,10 @@ import ( var Cases = []TestCase{ {Run: JSONExtract, Schema: JSONExtract_Schema}, - {Run: JSONPathOperations}, + {Run: FnJSONKeys}, + {Run: FnJSONExtract}, + {Run: FnJSONContainsPath}, + {Run: FnJSONUnquote}, {Run: JSONArray}, {Run: JSONObject}, {Run: CharsetConversionOperators}, @@ -176,23 +179,76 @@ var Cases = []TestCase{ {Run: RegexpReplace}, } -func JSONPathOperations(yield Query) { +func FnJSONKeys(yield Query) { for _, obj := range inputJSONObjects { - yield(fmt.Sprintf("JSON_KEYS('%s')", obj), nil, false) + yield(fmt.Sprintf("JSON_KEYS(%s)", obj), nil, false) for _, path1 := range inputJSONPaths { - yield(fmt.Sprintf("JSON_EXTRACT('%s', '%s')", obj, path1), nil, false) - yield(fmt.Sprintf("JSON_CONTAINS_PATH('%s', 'one', '%s')", obj, path1), nil, false) - yield(fmt.Sprintf("JSON_CONTAINS_PATH('%s', 'all', '%s')", obj, path1), nil, false) - yield(fmt.Sprintf("JSON_KEYS('%s', '%s')", obj, path1), nil, false) + yield(fmt.Sprintf("JSON_KEYS(%s, '%s')", obj, path1), nil, false) + } + } +} + +func FnJSONExtract(yield Query) { + for _, obj := range inputJSONObjects { + for _, path1 := range inputJSONPaths { + yield(fmt.Sprintf("JSON_EXTRACT(%s, '%s')", obj, path1), nil, false) for _, path2 := range inputJSONPaths { - yield(fmt.Sprintf("JSON_EXTRACT('%s', '%s', '%s')", obj, path1, path2), nil, false) - yield(fmt.Sprintf("JSON_CONTAINS_PATH('%s', 'one', '%s', '%s')", obj, path1, path2), nil, false) - yield(fmt.Sprintf("JSON_CONTAINS_PATH('%s', 'all', '%s', '%s')", obj, path1, path2), nil, false) + yield(fmt.Sprintf("JSON_EXTRACT(%s, '%s', '%s')", obj, path1, path2), nil, false) } } } + + yield(`JSON_EXTRACT('{"a": 1}', '$.a')`, nil, false) + yield(`JSON_EXTRACT('{"a": 1}', '$.*')`, nil, false) + yield(`JSON_EXTRACT('[1, 2, 3]', '$[0 to 2]')`, nil, false) + yield(`JSON_EXTRACT('{"a": 1, "b": 2}', '$.a', '$.b')`, nil, false) + yield(`JSON_EXTRACT('{"a": 1}', '$.a', '$.z')`, nil, false) + + yield(`JSON_EXTRACT(CONCAT('{', '"a"', ':', ' ', '1', '}'), '$.a')`, nil, false) + yield(`JSON_EXTRACT('{"a": 1}', CONCAT('$', '.', 'a'))`, nil, false) + + yield(`JSON_EXTRACT(NULL, '$.a')`, nil, false) + yield(`JSON_EXTRACT(NULL, NULL)`, nil, false) + + yield(`JSON_EXTRACT('{"a": 1}', NULL)`, nil, false) + yield(`JSON_EXTRACT('{"a": 1}', '$.a', NULL)`, nil, false) + yield(`JSON_EXTRACT('{"a": 1}', NULL, '$.a')`, nil, false) + + yield(`JSON_EXTRACT('{"a": 1}', '$.b')`, nil, false) + yield(`JSON_EXTRACT('{"a": 1}', '$.b', '$.c')`, nil, false) + yield(`JSON_EXTRACT('[1,2,3]', '$[10]')`, nil, false) + + yield(`JSON_EXTRACT('{invalid}', '$.a')`, nil, false) + yield(`JSON_EXTRACT('not json', '$.a')`, nil, false) + yield(`JSON_EXTRACT('', '$.a')`, nil, false) + yield(`JSON_EXTRACT('{invalid}', NULL)`, nil, false) + + yield(`JSON_EXTRACT('{"a": 1}', '$.b[ 1 ].')`, nil, false) + + yield(`JSON_EXTRACT(NULL, 'invalid-path')`, nil, false) + yield(`JSON_EXTRACT('{"a": 1}', NULL, 'invalid-path')`, nil, false) + yield(`JSON_EXTRACT('{"a": 1}', 'invalid-path', NULL)`, nil, false) + yield(`JSON_EXTRACT('{"a": 1}', '$.a', 'invalid')`, nil, false) +} + +func FnJSONContainsPath(yield Query) { + for _, obj := range inputJSONObjects { + for _, path1 := range inputJSONPaths { + yield(fmt.Sprintf("JSON_CONTAINS_PATH(%s, 'one', '%s')", obj, path1), nil, false) + yield(fmt.Sprintf("JSON_CONTAINS_PATH(%s, 'all', '%s')", obj, path1), nil, false) + + for _, path2 := range inputJSONPaths { + yield(fmt.Sprintf("JSON_CONTAINS_PATH(%s, 'one', '%s', '%s')", obj, path1, path2), nil, false) + yield(fmt.Sprintf("JSON_CONTAINS_PATH(%s, 'all', '%s', '%s')", obj, path1, path2), nil, false) + } + } + } +} + +func FnJSONUnquote(yield Query) { + yield("JSON_UNQUOTE(NULL)", nil, false) } func JSONArray(yield Query) { diff --git a/go/vt/vtgate/evalengine/testcases/inputs.go b/go/vt/vtgate/evalengine/testcases/inputs.go index 4c65cc5002f..281eebb4fe0 100644 --- a/go/vt/vtgate/evalengine/testcases/inputs.go +++ b/go/vt/vtgate/evalengine/testcases/inputs.go @@ -24,13 +24,14 @@ import ( ) var inputJSONObjects = []string{ - `[ { "a": 1 }, { "a": 2 } ]`, - `{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }`, - `{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }`, - `{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }`, - `{"a": 1, "b": 2, "c": {"d": 4}}`, - `["a", {"b": [true, false]}, [10, 20]]`, - `[10, 20, [30, 40]]`, + `'[ { "a": 1 }, { "a": 2 } ]'`, + `'{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }'`, + `'{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }'`, + `'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }'`, + `'{"a": 1, "b": 2, "c": {"d": 4}}'`, + `'["a", {"b": [true, false]}, [10, 20]]'`, + `'[10, 20, [30, 40]]'`, + `NULL`, } var inputJSONPaths = []string{ diff --git a/go/vt/vtgate/executor.go b/go/vt/vtgate/executor.go index 8621a107bf7..bab11fc272b 100644 --- a/go/vt/vtgate/executor.go +++ b/go/vt/vtgate/executor.go @@ -326,6 +326,7 @@ func (e *Executor) StreamExecute( // the framework currently sends all results as one packet. byteCount := 0 if len(qr.Fields) > 0 { + result.Fields = qr.Fields if err := callback(qr.Metadata()); err != nil { return err } diff --git a/go/vt/vtgate/executor_select_test.go b/go/vt/vtgate/executor_select_test.go index b9139556f8c..3bffe39c5ee 100644 --- a/go/vt/vtgate/executor_select_test.go +++ b/go/vt/vtgate/executor_select_test.go @@ -673,6 +673,10 @@ func TestStreamBuffering(t *testing.T) { {Name: "col", Type: sqltypes.VarChar, Charset: uint32(collations.MySQL8().DefaultConnectionCharset())}, }, }, { + Fields: []*querypb.Field{ + {Name: "id", Type: sqltypes.Int32, Charset: collations.CollationBinaryID, Flags: uint32(querypb.MySqlFlag_NUM_FLAG)}, + {Name: "col", Type: sqltypes.VarChar, Charset: uint32(collations.MySQL8().DefaultConnectionCharset())}, + }, Rows: [][]sqltypes.Value{{ sqltypes.NewInt32(1), sqltypes.NewVarChar("01234567890123456789"), diff --git a/go/vt/vtgate/executorcontext/vcursor_impl.go b/go/vt/vtgate/executorcontext/vcursor_impl.go index 0b3ab09b8cc..806926234dd 100644 --- a/go/vt/vtgate/executorcontext/vcursor_impl.go +++ b/go/vt/vtgate/executorcontext/vcursor_impl.go @@ -286,12 +286,6 @@ func (vc *VCursorImpl) CloneForMirroring(ctx context.Context) engine.VCursor { } func (vc *VCursorImpl) CloneForReplicaWarming(ctx context.Context) engine.VCursor { - callerId := callerid.EffectiveCallerIDFromContext(ctx) - immediateCallerId := callerid.ImmediateCallerIDFromContext(ctx) - - timedCtx, _ := context.WithTimeout(context.Background(), vc.config.WarmingReadsTimeout) // nolint - clonedCtx := callerid.NewContext(timedCtx, callerId, immediateCallerId) - v := &VCursorImpl{ config: vc.config, SafeSession: NewAutocommitSession(vc.SafeSession.Session), @@ -302,7 +296,7 @@ func (vc *VCursorImpl) CloneForReplicaWarming(ctx context.Context) engine.VCurso executor: vc.executor, resolver: vc.resolver, topoServer: vc.topoServer, - logStats: &logstats.LogStats{Ctx: clonedCtx}, + logStats: &logstats.LogStats{}, ignoreMaxMemoryRows: vc.ignoreMaxMemoryRows, vschema: vc.vschema, @@ -317,6 +311,19 @@ func (vc *VCursorImpl) CloneForReplicaWarming(ctx context.Context) engine.VCurso return v } +func (vc *VCursorImpl) WarmingReadsContext(ctx context.Context) (context.Context, context.CancelFunc) { + callerId := callerid.EffectiveCallerIDFromContext(ctx) + immediateCallerId := callerid.ImmediateCallerIDFromContext(ctx) + + baseCtx := context.WithoutCancel(ctx) + timedCtx, cancel := context.WithTimeout(baseCtx, vc.config.WarmingReadsTimeout) + clonedCtx := callerid.NewContext(timedCtx, callerId, immediateCallerId) + + vc.logStats = &logstats.LogStats{Ctx: clonedCtx} + + return clonedCtx, cancel +} + func (vc *VCursorImpl) cloneWithAutocommitSession() *VCursorImpl { safeSession := vc.SafeSession.NewAutocommitSession() return &VCursorImpl{ @@ -1311,6 +1318,7 @@ func (vc *VCursorImpl) AddAdvisoryLock(name string) { func (vc *VCursorImpl) GetBindVars() map[string]*querypb.BindVariable { return vc.bindVars } + func (vc *VCursorImpl) SetBindVars(m map[string]*querypb.BindVariable) { vc.bindVars = m } diff --git a/go/vt/vtgate/grpcvtgateconn/conn.go b/go/vt/vtgate/grpcvtgateconn/conn.go index 86967de9662..27c7eed3655 100644 --- a/go/vt/vtgate/grpcvtgateconn/conn.go +++ b/go/vt/vtgate/grpcvtgateconn/conn.go @@ -238,6 +238,13 @@ func (a *streamExecuteMultiAdapter) Recv() (*sqltypes.Result, bool, error) { // we reach here, only when it is the last packet. // as in the last packet we receive the session and there is no result } + + // When a new result set starts, clear cached fields from the previous + // result set. + if newResult { + a.fields = nil + } + if err != nil { return nil, newResult, err } diff --git a/go/vt/vtgate/plan_execute.go b/go/vt/vtgate/plan_execute.go index 6e0672d845b..f2dcb05632f 100644 --- a/go/vt/vtgate/plan_execute.go +++ b/go/vt/vtgate/plan_execute.go @@ -19,6 +19,7 @@ package vtgate import ( "context" "fmt" + "slices" "strings" "time" @@ -70,12 +71,6 @@ func (e *Executor) newExecute( execPlan planExec, // used when there is a plan to execute recResult txResult, // used when it's something simple like begin/commit/rollback/savepoint ) (err error) { - // Start an implicit transaction if necessary. - err = e.startTxIfNecessary(ctx, safeSession) - if err != nil { - return err - } - if bindVars == nil { bindVars = make(map[string]*querypb.BindVariable) } @@ -130,6 +125,14 @@ func (e *Executor) newExecute( return err } + // Start an implicit transaction if necessary. This is done after plan + // creation so we can check whether the plan actually accesses real table + // data, matching MySQL's behavior where only data-accessing statements + // start implicit transactions when autocommit=0. + if err = e.startTxIfNecessary(ctx, plan, stmt, safeSession); err != nil { + return err + } + if plan.QueryType != sqlparser.StmtShow { safeSession.ClearWarnings() } @@ -264,8 +267,8 @@ func (e *Executor) handleTransactions( return nil, nil } -func (e *Executor) startTxIfNecessary(ctx context.Context, safeSession *econtext.SafeSession) error { - if !safeSession.Autocommit && !safeSession.InTransaction() { +func (e *Executor) startTxIfNecessary(ctx context.Context, plan *engine.Plan, stmt sqlparser.Statement, safeSession *econtext.SafeSession) error { + if !safeSession.Autocommit && !safeSession.InTransaction() && planStartsImplicitTx(plan, stmt) { if err := e.txConn.Begin(ctx, safeSession, nil); err != nil { return err } @@ -273,6 +276,75 @@ func (e *Executor) startTxIfNecessary(ctx context.Context, safeSession *econtext return nil } +// planStartsImplicitTx returns true if the given plan should start an implicit +// transaction when autocommit is disabled. This matches MySQL's behavior where +// only statements that access real table data start implicit transactions. +// +// The default is to start a transaction (matching the previous behavior), +// and we opt out for specific statement types we've verified against MySQL +// that don't start implicit transactions. +func planStartsImplicitTx(plan *engine.Plan, stmt sqlparser.Statement) bool { + switch plan.QueryType { + case sqlparser.StmtSelect: + // Only start an implicit tx if the plan accesses real tables, not just dual. + return slices.ContainsFunc(plan.TablesUsed, func(table string) bool { + return !strings.HasSuffix(table, ".dual") + }) + case sqlparser.StmtSet, sqlparser.StmtUse: + return false + case sqlparser.StmtShow: + return showStartsImplicitTx(stmt) + case sqlparser.StmtBegin, sqlparser.StmtCommit, sqlparser.StmtRollback, sqlparser.StmtSRollback, sqlparser.StmtRelease: + // Transaction control statements are handled by handleTransactions and should not + // trigger an implicit transaction start. + return false + default: + return true + } +} + +// showStartsImplicitTx returns true for SHOW commands that start implicit +// transactions in MySQL when autocommit=0. Verified experimentally against +// MySQL 8.0. Commands that only read server state (variables, status, +// warnings, engines, plugins, privileges) do not start transactions. +// +// The default is true (start a transaction) for safety — we only return +// false for commands we've explicitly verified against MySQL. +func showStartsImplicitTx(stmt sqlparser.Statement) bool { + show, ok := stmt.(*sqlparser.Show) + if !ok { + return true + } + switch internal := show.Internal.(type) { + case *sqlparser.ShowCreate: + // SHOW CREATE TABLE/DATABASE/etc. do not start implicit transactions in MySQL. + return false + case *sqlparser.ShowOther: + // ShowOther covers SHOW PROCESSLIST, SHOW ENGINE STATUS, SHOW BINARY LOGS, + // SHOW GRANTS, SHOW REPLICA STATUS, etc. These are server-state commands + // that don't start implicit transactions in MySQL. + return false + case *sqlparser.ShowBasic: + // Some SHOW commands do not start implicit transactions in MySQL, but we need to look at the command to determine which ones. + switch internal.Command { + case sqlparser.VariableSession, sqlparser.VariableGlobal, + sqlparser.StatusSession, sqlparser.StatusGlobal, + sqlparser.Warnings, sqlparser.Engines, sqlparser.Plugins, sqlparser.Privilege, + sqlparser.OpenTable, + // Vitess-specific SHOW commands are handled internally by vtgate and don't access InnoDB data. + sqlparser.GtidExecGlobal, sqlparser.VGtidExecGlobal, + sqlparser.VitessMigrations, sqlparser.VitessReplicationStatus, + sqlparser.VitessShards, sqlparser.VitessTablets, sqlparser.VitessTarget, sqlparser.VitessVariables, + sqlparser.VschemaTables, sqlparser.VschemaKeyspaces, sqlparser.VschemaVindexes, sqlparser.Keyspace: + return false + default: + return true + } + default: + return true + } +} + func (e *Executor) insideTransaction(ctx context.Context, safeSession *econtext.SafeSession, logStats *logstats.LogStats, execPlan func() error) error { mustCommit := false if safeSession.Autocommit && !safeSession.InTransaction() { diff --git a/go/vt/vtgate/planbuilder/operators/projection.go b/go/vt/vtgate/planbuilder/operators/projection.go index fb600f5eff0..1ff6b191a82 100644 --- a/go/vt/vtgate/planbuilder/operators/projection.go +++ b/go/vt/vtgate/planbuilder/operators/projection.go @@ -286,18 +286,7 @@ func (p *Projection) addUnexploredExpr(ae *sqlparser.AliasedExpr, e sqlparser.Ex return p.addProjExpr(newProjExprWithInner(ae, e)) } -func (p *Projection) addSubqueryExpr(ctx *plancontext.PlanningContext, ae *sqlparser.AliasedExpr, expr sqlparser.Expr, sqs ...*SubQuery) { - ap, err := p.GetAliasedProjections() - if err != nil { - panic(err) - } - for _, projExpr := range ap { - if ctx.SemTable.EqualsExprWithDeps(projExpr.EvalExpr, expr) { - // if we already have this column, we can just return the offset - return - } - } - +func (p *Projection) addSubqueryExpr(_ *plancontext.PlanningContext, ae *sqlparser.AliasedExpr, expr sqlparser.Expr, sqs ...*SubQuery) { pe := newProjExprWithInner(ae, expr) pe.Info = SubQueryExpression(sqs) diff --git a/go/vt/vtgate/planbuilder/operators/route_planning.go b/go/vt/vtgate/planbuilder/operators/route_planning.go index 200388365bd..5f64d8acff6 100644 --- a/go/vt/vtgate/planbuilder/operators/route_planning.go +++ b/go/vt/vtgate/planbuilder/operators/route_planning.go @@ -44,7 +44,7 @@ func pushDerived(ctx *plancontext.PlanningContext, op *Horizon) (Operator, *Appl return op, NoRewrite } - if !(innerRoute.Routing.OpCode() == engine.EqualUnique) && !op.IsMergeable(ctx) { + if !innerRoute.Routing.OpCode().IsSingleShard() && !op.IsMergeable(ctx) { // no need to check anything if we are sure that we will only hit a single shard return op, NoRewrite } diff --git a/go/vt/vtgate/planbuilder/operators/subquery_builder.go b/go/vt/vtgate/planbuilder/operators/subquery_builder.go index d9c29d936ab..3df5b8d3de5 100644 --- a/go/vt/vtgate/planbuilder/operators/subquery_builder.go +++ b/go/vt/vtgate/planbuilder/operators/subquery_builder.go @@ -343,16 +343,29 @@ func (sqb *SubQueryBuilder) pullOutValueSubqueries( if sqe == nil { return nil, nil } - var newSubqs []*SubQuery + var allSubqs []*SubQuery for idx, subq := range sqe.subq { - sqInner := createSubquery(ctx, original, subq, outerID, original, sqe.cols[idx], sqe.pullOutCode[idx], true) - newSubqs = append(newSubqs, sqInner) + argName := sqe.cols[idx] + if existing := sqb.findByArgName(argName); existing != nil { + allSubqs = append(allSubqs, existing) + continue + } + sqInner := createSubquery(ctx, original, subq, outerID, original, argName, sqe.pullOutCode[idx], true) + allSubqs = append(allSubqs, sqInner) + sqb.Inner = append(sqb.Inner, sqInner) } - sqb.Inner = append(sqb.Inner, newSubqs...) + return sqe.new, allSubqs +} - return sqe.new, newSubqs +func (sqb *SubQueryBuilder) findByArgName(name string) *SubQuery { + for _, sq := range sqb.Inner { + if sq.ArgName == name { + return sq + } + } + return nil } type subqueryExtraction struct { diff --git a/go/vt/vtgate/planbuilder/operators/union.go b/go/vt/vtgate/planbuilder/operators/union.go index 0c7ecc97bc3..0731d8c888e 100644 --- a/go/vt/vtgate/planbuilder/operators/union.go +++ b/go/vt/vtgate/planbuilder/operators/union.go @@ -19,10 +19,12 @@ package operators import ( "fmt" "slices" + "strings" "vitess.io/vitess/go/slice" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/predicates" "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" ) @@ -100,14 +102,10 @@ func (u *Union) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser.Ex if !ok { panic(vterrors.VT12001("pushing predicates on UNION where the first SELECT contains * or NEXT")) } - offsets[ae.ColumnName()] = i - } - - needsFilter, exprPerSource := u.predicatePerSource(expr, offsets) - if needsFilter { - return newFilter(u, expr) + offsets[strings.ToLower(ae.ColumnName())] = i } + exprPerSource := u.predicatePerSource(ctx, expr, offsets) for i, src := range u.Sources { u.Sources[i] = src.AddPredicate(ctx, exprPerSource[i]) } @@ -115,11 +113,20 @@ func (u *Union) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser.Ex return u } -func (u *Union) predicatePerSource(expr sqlparser.Expr, offsets map[string]int) (bool, []sqlparser.Expr) { - needsFilter := false +func (u *Union) predicatePerSource(ctx *plancontext.PlanningContext, expr sqlparser.Expr, offsets map[string]int) []sqlparser.Expr { exprPerSource := make([]sqlparser.Expr, len(u.Sources)) + for i := range u.Sources { - predicate := sqlparser.CopyOnRewrite(expr, nil, func(cursor *sqlparser.CopyOnWriteCursor) { + predicate := expr + + if jp, ok := predicate.(*predicates.JoinPredicate); ok { + // Create a new JoinPredicate for each source to keep tracking working + // We can't use `*JoinPredicate.Clone` here as that would update the tracker and overwrite + // the expression for the original predicate + predicate = ctx.PredTracker.NewJoinPredicate(jp.Current()) + } + + predicate = sqlparser.CopyOnRewrite(predicate, nil, func(cursor *sqlparser.CopyOnWriteCursor) { col, ok := cursor.Node().(*sqlparser.ColName) if !ok { return @@ -127,9 +134,7 @@ func (u *Union) predicatePerSource(expr sqlparser.Expr, offsets map[string]int) idx, ok := offsets[col.Name.Lowered()] if !ok { - needsFilter = true - cursor.StopTreeWalk() - return + panic(vterrors.VT13001(fmt.Sprintf("could not find the column '%s' on the UNION", sqlparser.String(col)))) } sel := u.GetSelectFor(i) @@ -137,12 +142,14 @@ func (u *Union) predicatePerSource(expr sqlparser.Expr, offsets map[string]int) if !ok { panic(vterrors.VT09015()) } + cursor.Replace(ae.Expr) }, nil).(sqlparser.Expr) exprPerSource[i] = predicate } - return needsFilter, exprPerSource + + return exprPerSource } func (u *Union) GetSelectFor(source int) *sqlparser.Select { diff --git a/go/vt/vtgate/planbuilder/testdata/dml_cases.json b/go/vt/vtgate/planbuilder/testdata/dml_cases.json index 370d24af4f3..b8633ecc9ba 100644 --- a/go/vt/vtgate/planbuilder/testdata/dml_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/dml_cases.json @@ -4038,7 +4038,7 @@ { "comment": "insert using select with more columns in select after accounting for star column", "query": "insert into music(id, user_id) select id, *, 2 from user", - "plan": "VT03006: column count does not match value count with the row", + "plan": "syntax error at position 44", "skip_e2e": true }, { diff --git a/go/vt/vtgate/planbuilder/testdata/reference_cases.json b/go/vt/vtgate/planbuilder/testdata/reference_cases.json index 424f80417f9..b14d85121c6 100644 --- a/go/vt/vtgate/planbuilder/testdata/reference_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/reference_cases.json @@ -934,5 +934,28 @@ "user.music" ] } + }, + { + "comment": "Derived table pushdown optimization", + "query": "SELECT * FROM (SELECT DISTINCT col FROM user.ref WHERE col = 1 LIMIT 10) as sub", + "plan": { + "Type": "Passthrough", + "QueryType": "SELECT", + "Original": "SELECT * FROM (SELECT DISTINCT col FROM user.ref WHERE col = 1 LIMIT 10) as sub", + "Instructions": { + "OperatorType": "Route", + "Variant": "Reference", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select col from (select col from ref where 1 != 1) as sub where 1 != 1", + "Query": "select col from (select distinct col from ref where col = 1 limit 10) as sub", + "Table": "ref" + }, + "TablesUsed": [ + "user.ref" + ] + } } -] +] \ No newline at end of file diff --git a/go/vt/vtgate/planbuilder/testdata/select_cases.json b/go/vt/vtgate/planbuilder/testdata/select_cases.json index a10274cbc78..edd1a315eba 100644 --- a/go/vt/vtgate/planbuilder/testdata/select_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/select_cases.json @@ -5548,6 +5548,63 @@ ] } }, + { + "comment": "Duplicate uncorrelated subqueries should not be deduplicated in the projection", + "query": "SELECT (SELECT count(*) FROM user_extra), (SELECT count(*) FROM user_extra) FROM user WHERE id = 1", + "plan": { + "Type": "Complex", + "QueryType": "SELECT", + "Original": "SELECT (SELECT count(*) FROM user_extra), (SELECT count(*) FROM user_extra) FROM user WHERE id = 1", + "Instructions": { + "OperatorType": "UncorrelatedSubquery", + "Variant": "PulloutValue", + "PulloutVars": [ + "__sq1" + ], + "Inputs": [ + { + "InputName": "SubQuery", + "OperatorType": "Aggregate", + "Variant": "Scalar", + "Aggregates": "sum_count_star(0) AS count(*)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select count(*) from user_extra where 1 != 1", + "Query": "select count(*) from user_extra", + "Table": "user_extra" + } + ] + }, + { + "InputName": "Outer", + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select :__sq1 /* INT64 */ as `(select count(*) from user_extra)`, :__sq1 /* INT64 */ as `(select count(*) from user_extra)` from `user` where 1 != 1", + "Query": "select :__sq1 /* INT64 */ as `(select count(*) from user_extra)`, :__sq1 /* INT64 */ as `(select count(*) from user_extra)` from `user` where id = 1", + "Table": "`user`", + "Values": [ + "1" + ], + "Vindex": "user_index" + } + ] + }, + "TablesUsed": [ + "user.user", + "user.user_extra" + ] + } + }, { "comment": "(OR 1 = 0) doesn't cause unnecessary scatter", "query": "select * from user where id = 1 or 1 = 0", diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index 0cf8defd671..6fccfba3eb7 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -1357,45 +1357,39 @@ "QueryType": "SELECT", "Original": "select * from (select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `COLUMN_NAME` = 'primary'", "Instructions": { - "OperatorType": "Filter", - "Predicate": "`COLUMN_NAME` = 'primary'", + "OperatorType": "Distinct", + "Collations": [ + "0: utf8mb3_general_ci" + ], "Inputs": [ { - "OperatorType": "Distinct", - "Collations": [ - "0: utf8mb3_general_ci" - ], + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select kcu.`COLUMN_NAME` from information_schema.key_column_usage as kcu where 1 != 1", - "Query": "select distinct kcu.`COLUMN_NAME` from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.`table_name` = :kcu_table_name /* VARCHAR */", - "SysTableTableName": "[kcu_table_name:'user_extra']", - "SysTableTableSchema": "['user']", - "Table": "information_schema.key_column_usage" - }, - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select kcu.`COLUMN_NAME` from information_schema.key_column_usage as kcu where 1 != 1", - "Query": "select distinct kcu.`COLUMN_NAME` from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.`table_name` = :kcu_table_name1 /* VARCHAR */", - "SysTableTableName": "[kcu_table_name1:'music']", - "SysTableTableSchema": "['user']", - "Table": "information_schema.key_column_usage" - } - ] + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select kcu.`COLUMN_NAME` from information_schema.key_column_usage as kcu where 1 != 1", + "Query": "select distinct kcu.`COLUMN_NAME` from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.`table_name` = :kcu_table_name /* VARCHAR */ and `COLUMN_NAME` = 'primary'", + "SysTableTableName": "[kcu_table_name:'user_extra']", + "SysTableTableSchema": "['user']", + "Table": "information_schema.key_column_usage" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select kcu.`COLUMN_NAME` from information_schema.key_column_usage as kcu where 1 != 1", + "Query": "select distinct kcu.`COLUMN_NAME` from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.`table_name` = :kcu_table_name1 /* VARCHAR */ and `COLUMN_NAME` = 'primary'", + "SysTableTableName": "[kcu_table_name1:'music']", + "SysTableTableSchema": "['user']", + "Table": "information_schema.key_column_usage" } ] } @@ -1439,56 +1433,50 @@ "QueryType": "SELECT", "Original": "select * from (select * from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select * from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `constraint_name` = 'primary'", "Instructions": { - "OperatorType": "Filter", - "Predicate": "`constraint_name` = 'primary'", + "OperatorType": "Distinct", + "Collations": [ + "0: utf8mb3_general_ci", + "1: utf8mb3_general_ci", + "2: utf8mb3_general_ci", + "3: utf8mb3_general_ci", + "4: utf8mb3_general_ci", + "5: utf8mb3_general_ci", + "6: utf8mb3_general_ci", + "7", + "8", + "9: utf8mb3_general_ci", + "10: utf8mb3_general_ci", + "11: utf8mb3_general_ci" + ], "Inputs": [ { - "OperatorType": "Distinct", - "Collations": [ - "0: utf8mb3_general_ci", - "1: utf8mb3_general_ci", - "2: utf8mb3_general_ci", - "3: utf8mb3_general_ci", - "4: utf8mb3_general_ci", - "5: utf8mb3_general_ci", - "6: utf8mb3_general_ci", - "7", - "8", - "9: utf8mb3_general_ci", - "10: utf8mb3_general_ci", - "11: utf8mb3_general_ci" - ], + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select `CONSTRAINT_CATALOG`, `CONSTRAINT_SCHEMA`, `CONSTRAINT_NAME`, TABLE_CATALOG, TABLE_SCHEMA, `TABLE_NAME`, `COLUMN_NAME`, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1", - "Query": "select distinct `CONSTRAINT_CATALOG`, `CONSTRAINT_SCHEMA`, `CONSTRAINT_NAME`, TABLE_CATALOG, TABLE_SCHEMA, `TABLE_NAME`, `COLUMN_NAME`, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.`table_name` = :kcu_table_name /* VARCHAR */", - "SysTableTableName": "[kcu_table_name:'user_extra']", - "SysTableTableSchema": "['user']", - "Table": "information_schema.key_column_usage" - }, - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select `CONSTRAINT_CATALOG`, `CONSTRAINT_SCHEMA`, `CONSTRAINT_NAME`, TABLE_CATALOG, TABLE_SCHEMA, `TABLE_NAME`, `COLUMN_NAME`, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1", - "Query": "select distinct `CONSTRAINT_CATALOG`, `CONSTRAINT_SCHEMA`, `CONSTRAINT_NAME`, TABLE_CATALOG, TABLE_SCHEMA, `TABLE_NAME`, `COLUMN_NAME`, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.`table_name` = :kcu_table_name1 /* VARCHAR */", - "SysTableTableName": "[kcu_table_name1:'music']", - "SysTableTableSchema": "['user']", - "Table": "information_schema.key_column_usage" - } - ] + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select `CONSTRAINT_CATALOG`, `CONSTRAINT_SCHEMA`, `CONSTRAINT_NAME`, TABLE_CATALOG, TABLE_SCHEMA, `TABLE_NAME`, `COLUMN_NAME`, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1", + "Query": "select distinct `CONSTRAINT_CATALOG`, `CONSTRAINT_SCHEMA`, `CONSTRAINT_NAME`, TABLE_CATALOG, TABLE_SCHEMA, `TABLE_NAME`, `COLUMN_NAME`, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.`table_name` = :kcu_table_name /* VARCHAR */ and `CONSTRAINT_NAME` = 'primary'", + "SysTableTableName": "[kcu_table_name:'user_extra']", + "SysTableTableSchema": "['user']", + "Table": "information_schema.key_column_usage" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select `CONSTRAINT_CATALOG`, `CONSTRAINT_SCHEMA`, `CONSTRAINT_NAME`, TABLE_CATALOG, TABLE_SCHEMA, `TABLE_NAME`, `COLUMN_NAME`, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1", + "Query": "select distinct `CONSTRAINT_CATALOG`, `CONSTRAINT_SCHEMA`, `CONSTRAINT_NAME`, TABLE_CATALOG, TABLE_SCHEMA, `TABLE_NAME`, `COLUMN_NAME`, ORDINAL_POSITION, POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.`table_name` = :kcu_table_name1 /* VARCHAR */ and `CONSTRAINT_NAME` = 'primary'", + "SysTableTableName": "[kcu_table_name1:'music']", + "SysTableTableSchema": "['user']", + "Table": "information_schema.key_column_usage" } ] } @@ -2086,5 +2074,79 @@ "user.user" ] } + }, + { + "comment": "join with derived table containing UNION with aliased columns across different keyspaces", + "query": "select u.id from user as u join (select id as pid from user where id = 1 union select id as pid from unsharded where id = 1) as i on u.id = i.pid", + "plan": { + "Type": "Join", + "QueryType": "SELECT", + "Original": "select u.id from user as u join (select id as pid from user where id = 1 union select id as pid from unsharded where id = 1) as i on u.id = i.pid", + "Instructions": { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0", + "JoinVars": { + "u_id": 0 + }, + "TableName": "`user`_`user`_unsharded", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select u.id from `user` as u where 1 != 1", + "Query": "select u.id from `user` as u", + "Table": "`user`" + }, + { + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select dt.c0 as pid, weight_string(dt.c0) from (select id as pid from `user` where 1 != 1) as dt(c0) where 1 != 1", + "Query": "select dt.c0 as pid, weight_string(dt.c0) from (select distinct id as pid from `user` where id = 1 and id = :u_id) as dt(c0)", + "Table": "`user`", + "Values": [ + ":u_id" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select dt.c0 as pid, weight_string(dt.c0) from (select id as pid from unsharded where 1 != 1) as dt(c0) where 1 != 1", + "Query": "select dt.c0 as pid, weight_string(dt.c0) from (select distinct id as pid from unsharded where id = 1 and id = :u_id) as dt(c0)", + "Table": "unsharded" + } + ] + } + ] + } + ] + }, + "TablesUsed": [ + "main.unsharded", + "user.user" + ] + } } ] diff --git a/go/vt/vtgate/planbuilder/testdata/unknown_schema_cases.json b/go/vt/vtgate/planbuilder/testdata/unknown_schema_cases.json index df4459d9e0f..b3e0e78c3ef 100644 --- a/go/vt/vtgate/planbuilder/testdata/unknown_schema_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/unknown_schema_cases.json @@ -47,7 +47,7 @@ { "comment": "ORDER BY on select multi *", "query": "select *, name, *, col from user order by col", - "plan": "VT09015: schema tracking required" + "plan": "syntax error at position 18" }, { "comment": "Group by column number, used with non-aliased expression (duplicated code)", diff --git a/go/vt/vtgate/plugin_mysql_server.go b/go/vt/vtgate/plugin_mysql_server.go index 265d8b7c9cb..8e102b6689b 100644 --- a/go/vt/vtgate/plugin_mysql_server.go +++ b/go/vt/vtgate/plugin_mysql_server.go @@ -128,6 +128,10 @@ func newVtgateHandler(vtg *VTGate) *vtgateHandler { } func (vh *vtgateHandler) NewConnection(c *mysql.Conn) { + // Match VTGate's default session state (Autocommit: true) so the + // handshake packet reports correct status flags to the client. + c.StatusFlags |= mysql.ServerStatusAutocommit + vh.mu.Lock() defer vh.mu.Unlock() vh.connections[c.ConnectionID] = c diff --git a/go/vt/vtgate/plugin_mysql_server_test.go b/go/vt/vtgate/plugin_mysql_server_test.go index a77d66d32b0..7b13ce2d7a6 100644 --- a/go/vt/vtgate/plugin_mysql_server_test.go +++ b/go/vt/vtgate/plugin_mysql_server_test.go @@ -198,6 +198,20 @@ func TestConnectionRespectsExistingUnixSocket(t *testing.T) { } } +func TestNewConnectionSetsAutocommitStatusFlag(t *testing.T) { + vh := &vtgateHandler{ + connections: make(map[uint32]*mysql.Conn), + } + + c := &mysql.Conn{} + assert.Zero(t, c.StatusFlags, "StatusFlags should be zero before NewConnection") + + vh.NewConnection(c) + + assert.True(t, c.StatusFlags&mysql.ServerStatusAutocommit != 0, + "NewConnection should set ServerStatusAutocommit flag to match VTGate's default session state") +} + var newSpanOK = func(ctx context.Context, label string) (trace.Span, context.Context) { return trace.NoopSpan{}, context.Background() } @@ -565,6 +579,14 @@ func TestComQueryMulti(t *testing.T) { }, { QueryResult: &sqltypes.Result{ + Fields: []*querypb.Field{ + { + Name: "1", + Type: sqltypes.Int64, + Flags: uint32(querypb.MySqlFlag_NUM_FLAG | querypb.MySqlFlag_NOT_NULL_FLAG), + Charset: collations.CollationBinaryID, + }, + }, Rows: [][]sqltypes.Value{ { sqltypes.NewInt64(1), @@ -610,6 +632,14 @@ func TestComQueryMulti(t *testing.T) { }, { QueryResult: &sqltypes.Result{ + Fields: []*querypb.Field{ + { + Name: "1", + Type: sqltypes.Int64, + Flags: uint32(querypb.MySqlFlag_NUM_FLAG | querypb.MySqlFlag_NOT_NULL_FLAG), + Charset: collations.CollationBinaryID, + }, + }, Rows: [][]sqltypes.Value{ { sqltypes.NewInt64(1), @@ -646,6 +676,14 @@ func TestComQueryMulti(t *testing.T) { }, { QueryResult: &sqltypes.Result{ + Fields: []*querypb.Field{ + { + Name: "2", + Type: sqltypes.Int64, + Flags: uint32(querypb.MySqlFlag_NUM_FLAG | querypb.MySqlFlag_NOT_NULL_FLAG), + Charset: collations.CollationBinaryID, + }, + }, Rows: [][]sqltypes.Value{ { sqltypes.NewInt64(2), @@ -682,6 +720,14 @@ func TestComQueryMulti(t *testing.T) { }, { QueryResult: &sqltypes.Result{ + Fields: []*querypb.Field{ + { + Name: "3", + Type: sqltypes.Int64, + Flags: uint32(querypb.MySqlFlag_NUM_FLAG | querypb.MySqlFlag_NOT_NULL_FLAG), + Charset: collations.CollationBinaryID, + }, + }, Rows: [][]sqltypes.Value{ { sqltypes.NewInt64(3), @@ -727,6 +773,14 @@ func TestComQueryMulti(t *testing.T) { }, { QueryResult: &sqltypes.Result{ + Fields: []*querypb.Field{ + { + Name: "1", + Type: sqltypes.Int64, + Flags: uint32(querypb.MySqlFlag_NUM_FLAG | querypb.MySqlFlag_NOT_NULL_FLAG), + Charset: collations.CollationBinaryID, + }, + }, Rows: [][]sqltypes.Value{ { sqltypes.NewInt64(1), @@ -763,6 +817,14 @@ func TestComQueryMulti(t *testing.T) { }, { QueryResult: &sqltypes.Result{ + Fields: []*querypb.Field{ + { + Name: "2", + Type: sqltypes.Int64, + Flags: uint32(querypb.MySqlFlag_NUM_FLAG | querypb.MySqlFlag_NOT_NULL_FLAG), + Charset: collations.CollationBinaryID, + }, + }, Rows: [][]sqltypes.Value{ { sqltypes.NewInt64(2), diff --git a/go/vt/vtgate/sandbox_test.go b/go/vt/vtgate/sandbox_test.go index 6030de2ba59..f2f6e974bac 100644 --- a/go/vt/vtgate/sandbox_test.go +++ b/go/vt/vtgate/sandbox_test.go @@ -297,6 +297,11 @@ func (sct *sandboxTopo) WatchSrvVSchema(ctx context.Context, cell string, callba return } + // Context may already be canceled during test cleanup - exit gracefully. + if ctx.Err() != nil { + return + } + // Update the backing topo server with the current sandbox vschemas. for ks := range ksToSandbox { ksvs := &topo.KeyspaceVSchemaInfo{ @@ -304,12 +309,23 @@ func (sct *sandboxTopo) WatchSrvVSchema(ctx context.Context, cell string, callba Keyspace: srvVSchema.Keyspaces[ks], } if err := sct.topoServer.SaveVSchema(ctx, ksvs); err != nil { + if ctx.Err() != nil { + return + } panic(fmt.Sprintf("sandboxTopo SaveVSchema returned an error: %v", err)) } } - sct.topoServer.UpdateSrvVSchema(ctx, cell, srvVSchema) + if err := sct.topoServer.UpdateSrvVSchema(ctx, cell, srvVSchema); err != nil { + if ctx.Err() != nil { + return + } + panic(fmt.Sprintf("sandboxTopo UpdateSrvVSchema returned an error: %v", err)) + } current, updateChan, err := sct.topoServer.WatchSrvVSchema(ctx, cell) if err != nil { + if ctx.Err() != nil { + return + } panic(fmt.Sprintf("sandboxTopo WatchSrvVSchema returned an error: %v", err)) } if !callback(current.Value, nil) { diff --git a/go/vt/vtgate/schema/tracker_test.go b/go/vt/vtgate/schema/tracker_test.go index 6feeacb6864..90235ab4583 100644 --- a/go/vt/vtgate/schema/tracker_test.go +++ b/go/vt/vtgate/schema/tracker_test.go @@ -194,7 +194,7 @@ func TestTrackerNoLock(t *testing.T) { for i := 0; i < 500000; i++ { select { case ch <- th: - case <-time.After(10 * time.Millisecond): + case <-time.After(50 * time.Millisecond): t.Fatalf("failed to send health check to tracker") } } diff --git a/go/vt/vtgate/semantics/analyzer_test.go b/go/vt/vtgate/semantics/analyzer_test.go index 72b9ad83eb4..3f1ff88c9df 100644 --- a/go/vt/vtgate/semantics/analyzer_test.go +++ b/go/vt/vtgate/semantics/analyzer_test.go @@ -940,6 +940,9 @@ func TestInvalidQueries(t *testing.T) { sql: "select sql_calc_found_rows id from a union select 1 limit 109", err: &UnionWithSQLCalcFoundRowsError{}, serr: "VT12001: unsupported: SQL_CALC_FOUND_ROWS not supported with union", + }, { + sql: "select 1 union select *, m from t1", + err: &UnionColumnsDoNotMatchError{FirstProj: 1, SecondProj: 2}, }, { sql: "select * from (select sql_calc_found_rows id from a) as t", serr: "Incorrect usage/placement of 'SQL_CALC_FOUND_ROWS'", diff --git a/go/vt/vtgate/semantics/early_rewriter_test.go b/go/vt/vtgate/semantics/early_rewriter_test.go index 074deb39f64..3b00ce77e82 100644 --- a/go/vt/vtgate/semantics/early_rewriter_test.go +++ b/go/vt/vtgate/semantics/early_rewriter_test.go @@ -769,10 +769,6 @@ func TestSemTableDependenciesAfterExpandStar(t *testing.T) { otherTbl int expandedCol int }{{ - sql: "select a, * from t1", - expSQL: "select a, a from t1", - otherTbl: -1, sameTbl: 0, expandedCol: 1, - }, { sql: "select t2.a, t1.a, t1.* from t1, t2", expSQL: "select t2.a, t1.a, t1.a from t1, t2", otherTbl: 0, sameTbl: 1, expandedCol: 2, diff --git a/go/vt/vtgate/semantics/table_collector.go b/go/vt/vtgate/semantics/table_collector.go index 4eed6f4eb93..a91a29bd342 100644 --- a/go/vt/vtgate/semantics/table_collector.go +++ b/go/vt/vtgate/semantics/table_collector.go @@ -175,6 +175,9 @@ func (tc *tableCollector) visitUnion(union *sqlparser.Union) error { err = sqlparser.VisitAllSelects(union, func(s *sqlparser.Select, idx int) error { for i, expr := range s.GetColumns() { + if i >= size { + return &UnionColumnsDoNotMatchError{FirstProj: size, SecondProj: len(s.GetColumns())} + } ae, ok := expr.(*sqlparser.AliasedExpr) if !ok { continue diff --git a/go/vt/vtgate/vtgate_test.go b/go/vt/vtgate/vtgate_test.go index eea3618cec9..d1a53d324c2 100644 --- a/go/vt/vtgate/vtgate_test.go +++ b/go/vt/vtgate/vtgate_test.go @@ -271,7 +271,8 @@ func TestVTGateStreamExecute(t *testing.T) { want := []*sqltypes.Result{{ Fields: sandboxconn.StreamRowResult.Fields, }, { - Rows: sandboxconn.StreamRowResult.Rows, + Fields: sandboxconn.StreamRowResult.Fields, + Rows: sandboxconn.StreamRowResult.Rows, }} utils.MustMatch(t, want, qrs) if !proto.Equal(sbc.Options[0], executeOptions) { diff --git a/go/vt/vtorc/inst/analysis.go b/go/vt/vtorc/inst/analysis.go index f6948ad89f4..9497dc20d45 100644 --- a/go/vt/vtorc/inst/analysis.go +++ b/go/vt/vtorc/inst/analysis.go @@ -21,6 +21,7 @@ import ( "time" topodatapb "vitess.io/vitess/go/vt/proto/topodata" + "vitess.io/vitess/go/vt/vtctl/reparentutil/policy" "vitess.io/vitess/go/vt/vtorc/config" ) @@ -59,6 +60,10 @@ const ( PrimarySemiSyncBlocked AnalysisCode = "PrimarySemiSyncBlocked" ErrantGTIDDetected AnalysisCode = "ErrantGTIDDetected" PrimaryDiskStalled AnalysisCode = "PrimaryDiskStalled" + + // StaleTopoPrimary describes when a tablet still has the type PRIMARY in the topology when a newer primary + // has been elected. VTOrc should demote this primary to a replica. + StaleTopoPrimary AnalysisCode = "StaleTopoPrimary" ) type StructureAnalysisCode string @@ -80,20 +85,26 @@ const ( // Key of this map is a InstanceAnalysis.String() type PeerAnalysisMap map[string]int -type ReplicationAnalysisHints struct { +type DetectionAnalysisHints struct { AuditAnalysis bool } -// ReplicationAnalysis notes analysis on replication chain status, per instance -type ReplicationAnalysis struct { +// DetectionAnalysis notes analysis on replication chain status, per instance +type DetectionAnalysis struct { AnalyzedInstanceAlias string AnalyzedInstancePrimaryAlias string - TabletType topodatapb.TabletType - CurrentTabletType topodatapb.TabletType - PrimaryTimeStamp time.Time - ClusterDetails ClusterInfo - AnalyzedKeyspace string - AnalyzedShard string + + // TabletType is the tablet's type as seen in the topology. + TabletType topodatapb.TabletType + + // CurrentTabletType is the type this tablet is currently running as. + CurrentTabletType topodatapb.TabletType + + PrimaryTimeStamp time.Time + ClusterDetails ClusterInfo + AnalyzedKeyspace string + AnalyzedShard string + // ShardPrimaryTermTimestamp is the primary term start time stored in the shard record. ShardPrimaryTermTimestamp string AnalyzedInstanceBinlogCoordinates BinlogCoordinates @@ -104,11 +115,13 @@ type ReplicationAnalysis struct { CountReplicas uint CountValidReplicas uint CountValidReplicatingReplicas uint + CountValidSemiSyncReplicatingReplicas uint ReplicationStopped bool ErrantGTID string ReplicaNetTimeout int32 HeartbeatInterval float64 Analysis AnalysisCode + AnalysisMatchedProblems []*DetectionAnalysisProblemMeta Description string StructureAnalysis []StructureAnalysisCode OracleGTIDImmediateTopology bool @@ -137,11 +150,21 @@ type ReplicationAnalysis struct { IsDiskStalled bool } -func (replicationAnalysis *ReplicationAnalysis) MarshalJSON() ([]byte, error) { +// hasMinSemiSyncAckers returns true if there are a minimum number of semi-sync ackers enabled and replicating. +// True is always returned if the durability policy does not require semi-sync ackers (eg: "none"). This gives +// a useful signal if it is safe to enable semi-sync without risk of stalling ongoing PRIMARY writes. +func hasMinSemiSyncAckers(durabler policy.Durabler, primary *topodatapb.Tablet, analysis *DetectionAnalysis) bool { + if durabler == nil || analysis == nil { + return false + } + return int(analysis.CountValidSemiSyncReplicatingReplicas) >= durabler.SemiSyncAckers(primary) +} + +func (detectionAnalysis *DetectionAnalysis) MarshalJSON() ([]byte, error) { i := struct { - ReplicationAnalysis + DetectionAnalysis }{} - i.ReplicationAnalysis = *replicationAnalysis + i.DetectionAnalysis = *detectionAnalysis return json.Marshal(i) } diff --git a/go/vt/vtorc/inst/analysis_dao.go b/go/vt/vtorc/inst/analysis_dao.go index 0e480f74ee8..f4ba598cb9c 100644 --- a/go/vt/vtorc/inst/analysis_dao.go +++ b/go/vt/vtorc/inst/analysis_dao.go @@ -18,7 +18,6 @@ package inst import ( "fmt" - "math" "time" "github.com/patrickmn/go-cache" @@ -51,23 +50,28 @@ func initializeAnalysisDaoPostConfiguration() { } type clusterAnalysis struct { - hasClusterwideAction bool - totalTablets int - primaryAlias string - durability policy.Durabler + hasShardWideAction bool + totalTablets int + primaryAlias string + + // primaryTimestamp is the most recent primary term start time observed for the shard. + primaryTimestamp time.Time + + // durability is the shard's current durability policy. + durability policy.Durabler } -// GetReplicationAnalysis will check for replication problems (dead primary; unreachable primary; etc) -func GetReplicationAnalysis(keyspace string, shard string, hints *ReplicationAnalysisHints) ([]*ReplicationAnalysis, error) { - var result []*ReplicationAnalysis - appendAnalysis := func(analysis *ReplicationAnalysis) { +// GetDetectionAnalysis will check for replication problems (dead primary; unreachable primary; etc) +func GetDetectionAnalysis(keyspace string, shard string, hints *DetectionAnalysisHints) ([]*DetectionAnalysis, error) { + var result []*DetectionAnalysis + appendAnalysis := func(analysis *DetectionAnalysis) { if analysis.Analysis == NoProblem && len(analysis.StructureAnalysis) == 0 { return } result = append(result, analysis) } - // TODO(sougou); deprecate ReduceReplicationAnalysisCount + // TODO(sougou); deprecate ReduceDetectionAnalysisCount args := sqlutils.Args(config.GetReasonableReplicationLagSeconds(), ValidSecondsFromSeenToLastAttemptedCheck(), config.GetReasonableReplicationLagSeconds(), keyspace, shard) query := `SELECT vitess_tablet.info AS tablet_info, @@ -189,6 +193,15 @@ func GetReplicationAnalysis(keyspace string, shard string, hints *ReplicationAna ), 0 ) AS count_valid_semi_sync_replicas, + IFNULL( + SUM( + replica_instance.last_checked <= replica_instance.last_seen + AND replica_instance.replica_io_running != 0 + AND replica_instance.replica_sql_running != 0 + AND replica_instance.semi_sync_replica_enabled != 0 + ), + 0 + ) AS count_valid_semi_sync_replicating_replicas, IFNULL( SUM( replica_instance.log_bin @@ -278,7 +291,7 @@ func GetReplicationAnalysis(keyspace string, shard string, hints *ReplicationAna clusters := make(map[string]*clusterAnalysis) err := db.Db.QueryVTOrc(query, args, func(m sqlutils.RowMap) error { - a := &ReplicationAnalysis{ + a := &DetectionAnalysis{ Analysis: NoProblem, } @@ -343,6 +356,7 @@ func GetReplicationAnalysis(keyspace string, shard string, hints *ReplicationAna a.SemiSyncBlocked = m.GetBool("semi_sync_blocked") a.SemiSyncReplicaEnabled = m.GetBool("semi_sync_replica_enabled") a.CountSemiSyncReplicasEnabled = m.GetUint("count_semi_sync_replicas") + a.CountValidSemiSyncReplicatingReplicas = m.GetUint("count_valid_semi_sync_replicating_replicas") // countValidSemiSyncReplicasEnabled := m.GetUint("count_valid_semi_sync_replicas") a.SemiSyncPrimaryWaitForReplicaCount = m.GetUint("semi_sync_primary_wait_for_replica_count") a.SemiSyncPrimaryClients = m.GetUint("semi_sync_primary_clients") @@ -379,6 +393,7 @@ func GetReplicationAnalysis(keyspace string, shard string, hints *ReplicationAna if a.TabletType == topodatapb.TabletType_PRIMARY { a.IsClusterPrimary = true clusters[keyspaceShard].primaryAlias = a.AnalyzedInstanceAlias + clusters[keyspaceShard].primaryTimestamp = a.PrimaryTimeStamp } durabilityPolicy := m.GetString("durability_policy") if durabilityPolicy == "" { @@ -396,8 +411,8 @@ func GetReplicationAnalysis(keyspace string, shard string, hints *ReplicationAna ca := clusters[keyspaceShard] // Increment the total number of tablets. ca.totalTablets += 1 - if ca.hasClusterwideAction { - // We can only take one cluster level action at a time. + if ca.hasShardWideAction { + // We can only take one shard-wide action at a time. return nil } if ca.durability == nil { @@ -405,139 +420,30 @@ func GetReplicationAnalysis(keyspace string, shard string, hints *ReplicationAna return nil } isInvalid := m.GetBool("is_invalid") - if a.IsClusterPrimary && isInvalid { - a.Analysis = InvalidPrimary - a.Description = "VTOrc hasn't been able to reach the primary even once since restart/shutdown" - } else if isInvalid { - a.Analysis = InvalidReplica - a.Description = "VTOrc hasn't been able to reach the replica even once since restart/shutdown" - } else if a.IsClusterPrimary && !a.LastCheckValid && a.IsDiskStalled { - a.Analysis = PrimaryDiskStalled - a.Description = "Primary has a stalled disk" - ca.hasClusterwideAction = true - } else if a.IsClusterPrimary && !a.LastCheckValid && a.CountReplicas == 0 { - a.Analysis = DeadPrimaryWithoutReplicas - a.Description = "Primary cannot be reached by vtorc and has no replica" - ca.hasClusterwideAction = true - // - } else if a.IsClusterPrimary && !a.LastCheckValid && a.CountValidReplicas == a.CountReplicas && a.CountValidReplicatingReplicas == 0 { - a.Analysis = DeadPrimary - a.Description = "Primary cannot be reached by vtorc and none of its replicas is replicating" - ca.hasClusterwideAction = true - // - } else if a.IsClusterPrimary && !a.LastCheckValid && a.CountReplicas > 0 && a.CountValidReplicas == 0 && a.CountValidReplicatingReplicas == 0 { - a.Analysis = DeadPrimaryAndReplicas - a.Description = "Primary cannot be reached by vtorc and none of its replicas is replicating" - ca.hasClusterwideAction = true - // - } else if a.IsClusterPrimary && !a.LastCheckValid && a.CountValidReplicas < a.CountReplicas && a.CountValidReplicas > 0 && a.CountValidReplicatingReplicas == 0 { - a.Analysis = DeadPrimaryAndSomeReplicas - a.Description = "Primary cannot be reached by vtorc; some of its replicas are unreachable and none of its reachable replicas is replicating" - ca.hasClusterwideAction = true - // - } else if a.IsClusterPrimary && !a.IsPrimary { - a.Analysis = PrimaryHasPrimary - a.Description = "Primary is replicating from somewhere else" - ca.hasClusterwideAction = true - // - } else if a.IsClusterPrimary && a.IsReadOnly { - a.Analysis = PrimaryIsReadOnly - a.Description = "Primary is read-only" - // - } else if a.IsClusterPrimary && policy.SemiSyncAckers(ca.durability, tablet) != 0 && !a.SemiSyncPrimaryEnabled { - a.Analysis = PrimarySemiSyncMustBeSet - a.Description = "Primary semi-sync must be set" - // - } else if a.IsClusterPrimary && policy.SemiSyncAckers(ca.durability, tablet) == 0 && a.SemiSyncPrimaryEnabled { - a.Analysis = PrimarySemiSyncMustNotBeSet - a.Description = "Primary semi-sync must not be set" - // - } else if a.IsClusterPrimary && a.CurrentTabletType != topodatapb.TabletType_UNKNOWN && a.CurrentTabletType != topodatapb.TabletType_PRIMARY { - a.Analysis = PrimaryCurrentTypeMismatch - a.Description = "Primary tablet's current type is not PRIMARY" - } else if topo.IsReplicaType(a.TabletType) && a.ErrantGTID != "" { - a.Analysis = ErrantGTIDDetected - a.Description = "Tablet has errant GTIDs" - } else if topo.IsReplicaType(a.TabletType) && ca.primaryAlias == "" && a.ShardPrimaryTermTimestamp == "" { - // ClusterHasNoPrimary should only be detected when the shard record doesn't have any primary term start time specified either. - a.Analysis = ClusterHasNoPrimary - a.Description = "Cluster has no primary" - ca.hasClusterwideAction = true - } else if topo.IsReplicaType(a.TabletType) && ca.primaryAlias == "" && a.ShardPrimaryTermTimestamp != "" { - // If there are no primary tablets, but the shard primary start time isn't empty, then we know - // the primary tablet was deleted. - a.Analysis = PrimaryTabletDeleted - a.Description = "Primary tablet has been deleted" - ca.hasClusterwideAction = true - } else if a.IsPrimary && a.SemiSyncBlocked && a.CountSemiSyncReplicasEnabled >= a.SemiSyncPrimaryWaitForReplicaCount { - // The primary is reporting that semi-sync monitor is blocked on writes. - // There are enough replicas configured to send semi-sync ACKs such that the primary shouldn't be blocked. - // There is some network diruption in progress. We should run an ERS. - a.Analysis = PrimarySemiSyncBlocked - a.Description = "Writes seem to be blocked on semi-sync acks on the primary, even though sufficient replicas are configured to send ACKs" - ca.hasClusterwideAction = true - } else if topo.IsReplicaType(a.TabletType) && !a.IsReadOnly { - a.Analysis = ReplicaIsWritable - a.Description = "Replica is writable" - // - } else if topo.IsReplicaType(a.TabletType) && a.IsPrimary { - a.Analysis = NotConnectedToPrimary - a.Description = "Not connected to the primary" - // - } else if topo.IsReplicaType(a.TabletType) && !a.IsPrimary && math.Round(a.HeartbeatInterval*2) != float64(a.ReplicaNetTimeout) { - a.Analysis = ReplicaMisconfigured - a.Description = "Replica has been misconfigured" - // - } else if topo.IsReplicaType(a.TabletType) && !a.IsPrimary && ca.primaryAlias != "" && a.AnalyzedInstancePrimaryAlias != ca.primaryAlias { - a.Analysis = ConnectedToWrongPrimary - a.Description = "Connected to wrong primary" - // - } else if topo.IsReplicaType(a.TabletType) && !a.IsPrimary && a.ReplicationStopped { - a.Analysis = ReplicationStopped - a.Description = "Replication is stopped" - // - } else if topo.IsReplicaType(a.TabletType) && !a.IsPrimary && policy.IsReplicaSemiSync(ca.durability, primaryTablet, tablet) && !a.SemiSyncReplicaEnabled { - a.Analysis = ReplicaSemiSyncMustBeSet - a.Description = "Replica semi-sync must be set" - // - } else if topo.IsReplicaType(a.TabletType) && !a.IsPrimary && !policy.IsReplicaSemiSync(ca.durability, primaryTablet, tablet) && a.SemiSyncReplicaEnabled { - a.Analysis = ReplicaSemiSyncMustNotBeSet - a.Description = "Replica semi-sync must not be set" - // - // TODO(sougou): Events below here are either ignored or not possible. - } else if a.IsPrimary && !a.LastCheckValid && a.CountLaggingReplicas == a.CountReplicas && a.CountDelayedReplicas < a.CountReplicas && a.CountValidReplicatingReplicas > 0 { - a.Analysis = UnreachablePrimaryWithLaggingReplicas - a.Description = "Primary cannot be reached by vtorc and all of its replicas are lagging" - // - } else if a.IsPrimary && !a.LastCheckValid && !a.LastCheckPartialSuccess && a.CountValidReplicas > 0 && a.CountValidReplicatingReplicas > 0 { - // partial success is here to reduce noise - a.Analysis = UnreachablePrimary - a.Description = "Primary cannot be reached by vtorc but it has replicating replicas; possibly a network/host issue" - // - } else if a.IsPrimary && a.SemiSyncPrimaryEnabled && a.SemiSyncPrimaryStatus && a.SemiSyncPrimaryWaitForReplicaCount > 0 && a.SemiSyncPrimaryClients < a.SemiSyncPrimaryWaitForReplicaCount { - if isStaleBinlogCoordinates { - a.Analysis = LockedSemiSyncPrimary - a.Description = "Semi sync primary is locked since it doesn't get enough replica acknowledgements" - } else { - a.Analysis = LockedSemiSyncPrimaryHypothesis - a.Description = "Semi sync primary seems to be locked, more samplings needed to validate" + var matchedProblems []*DetectionAnalysisProblem + for _, problem := range detectionAnalysisProblems { + // When isInvalid is true, instance data is unreliable (never been reached). + // Only InvalidPrimary/InvalidReplica should match; postProcessAnalyses + // handles upgrading InvalidPrimary to DeadPrimary if needed. + if isInvalid && problem.Meta.Analysis != InvalidPrimary && problem.Meta.Analysis != InvalidReplica { + continue + } + if problem.HasMatch(a, ca, primaryTablet, tablet, isInvalid, isStaleBinlogCoordinates) { + matchedProblems = append(matchedProblems, problem) + } + } + if len(matchedProblems) > 0 { + sortDetectionAnalysisMatchedProblems(matchedProblems) + for _, problem := range matchedProblems { + a.AnalysisMatchedProblems = append(a.AnalysisMatchedProblems, problem.Meta) } - // - } else if a.IsPrimary && a.LastCheckValid && a.CountReplicas == 1 && a.CountValidReplicas == a.CountReplicas && a.CountValidReplicatingReplicas == 0 { - a.Analysis = PrimarySingleReplicaNotReplicating - a.Description = "Primary is reachable but its single replica is not replicating" - } else if a.IsPrimary && a.LastCheckValid && a.CountReplicas == 1 && a.CountValidReplicas == 0 { - a.Analysis = PrimarySingleReplicaDead - a.Description = "Primary is reachable but its single replica is dead" - // - } else if a.IsPrimary && a.LastCheckValid && a.CountReplicas > 1 && a.CountValidReplicas == a.CountReplicas && a.CountValidReplicatingReplicas == 0 { - a.Analysis = AllPrimaryReplicasNotReplicating - a.Description = "Primary is reachable but none of its replicas is replicating" - // - } else if a.IsPrimary && a.LastCheckValid && a.CountReplicas > 1 && a.CountValidReplicas < a.CountReplicas && a.CountValidReplicas > 0 && a.CountValidReplicatingReplicas == 0 { - a.Analysis = AllPrimaryReplicasNotReplicatingOrDead - a.Description = "Primary is reachable but none of its replicas is replicating" - // + // We return a single problem per tablet. Any remaining problems will be discovered/recovered + // by VTOrc(s) on future polls. Often many problems are resolved by a single recovery of the + // first problem. The first element of matchedProblems is the highest-priority problem. + chosenProblem := matchedProblems[0] + a.Analysis = chosenProblem.Meta.Analysis + a.Description = chosenProblem.Meta.Description + ca.hasShardWideAction = chosenProblem.Meta.Priority == detectionAnalysisPriorityShardWideAction } // else if a.IsPrimary && a.CountReplicas == 0 { // a.Analysis = PrimaryWithoutReplicas @@ -599,12 +505,22 @@ func GetReplicationAnalysis(keyspace string, shard string, hints *ReplicationAna if err != nil { log.Error(err) } - // TODO: result, err = getConcensusReplicationAnalysis(result) + // TODO: result, err = getConcensusDetectionAnalysis(result) return result, err } +// isStaleTopoPrimary returns true when a tablet has type PRIMARY in the topology and has an older primary term +// start time than the shard's current primary. +func isStaleTopoPrimary(tablet *DetectionAnalysis, cluster *clusterAnalysis) bool { + if tablet.TabletType != topodatapb.TabletType_PRIMARY { + return false + } + + return tablet.PrimaryTimeStamp.Before(cluster.primaryTimestamp) +} + // postProcessAnalyses is used to update different analyses based on the information gleaned from looking at all the analyses together instead of individual data. -func postProcessAnalyses(result []*ReplicationAnalysis, clusters map[string]*clusterAnalysis) []*ReplicationAnalysis { +func postProcessAnalyses(result []*DetectionAnalysis, clusters map[string]*clusterAnalysis) []*DetectionAnalysis { for { // Store whether we have changed the result of replication analysis or not. resultChanged := false diff --git a/go/vt/vtorc/inst/analysis_dao_test.go b/go/vt/vtorc/inst/analysis_dao_test.go index b24e15107d4..cdb15d209fc 100644 --- a/go/vt/vtorc/inst/analysis_dao_test.go +++ b/go/vt/vtorc/inst/analysis_dao_test.go @@ -30,27 +30,25 @@ import ( "vitess.io/vitess/go/vt/vtorc/test" ) -var ( - // The initialSQL is a set of insert commands copied from a dump of an actual running VTOrc instances. The relevant insert commands are here. - // This is a dump taken from a test running 4 tablets, zone1-101 is the primary, zone1-100 is a replica, zone1-112 is a rdonly and zone2-200 is a cross-cell replica. - initialSQL = []string{ - `INSERT INTO database_instance VALUES('zone1-0000000112','localhost',6747,3,'2022-12-28 07:26:04','2022-12-28 07:26:04',213696377,'8.0.31','ROW',1,1,'vt-0000000112-bin.000001',15963,'localhost',6714,8,4.0,1,1,'vt-0000000101-bin.000001',15583,'vt-0000000101-bin.000001',15583,0,0,1,'','',1,'vt-0000000112-relay-bin.000002',15815,1,0,'zone1','',0,0,0,1,'729a4cc4-8680-11ed-a104-47706090afbd:1-54','729a5138-8680-11ed-9240-92a06c3be3c2','2022-12-28 07:26:04','',1,0,0,'Homebrew','8.0','FULL',10816929,0,0,'ON',1,'729a4cc4-8680-11ed-a104-47706090afbd','','729a4cc4-8680-11ed-a104-47706090afbd,729a5138-8680-11ed-9240-92a06c3be3c2',1,1,'',1000000000000000000,1,0,0,0,false,false);`, - `INSERT INTO database_instance VALUES('zone1-0000000100','localhost',6711,2,'2022-12-28 07:26:04','2022-12-28 07:26:04',1094500338,'8.0.31','ROW',1,1,'vt-0000000100-bin.000001',15963,'localhost',6714,8,4.0,1,1,'vt-0000000101-bin.000001',15583,'vt-0000000101-bin.000001',15583,0,0,1,'','',1,'vt-0000000100-relay-bin.000002',15815,1,0,'zone1','',0,0,0,1,'729a4cc4-8680-11ed-a104-47706090afbd:1-54','729a5138-8680-11ed-acf8-d6b0ef9f4eaa','2022-12-28 07:26:04','',1,0,0,'Homebrew','8.0','FULL',10103920,0,1,'ON',1,'729a4cc4-8680-11ed-a104-47706090afbd','','729a4cc4-8680-11ed-a104-47706090afbd,729a5138-8680-11ed-acf8-d6b0ef9f4eaa',1,1,'',1000000000000000000,1,0,1,0,false,false);`, - `INSERT INTO database_instance VALUES('zone1-0000000101','localhost',6714,1,'2022-12-28 07:26:04','2022-12-28 07:26:04',390954723,'8.0.31','ROW',1,1,'vt-0000000101-bin.000001',15583,'',0,0,0,0,0,'',0,'',0,NULL,NULL,0,'','',0,'',0,0,0,'zone1','',0,0,0,1,'729a4cc4-8680-11ed-a104-47706090afbd:1-54','729a4cc4-8680-11ed-a104-47706090afbd','2022-12-28 07:26:04','',0,0,0,'Homebrew','8.0','FULL',11366095,1,1,'ON',1,'','','729a4cc4-8680-11ed-a104-47706090afbd',-1,-1,'',1000000000000000000,1,1,0,2,false,false);`, - `INSERT INTO database_instance VALUES('zone2-0000000200','localhost',6756,2,'2022-12-28 07:26:05','2022-12-28 07:26:05',444286571,'8.0.31','ROW',1,1,'vt-0000000200-bin.000001',15963,'localhost',6714,8,4.0,1,1,'vt-0000000101-bin.000001',15583,'vt-0000000101-bin.000001',15583,0,0,1,'','',1,'vt-0000000200-relay-bin.000002',15815,1,0,'zone2','',0,0,0,1,'729a4cc4-8680-11ed-a104-47706090afbd:1-54','729a497c-8680-11ed-8ad4-3f51d747db75','2022-12-28 07:26:05','',1,0,0,'Homebrew','8.0','FULL',10443112,0,1,'ON',1,'729a4cc4-8680-11ed-a104-47706090afbd','','729a4cc4-8680-11ed-a104-47706090afbd,729a497c-8680-11ed-8ad4-3f51d747db75',1,1,'',1000000000000000000,1,0,1,0,false,false);`, - `INSERT INTO vitess_tablet VALUES('zone1-0000000100','localhost',6711,'ks','0','zone1',2,'0001-01-01 00:00:00+00:00',X'616c6961733a7b63656c6c3a227a6f6e653122207569643a3130307d20686f73746e616d653a226c6f63616c686f73742220706f72745f6d61703a7b6b65793a2267727063222076616c75653a363731307d20706f72745f6d61703a7b6b65793a227674222076616c75653a363730397d206b657973706163653a226b73222073686172643a22302220747970653a5245504c494341206d7973716c5f686f73746e616d653a226c6f63616c686f737422206d7973716c5f706f72743a363731312064625f7365727665725f76657273696f6e3a22382e302e3331222064656661756c745f636f6e6e5f636f6c6c6174696f6e3a3435');`, - `INSERT INTO vitess_tablet VALUES('zone1-0000000101','localhost',6714,'ks','0','zone1',1,'2022-12-28 07:23:25.129898+00:00',X'616c6961733a7b63656c6c3a227a6f6e653122207569643a3130317d20686f73746e616d653a226c6f63616c686f73742220706f72745f6d61703a7b6b65793a2267727063222076616c75653a363731337d20706f72745f6d61703a7b6b65793a227674222076616c75653a363731327d206b657973706163653a226b73222073686172643a22302220747970653a5052494d415259206d7973716c5f686f73746e616d653a226c6f63616c686f737422206d7973716c5f706f72743a36373134207072696d6172795f7465726d5f73746172745f74696d653a7b7365636f6e64733a31363732323132323035206e616e6f7365636f6e64733a3132393839383030307d2064625f7365727665725f76657273696f6e3a22382e302e3331222064656661756c745f636f6e6e5f636f6c6c6174696f6e3a3435');`, - `INSERT INTO vitess_tablet VALUES('zone1-0000000112','localhost',6747,'ks','0','zone1',3,'0001-01-01 00:00:00+00:00',X'616c6961733a7b63656c6c3a227a6f6e653122207569643a3131327d20686f73746e616d653a226c6f63616c686f73742220706f72745f6d61703a7b6b65793a2267727063222076616c75653a363734367d20706f72745f6d61703a7b6b65793a227674222076616c75653a363734357d206b657973706163653a226b73222073686172643a22302220747970653a52444f4e4c59206d7973716c5f686f73746e616d653a226c6f63616c686f737422206d7973716c5f706f72743a363734372064625f7365727665725f76657273696f6e3a22382e302e3331222064656661756c745f636f6e6e5f636f6c6c6174696f6e3a3435');`, - `INSERT INTO vitess_tablet VALUES('zone2-0000000200','localhost',6756,'ks','0','zone2',2,'0001-01-01 00:00:00+00:00',X'616c6961733a7b63656c6c3a227a6f6e653222207569643a3230307d20686f73746e616d653a226c6f63616c686f73742220706f72745f6d61703a7b6b65793a2267727063222076616c75653a363735357d20706f72745f6d61703a7b6b65793a227674222076616c75653a363735347d206b657973706163653a226b73222073686172643a22302220747970653a5245504c494341206d7973716c5f686f73746e616d653a226c6f63616c686f737422206d7973716c5f706f72743a363735362064625f7365727665725f76657273696f6e3a22382e302e3331222064656661756c745f636f6e6e5f636f6c6c6174696f6e3a3435');`, - `INSERT INTO vitess_shard VALUES('ks','0','zone1-0000000101','2022-12-28 07:23:25.129898+00:00');`, - `INSERT INTO vitess_keyspace VALUES('ks',0,'semi_sync');`, - } -) +// The initialSQL is a set of insert commands copied from a dump of an actual running VTOrc instances. The relevant insert commands are here. +// This is a dump taken from a test running 4 tablets, zone1-101 is the primary, zone1-100 is a replica, zone1-112 is a rdonly and zone2-200 is a cross-cell replica. +var initialSQL = []string{ + `INSERT INTO database_instance VALUES('zone1-0000000112','localhost',6747,3,'2022-12-28 07:26:04','2022-12-28 07:26:04',213696377,'8.0.31','ROW',1,1,'vt-0000000112-bin.000001',15963,'localhost',6714,8,4.0,1,1,'vt-0000000101-bin.000001',15583,'vt-0000000101-bin.000001',15583,0,0,1,'','',1,'vt-0000000112-relay-bin.000002',15815,1,0,'zone1','',0,0,0,1,'729a4cc4-8680-11ed-a104-47706090afbd:1-54','729a5138-8680-11ed-9240-92a06c3be3c2','2022-12-28 07:26:04','',1,0,0,'Homebrew','8.0','FULL',10816929,0,0,'ON',1,'729a4cc4-8680-11ed-a104-47706090afbd','','729a4cc4-8680-11ed-a104-47706090afbd,729a5138-8680-11ed-9240-92a06c3be3c2',1,1,'',1000000000000000000,1,0,0,0,false,false);`, + `INSERT INTO database_instance VALUES('zone1-0000000100','localhost',6711,2,'2022-12-28 07:26:04','2022-12-28 07:26:04',1094500338,'8.0.31','ROW',1,1,'vt-0000000100-bin.000001',15963,'localhost',6714,8,4.0,1,1,'vt-0000000101-bin.000001',15583,'vt-0000000101-bin.000001',15583,0,0,1,'','',1,'vt-0000000100-relay-bin.000002',15815,1,0,'zone1','',0,0,0,1,'729a4cc4-8680-11ed-a104-47706090afbd:1-54','729a5138-8680-11ed-acf8-d6b0ef9f4eaa','2022-12-28 07:26:04','',1,0,0,'Homebrew','8.0','FULL',10103920,0,1,'ON',1,'729a4cc4-8680-11ed-a104-47706090afbd','','729a4cc4-8680-11ed-a104-47706090afbd,729a5138-8680-11ed-acf8-d6b0ef9f4eaa',1,1,'',1000000000000000000,1,0,1,0,false,false);`, + `INSERT INTO database_instance VALUES('zone1-0000000101','localhost',6714,1,'2022-12-28 07:26:04','2022-12-28 07:26:04',390954723,'8.0.31','ROW',1,1,'vt-0000000101-bin.000001',15583,'',0,0,0,0,0,'',0,'',0,NULL,NULL,0,'','',0,'',0,0,0,'zone1','',0,0,0,1,'729a4cc4-8680-11ed-a104-47706090afbd:1-54','729a4cc4-8680-11ed-a104-47706090afbd','2022-12-28 07:26:04','',0,0,0,'Homebrew','8.0','FULL',11366095,1,1,'ON',1,'','','729a4cc4-8680-11ed-a104-47706090afbd',-1,-1,'',1000000000000000000,1,1,0,2,false,false);`, + `INSERT INTO database_instance VALUES('zone2-0000000200','localhost',6756,2,'2022-12-28 07:26:05','2022-12-28 07:26:05',444286571,'8.0.31','ROW',1,1,'vt-0000000200-bin.000001',15963,'localhost',6714,8,4.0,1,1,'vt-0000000101-bin.000001',15583,'vt-0000000101-bin.000001',15583,0,0,1,'','',1,'vt-0000000200-relay-bin.000002',15815,1,0,'zone2','',0,0,0,1,'729a4cc4-8680-11ed-a104-47706090afbd:1-54','729a497c-8680-11ed-8ad4-3f51d747db75','2022-12-28 07:26:05','',1,0,0,'Homebrew','8.0','FULL',10443112,0,1,'ON',1,'729a4cc4-8680-11ed-a104-47706090afbd','','729a4cc4-8680-11ed-a104-47706090afbd,729a497c-8680-11ed-8ad4-3f51d747db75',1,1,'',1000000000000000000,1,0,1,0,false,false);`, + `INSERT INTO vitess_tablet VALUES('zone1-0000000100','localhost',6711,'ks','0','zone1',2,'0001-01-01 00:00:00+00:00',X'616c6961733a7b63656c6c3a227a6f6e653122207569643a3130307d20686f73746e616d653a226c6f63616c686f73742220706f72745f6d61703a7b6b65793a2267727063222076616c75653a363731307d20706f72745f6d61703a7b6b65793a227674222076616c75653a363730397d206b657973706163653a226b73222073686172643a22302220747970653a5245504c494341206d7973716c5f686f73746e616d653a226c6f63616c686f737422206d7973716c5f706f72743a363731312064625f7365727665725f76657273696f6e3a22382e302e3331222064656661756c745f636f6e6e5f636f6c6c6174696f6e3a3435');`, + `INSERT INTO vitess_tablet VALUES('zone1-0000000101','localhost',6714,'ks','0','zone1',1,'2022-12-28 07:23:25.129898+00:00',X'616c6961733a7b63656c6c3a227a6f6e653122207569643a3130317d20686f73746e616d653a226c6f63616c686f73742220706f72745f6d61703a7b6b65793a2267727063222076616c75653a363731337d20706f72745f6d61703a7b6b65793a227674222076616c75653a363731327d206b657973706163653a226b73222073686172643a22302220747970653a5052494d415259206d7973716c5f686f73746e616d653a226c6f63616c686f737422206d7973716c5f706f72743a36373134207072696d6172795f7465726d5f73746172745f74696d653a7b7365636f6e64733a31363732323132323035206e616e6f7365636f6e64733a3132393839383030307d2064625f7365727665725f76657273696f6e3a22382e302e3331222064656661756c745f636f6e6e5f636f6c6c6174696f6e3a3435');`, + `INSERT INTO vitess_tablet VALUES('zone1-0000000112','localhost',6747,'ks','0','zone1',3,'0001-01-01 00:00:00+00:00',X'616c6961733a7b63656c6c3a227a6f6e653122207569643a3131327d20686f73746e616d653a226c6f63616c686f73742220706f72745f6d61703a7b6b65793a2267727063222076616c75653a363734367d20706f72745f6d61703a7b6b65793a227674222076616c75653a363734357d206b657973706163653a226b73222073686172643a22302220747970653a52444f4e4c59206d7973716c5f686f73746e616d653a226c6f63616c686f737422206d7973716c5f706f72743a363734372064625f7365727665725f76657273696f6e3a22382e302e3331222064656661756c745f636f6e6e5f636f6c6c6174696f6e3a3435');`, + `INSERT INTO vitess_tablet VALUES('zone2-0000000200','localhost',6756,'ks','0','zone2',2,'0001-01-01 00:00:00+00:00',X'616c6961733a7b63656c6c3a227a6f6e653222207569643a3230307d20686f73746e616d653a226c6f63616c686f73742220706f72745f6d61703a7b6b65793a2267727063222076616c75653a363735357d20706f72745f6d61703a7b6b65793a227674222076616c75653a363735347d206b657973706163653a226b73222073686172643a22302220747970653a5245504c494341206d7973716c5f686f73746e616d653a226c6f63616c686f737422206d7973716c5f706f72743a363735362064625f7365727665725f76657273696f6e3a22382e302e3331222064656661756c745f636f6e6e5f636f6c6c6174696f6e3a3435');`, + `INSERT INTO vitess_shard VALUES('ks','0','zone1-0000000101','2022-12-28 07:23:25.129898+00:00');`, + `INSERT INTO vitess_keyspace VALUES('ks',0,'semi_sync');`, +} -// TestGetReplicationAnalysisDecision tests the code of GetReplicationAnalysis decision-making. It doesn't check the SQL query +// TestGetDetectionAnalysisDecision tests the code of GetDetectionAnalysis decision-making. It doesn't check the SQL query // run by it. It only checks the analysis part after the rows have been read. This tests fakes the db and explicitly returns the // rows that are specified in the test. -func TestGetReplicationAnalysisDecision(t *testing.T) { +func TestGetDetectionAnalysisDecision(t *testing.T) { tests := []struct { name string info []*test.InfoForRecoveryAnalysis @@ -63,7 +61,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { name: "ClusterHasNoPrimary", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -77,11 +75,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: ClusterHasNoPrimary, - }, { + }, + { name: "PrimaryTabletDeleted", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -96,11 +95,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: PrimaryTabletDeleted, - }, { + }, + { name: "StalledDiskPrimary", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -120,11 +120,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: PrimaryDiskStalled, - }, { + }, + { name: "PrimarySemiSyncBlocked", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -149,11 +150,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: PrimarySemiSyncBlocked, - }, { + }, + { name: "LockedSemiSync", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -178,11 +180,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: LockedSemiSyncPrimaryHypothesis, - }, { + }, + { name: "DeadPrimary", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -201,11 +204,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: DeadPrimary, - }, { + }, + { name: "DeadPrimaryWithoutReplicas", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -222,11 +226,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: DeadPrimaryWithoutReplicas, - }, { + }, + { name: "DeadPrimaryAndReplicas", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -243,11 +248,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: DeadPrimaryAndReplicas, - }, { + }, + { name: "DeadPrimaryAndSomeReplicas", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -266,11 +272,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: DeadPrimaryAndSomeReplicas, - }, { + }, + { name: "PrimaryHasPrimary", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -288,11 +295,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: PrimaryHasPrimary, - }, { + }, + { name: "PrimaryIsReadOnly", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -311,11 +319,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: PrimaryIsReadOnly, - }, { + }, + { name: "PrimaryCurrentTypeMismatch", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -333,11 +342,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: PrimaryCurrentTypeMismatch, - }, { + }, + { name: "Unknown tablet type shouldn't run the mismatch recovery analysis", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 101}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -358,11 +368,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: NoProblem, - }, { + }, + { name: "PrimarySemiSyncMustNotBeSet", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -381,11 +392,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: PrimarySemiSyncMustNotBeSet, - }, { + }, + { name: "PrimarySemiSyncMustBeSet", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -393,22 +405,25 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { MysqlHostname: "localhost", MysqlPort: 6709, }, - DurabilityPolicy: policy.DurabilitySemiSync, - LastCheckValid: 1, - CountReplicas: 4, - CountValidReplicas: 4, - IsPrimary: 1, - SemiSyncPrimaryEnabled: 0, - CurrentTabletType: int(topodatapb.TabletType_PRIMARY), + DurabilityPolicy: policy.DurabilitySemiSync, + LastCheckValid: 1, + CountReplicas: 4, + CountValidReplicas: 4, + CountValidReplicatingReplicas: 4, + CountValidSemiSyncReplicatingReplicas: 1, + IsPrimary: 1, + SemiSyncPrimaryEnabled: 0, + CurrentTabletType: int(topodatapb.TabletType_PRIMARY), }}, keyspaceWanted: "ks", shardWanted: "0", codeWanted: PrimarySemiSyncMustBeSet, - }, { + }, + { name: "NotConnectedToPrimary", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 101}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -427,7 +442,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { CurrentTabletType: int(topodatapb.TabletType_PRIMARY), }, { TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -442,11 +457,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: NotConnectedToPrimary, - }, { + }, + { name: "ReplicaIsWritable", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 101}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -465,7 +481,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { CurrentTabletType: int(topodatapb.TabletType_PRIMARY), }, { TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -475,7 +491,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { }, DurabilityPolicy: policy.DurabilityNone, PrimaryTabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 101}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, }, LastCheckValid: 1, ReadOnly: 0, @@ -483,11 +499,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: ReplicaIsWritable, - }, { + }, + { name: "ConnectedToWrongPrimary", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 101}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -506,7 +523,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { CurrentTabletType: int(topodatapb.TabletType_PRIMARY), }, { TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -516,7 +533,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { }, DurabilityPolicy: policy.DurabilityNone, PrimaryTabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 102}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 102}, }, LastCheckValid: 1, ReadOnly: 1, @@ -524,11 +541,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: ConnectedToWrongPrimary, - }, { + }, + { name: "ReplicationStopped", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 101}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -547,7 +565,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { CurrentTabletType: int(topodatapb.TabletType_PRIMARY), }, { TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -557,7 +575,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { }, DurabilityPolicy: policy.DurabilityNone, PrimaryTabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 101}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, }, LastCheckValid: 1, ReadOnly: 1, @@ -566,11 +584,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: ReplicationStopped, - }, { + }, + { name: "No recoveries on drained tablets", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 101}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -589,7 +608,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { CurrentTabletType: int(topodatapb.TabletType_PRIMARY), }, { TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -599,7 +618,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { }, DurabilityPolicy: policy.DurabilityNone, PrimaryTabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 101}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, }, LastCheckValid: 1, ReadOnly: 1, @@ -608,11 +627,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: NoProblem, - }, { + }, + { name: "ReplicaMisconfigured", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 101}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -631,7 +651,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { CurrentTabletType: int(topodatapb.TabletType_PRIMARY), }, { TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -641,7 +661,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { }, DurabilityPolicy: policy.DurabilityNone, PrimaryTabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 101}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, }, LastCheckValid: 1, ReadOnly: 1, @@ -656,7 +676,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { name: "ReplicaSemiSyncMustBeSet", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 101}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -676,7 +696,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { CurrentTabletType: int(topodatapb.TabletType_PRIMARY), }, { TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -685,7 +705,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { MysqlPort: 6709, }, PrimaryTabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 101}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, }, DurabilityPolicy: policy.DurabilitySemiSync, LastCheckValid: 1, @@ -695,11 +715,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: ReplicaSemiSyncMustBeSet, - }, { + }, + { name: "ReplicaSemiSyncMustNotBeSet", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 101}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -718,7 +739,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { CurrentTabletType: int(topodatapb.TabletType_PRIMARY), }, { TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -727,7 +748,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { MysqlPort: 6709, }, PrimaryTabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 101}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, }, DurabilityPolicy: policy.DurabilityNone, LastCheckValid: 1, @@ -737,11 +758,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: ReplicaSemiSyncMustNotBeSet, - }, { + }, + { name: "SnapshotKeyspace", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -757,11 +779,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: NoProblem, - }, { + }, + { name: "EmptyDurabilityPolicy", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -775,13 +798,14 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: NoProblem, - }, { + }, + { // If the database_instance table for a tablet is empty (discovery of MySQL information hasn't happened yet or failed) // then we shouldn't run a failure fix on it until the discovery succeeds name: "Empty database_instance table", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 101}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -801,7 +825,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { CurrentTabletType: int(topodatapb.TabletType_PRIMARY), }, { TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -815,11 +839,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: InvalidReplica, - }, { + }, + { name: "DeadPrimary when VTOrc is starting up", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 101}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -831,7 +856,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { IsInvalid: 1, }, { TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -843,7 +868,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { ReplicationStopped: 1, }, { TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 103}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 103}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -857,11 +882,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: DeadPrimary, - }, { + }, + { name: "Invalid Primary", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 101}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -875,11 +901,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: InvalidPrimary, - }, { + }, + { name: "ErrantGTID", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 101}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -898,7 +925,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { CurrentTabletType: int(topodatapb.TabletType_PRIMARY), }, { TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -909,7 +936,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { DurabilityPolicy: policy.DurabilityNone, ErrantGTID: "some errant GTID", PrimaryTabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 101}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, }, LastCheckValid: 1, ReadOnly: 1, @@ -917,11 +944,12 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { keyspaceWanted: "ks", shardWanted: "0", codeWanted: ErrantGTIDDetected, - }, { + }, + { name: "ErrantGTID on a non-replica", info: []*test.InfoForRecoveryAnalysis{{ TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 101}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -940,7 +968,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { CurrentTabletType: int(topodatapb.TabletType_PRIMARY), }, { TabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 100}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, Hostname: "localhost", Keyspace: "ks", Shard: "0", @@ -951,7 +979,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { DurabilityPolicy: policy.DurabilityNone, ErrantGTID: "some errant GTID", PrimaryTabletInfo: &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{Cell: "zon1", Uid: 101}, + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, }, LastCheckValid: 1, ReadOnly: 1, @@ -975,7 +1003,7 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { } db.Db = test.NewTestDB([][]sqlutils.RowMap{rowMaps}) - got, err := GetReplicationAnalysis("", "", &ReplicationAnalysisHints{}) + got, err := GetDetectionAnalysis("", "", &DetectionAnalysisHints{}) if tt.wantErr != "" { require.EqualError(t, err, tt.wantErr) return @@ -993,11 +1021,111 @@ func TestGetReplicationAnalysisDecision(t *testing.T) { } } -// TestGetReplicationAnalysis tests the entire GetReplicationAnalysis. It inserts data into the database and runs the function. -// The database is not faked. This is intended to give more test coverage. This test is more comprehensive but more expensive than TestGetReplicationAnalysisDecision. +// TestStalePrimary tests that an old primary that remains writable and is of tablet type PRIMARY +// in the topo is demoted to a read-only replica by VTOrc. +func TestStalePrimary(t *testing.T) { + oldDB := db.Db + defer func() { + db.Db = oldDB + }() + + currentPrimaryTimestamp := time.Now().UTC().Truncate(time.Microsecond) + stalePrimaryTimestamp := currentPrimaryTimestamp.Add(-1 * time.Minute) + shardPrimaryTermTimestamp := currentPrimaryTimestamp.Format(sqlutils.DateTimeFormat) + + // We set up a real primary and replica, and then a stale primary running as REPLICA but with + // tablet type PRIMARY in the topology. + info := []*test.InfoForRecoveryAnalysis{ + { + TabletInfo: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, + Hostname: "localhost", + Keyspace: "ks", + Shard: "0", + Type: topodatapb.TabletType_PRIMARY, + MysqlHostname: "localhost", + MysqlPort: 6708, + }, + DurabilityPolicy: policy.DurabilitySemiSync, + LastCheckValid: 1, + CountReplicas: 1, + CountValidReplicas: 1, + CountValidReplicatingReplicas: 1, + IsPrimary: 1, + SemiSyncPrimaryEnabled: 1, + SemiSyncPrimaryStatus: 1, + SemiSyncPrimaryWaitForReplicaCount: 1, + SemiSyncPrimaryClients: 1, + CurrentTabletType: int(topodatapb.TabletType_PRIMARY), + PrimaryTimestamp: ¤tPrimaryTimestamp, + ShardPrimaryTermTimestamp: shardPrimaryTermTimestamp, + }, + { + TabletInfo: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 100}, + Hostname: "localhost", + Keyspace: "ks", + Shard: "0", + Type: topodatapb.TabletType_REPLICA, + MysqlHostname: "localhost", + MysqlPort: 6709, + }, + DurabilityPolicy: policy.DurabilitySemiSync, + PrimaryTabletInfo: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 101}, + }, + LastCheckValid: 1, + ReadOnly: 1, + SemiSyncReplicaEnabled: 1, + ShardPrimaryTermTimestamp: shardPrimaryTermTimestamp, + }, + { + TabletInfo: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{Cell: "zone1", Uid: 102}, + Hostname: "localhost", + Keyspace: "ks", + Shard: "0", + Type: topodatapb.TabletType_PRIMARY, + MysqlHostname: "localhost", + MysqlPort: 6710, + }, + DurabilityPolicy: policy.DurabilitySemiSync, + LastCheckValid: 1, + IsPrimary: 1, + ReadOnly: 0, + SemiSyncPrimaryEnabled: 1, + SemiSyncPrimaryStatus: 1, + SemiSyncPrimaryWaitForReplicaCount: 2, + SemiSyncPrimaryClients: 1, + CurrentTabletType: int(topodatapb.TabletType_REPLICA), + PrimaryTimestamp: &stalePrimaryTimestamp, + }, + } + + var rowMaps []sqlutils.RowMap + for _, analysis := range info { + analysis.SetValuesFromTabletInfo() + rowMaps = append(rowMaps, analysis.ConvertToRowMap()) + } + db.Db = test.NewTestDB([][]sqlutils.RowMap{rowMaps, rowMaps}) + + // Each sampling should yield the placeholder analysis that represents the future recovery behavior once + // the demotion logic is implemented, which makes this test fail until the actual fix is in place. + for range 2 { + got, err := GetDetectionAnalysis("", "", &DetectionAnalysisHints{}) + require.NoError(t, err, "expected detection analysis to run without error") + require.Len(t, got, 1, "expected exactly one analysis entry for the shard") + require.Equal(t, AnalysisCode("StaleTopoPrimary"), got[0].Analysis, "expected stale primary analysis") + require.Equal(t, "ks", got[0].AnalyzedKeyspace, "expected analysis to target keyspace ks") + require.Equal(t, "0", got[0].AnalyzedShard, "expected analysis to target shard 0") + } +} + +// TestGetDetectionAnalysis tests the entire GetDetectionAnalysis. It inserts data into the database and runs the function. +// The database is not faked. This is intended to give more test coverage. This test is more comprehensive but more expensive than TestGetDetectionAnalysisDecision. // This test is somewhere between a unit test, and an end-to-end test. It is specifically useful for testing situations which are hard to come by in end-to-end test, but require // real-world data to test specifically. -func TestGetReplicationAnalysis(t *testing.T) { +func TestGetDetectionAnalysis(t *testing.T) { // The test is intended to be used as follows. The initial data is stored into the database. Following this, some specific queries are run that each individual test specifies to get the desired state. tests := []struct { name string @@ -1059,7 +1187,7 @@ func TestGetReplicationAnalysis(t *testing.T) { require.NoError(t, err) } - got, err := GetReplicationAnalysis("", "", &ReplicationAnalysisHints{}) + got, err := GetDetectionAnalysis("", "", &DetectionAnalysisHints{}) require.NoError(t, err) if tt.codeWanted == NoProblem { require.Len(t, got, 0) @@ -1166,12 +1294,12 @@ func TestPostProcessAnalyses(t *testing.T) { tests := []struct { name string - analyses []*ReplicationAnalysis - want []*ReplicationAnalysis + analyses []*DetectionAnalysis + want []*DetectionAnalysis }{ { name: "No processing needed", - analyses: []*ReplicationAnalysis{ + analyses: []*DetectionAnalysis{ { Analysis: ReplicationStopped, TabletType: topodatapb.TabletType_REPLICA, @@ -1189,9 +1317,10 @@ func TestPostProcessAnalyses(t *testing.T) { ClusterDetails: ks0, }, }, - }, { + }, + { name: "Conversion of InvalidPrimary to DeadPrimary", - analyses: []*ReplicationAnalysis{ + analyses: []*DetectionAnalysis{ { Analysis: InvalidPrimary, AnalyzedInstanceAlias: "zone1-100", @@ -1231,7 +1360,7 @@ func TestPostProcessAnalyses(t *testing.T) { ClusterDetails: ks80, }, }, - want: []*ReplicationAnalysis{ + want: []*DetectionAnalysis{ { Analysis: DeadPrimary, AnalyzedInstanceAlias: "zone1-100", @@ -1254,7 +1383,7 @@ func TestPostProcessAnalyses(t *testing.T) { }, { name: "Unable to convert InvalidPrimary to DeadPrimary", - analyses: []*ReplicationAnalysis{ + analyses: []*DetectionAnalysis{ { Analysis: InvalidPrimary, AnalyzedInstanceAlias: "zone1-100", diff --git a/go/vt/vtorc/inst/analysis_problem.go b/go/vt/vtorc/inst/analysis_problem.go new file mode 100644 index 00000000000..030af55ca8e --- /dev/null +++ b/go/vt/vtorc/inst/analysis_problem.go @@ -0,0 +1,524 @@ +/* +Copyright 2026 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package inst + +import ( + "math" + "slices" + + topodatapb "vitess.io/vitess/go/vt/proto/topodata" + "vitess.io/vitess/go/vt/topo" + "vitess.io/vitess/go/vt/topo/topoproto" + "vitess.io/vitess/go/vt/vtctl/reparentutil/policy" +) + +const ( + detectionAnalysisPriorityShardWideAction = iota + detectionAnalysisPriorityCritical + detectionAnalysisPriorityHigh + detectionAnalysisPriorityMedium + detectionAnalysisPriorityLow +) + +// DetectionAnalysisProblemMeta contains basic metadata describing a problem. +type DetectionAnalysisProblemMeta struct { + // Analysis is the AnalysisCode representing the type of problem. + Analysis AnalysisCode + + // Description is a human-readable description of the problem. + Description string + + // Priority is an integer influencing the priority sorting of problems. A lower + // number is considered to be higher in the sort, with 0 being the top-priority. + Priority int +} + +// DetectionAnalysisProblem describes how to match, sort and track a problem. +type DetectionAnalysisProblem struct { + // Meta contains the metadata describing a problem. + Meta *DetectionAnalysisProblemMeta + + // AfterAnalyses defines problems that must be recovered before this problem. + AfterAnalyses []AnalysisCode + + // BeforeAnalyses defines problems that must be recovered after this problem. + BeforeAnalyses []AnalysisCode + + // MatchFunc is a function that returns true when the provided conditions match this problem. + MatchFunc func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool +} + +// RequiresOrderedExecution returns true if the problem must be executed +// sequentially relative to other problems in the same shard. This includes +// problems that declare dependencies directly (BeforeAnalyses/AfterAnalyses) +// as well as problems that are referenced by another problem's dependencies. +func (dap *DetectionAnalysisProblem) RequiresOrderedExecution() bool { + if dap.Meta.Priority == detectionAnalysisPriorityShardWideAction || len(dap.BeforeAnalyses) > 0 || len(dap.AfterAnalyses) > 0 { + return true + } + for _, p := range detectionAnalysisProblems { + if slices.Contains(p.BeforeAnalyses, dap.Meta.Analysis) || slices.Contains(p.AfterAnalyses, dap.Meta.Analysis) { + return true + } + } + return false +} + +// GetPriority returns the priority of a problem as an int. +func (dap *DetectionAnalysisProblem) GetPriority() int { + if dap.Meta == nil { + return 0 + } + return dap.Meta.Priority +} + +// GetDetectionAnalysisProblem returns the DetectionAnalysisProblem for the given AnalysisCode. +func GetDetectionAnalysisProblem(code AnalysisCode) *DetectionAnalysisProblem { + for _, p := range detectionAnalysisProblems { + if p.Meta.Analysis == code { + return p + } + } + return nil +} + +// HasMatch returns true if a DetectionAnalysisProblem matches the provided states. +func (dap *DetectionAnalysisProblem) HasMatch(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + if a == nil || ca == nil || dap.MatchFunc == nil { + return false + } + return dap.MatchFunc(a, ca, primary, tablet, isInvalid, isStaleBinlogCoordinates) +} + +// detectionAnalysisProblems contains all possible problems to match during detection analysis. +var detectionAnalysisProblems = []*DetectionAnalysisProblem{ + // InvalidPrimary and InvalidReplica + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: InvalidPrimary, + Description: "VTOrc hasn't been able to reach the primary even once since restart/shutdown", + Priority: detectionAnalysisPriorityCritical, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return a.IsClusterPrimary && isInvalid + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: InvalidReplica, + Description: "VTOrc hasn't been able to reach the replica even once since restart/shutdown", + Priority: detectionAnalysisPriorityLow, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return isInvalid + }, + }, + + // PrimaryDiskStalled + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: PrimaryDiskStalled, + Description: "Primary has a stalled disk", + Priority: detectionAnalysisPriorityShardWideAction, + }, + BeforeAnalyses: []AnalysisCode{DeadPrimary, DeadPrimaryAndReplicas, DeadPrimaryAndSomeReplicas, DeadPrimaryWithoutReplicas}, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return a.IsClusterPrimary && !a.LastCheckValid && a.IsDiskStalled + }, + }, + + // DeadPrimary* + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: DeadPrimaryWithoutReplicas, + Description: "Primary cannot be reached by vtorc and has no replica", + Priority: detectionAnalysisPriorityShardWideAction, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return a.IsClusterPrimary && !a.LastCheckValid && a.CountReplicas == 0 + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: DeadPrimary, + Description: "Primary cannot be reached by vtorc and none of its replicas is replicating", + Priority: detectionAnalysisPriorityShardWideAction, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return a.IsClusterPrimary && !a.LastCheckValid && a.CountReplicas > 0 && a.CountValidReplicas == a.CountReplicas && a.CountValidReplicatingReplicas == 0 + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: DeadPrimaryAndReplicas, + Description: "Primary cannot be reached by vtorc and none of its replicas is replicating", + Priority: detectionAnalysisPriorityShardWideAction, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return a.IsClusterPrimary && !a.LastCheckValid && a.CountReplicas > 0 && a.CountValidReplicas == 0 && a.CountValidReplicatingReplicas == 0 + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: DeadPrimaryAndSomeReplicas, + Description: "Primary cannot be reached by vtorc; some of its replicas are unreachable and none of its reachable replicas is replicating", + Priority: detectionAnalysisPriorityShardWideAction, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return a.IsClusterPrimary && !a.LastCheckValid && a.CountValidReplicas < a.CountReplicas && a.CountValidReplicas > 0 && a.CountValidReplicatingReplicas == 0 + }, + }, + + // PrimaryHasPrimary + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: PrimaryHasPrimary, + Description: "Primary is replicating from somewhere else", + Priority: detectionAnalysisPriorityShardWideAction, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return a.IsClusterPrimary && !a.IsPrimary + }, + }, + + // MySQL read-only checks + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: PrimaryIsReadOnly, + Description: "Primary is read-only", + Priority: detectionAnalysisPriorityHigh, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return a.IsClusterPrimary && a.IsReadOnly + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: ReplicaIsWritable, + Description: "Replica is writable", + Priority: detectionAnalysisPriorityMedium, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return topo.IsReplicaType(a.TabletType) && !a.IsReadOnly + }, + }, + + // Semi-sync checks + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: PrimarySemiSyncMustBeSet, + Description: "Primary semi-sync must be set", + Priority: detectionAnalysisPriorityMedium, + }, + AfterAnalyses: []AnalysisCode{ReplicaSemiSyncMustBeSet}, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + if !hasMinSemiSyncAckers(ca.durability, primary, a) { + return false + } + return a.IsClusterPrimary && policy.SemiSyncAckers(ca.durability, tablet) != 0 && !a.SemiSyncPrimaryEnabled + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: PrimarySemiSyncMustNotBeSet, + Description: "Primary semi-sync must not be set", + Priority: detectionAnalysisPriorityMedium, + }, + BeforeAnalyses: []AnalysisCode{ReplicaSemiSyncMustNotBeSet}, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return a.IsClusterPrimary && policy.SemiSyncAckers(ca.durability, tablet) == 0 && a.SemiSyncPrimaryEnabled + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: ReplicaSemiSyncMustBeSet, + Description: "Replica semi-sync must be set", + Priority: detectionAnalysisPriorityMedium, + }, + BeforeAnalyses: []AnalysisCode{PrimarySemiSyncMustBeSet}, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return topo.IsReplicaType(a.TabletType) && !a.IsPrimary && policy.IsReplicaSemiSync(ca.durability, primary, tablet) && !a.SemiSyncReplicaEnabled + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: ReplicaSemiSyncMustNotBeSet, + Description: "Replica semi-sync must not be set", + Priority: detectionAnalysisPriorityMedium, + }, + AfterAnalyses: []AnalysisCode{PrimarySemiSyncMustNotBeSet}, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return topo.IsReplicaType(a.TabletType) && !a.IsPrimary && !policy.IsReplicaSemiSync(ca.durability, primary, tablet) && a.SemiSyncReplicaEnabled + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: PrimarySemiSyncBlocked, + Description: "Writes seem to be blocked on semi-sync acks on the primary, even though sufficient replicas are configured to send ACKs", + Priority: detectionAnalysisPriorityShardWideAction, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return a.IsClusterPrimary && a.IsPrimary && a.SemiSyncBlocked && a.CountSemiSyncReplicasEnabled >= a.SemiSyncPrimaryWaitForReplicaCount + }, + }, + + // Primary tablet type checks + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: PrimaryCurrentTypeMismatch, + Description: "Primary tablet's current type is not PRIMARY", + Priority: detectionAnalysisPriorityMedium, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return a.IsClusterPrimary && a.CurrentTabletType != topodatapb.TabletType_UNKNOWN && a.CurrentTabletType != topodatapb.TabletType_PRIMARY + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: StaleTopoPrimary, + Description: "Primary tablet is stale, older than current primary", + Priority: detectionAnalysisPriorityHigh, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return isStaleTopoPrimary(a, ca) + }, + }, + + // Errant GTID + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: ErrantGTIDDetected, + Description: "Tablet has errant GTIDs", + Priority: detectionAnalysisPriorityMedium, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return topo.IsReplicaType(a.TabletType) && a.ErrantGTID != "" + }, + }, + + // Cluster primary checks + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: ClusterHasNoPrimary, + Description: "Cluster has no primary", + Priority: detectionAnalysisPriorityShardWideAction, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return topo.IsReplicaType(a.TabletType) && ca.primaryAlias == "" && a.ShardPrimaryTermTimestamp == "" + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: PrimaryTabletDeleted, + Description: "Primary tablet has been deleted", + Priority: detectionAnalysisPriorityShardWideAction, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return topo.IsReplicaType(a.TabletType) && ca.primaryAlias == "" && a.ShardPrimaryTermTimestamp != "" + }, + }, + + // Replica connectivity checks + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: NotConnectedToPrimary, + Description: "Not connected to the primary", + Priority: detectionAnalysisPriorityMedium, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return topo.IsReplicaType(a.TabletType) && a.IsPrimary + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: ReplicaMisconfigured, + Description: "Replica has been misconfigured", + Priority: detectionAnalysisPriorityMedium, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return topo.IsReplicaType(a.TabletType) && !a.IsPrimary && math.Round(a.HeartbeatInterval*2) != float64(a.ReplicaNetTimeout) + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: ConnectedToWrongPrimary, + Description: "Connected to wrong primary", + Priority: detectionAnalysisPriorityMedium, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return topo.IsReplicaType(a.TabletType) && !a.IsPrimary && ca.primaryAlias != "" && a.AnalyzedInstancePrimaryAlias != ca.primaryAlias + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: ReplicationStopped, + Description: "Replication is stopped", + Priority: detectionAnalysisPriorityMedium, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return topo.IsReplicaType(a.TabletType) && !a.IsPrimary && a.ReplicationStopped + }, + }, + + // Unreachable primary checks + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: UnreachablePrimaryWithLaggingReplicas, + Description: "Primary cannot be reached by vtorc and all of its replicas are lagging", + Priority: detectionAnalysisPriorityMedium, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return a.IsPrimary && !a.LastCheckValid && a.CountLaggingReplicas == a.CountReplicas && a.CountDelayedReplicas < a.CountReplicas && a.CountValidReplicatingReplicas > 0 + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: UnreachablePrimary, + Description: "Primary cannot be reached by vtorc but all of its replicas seem to be replicating; possibly a network/host issue", + Priority: detectionAnalysisPriorityMedium, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return a.IsPrimary && !a.LastCheckValid && !a.LastCheckPartialSuccess && a.CountValidReplicas > 0 && a.CountValidReplicatingReplicas == a.CountValidReplicas + }, + }, + // Locked semi-sync primary + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: LockedSemiSyncPrimary, + Description: "Semi sync primary is locked since it doesn't get enough replica acknowledgements", + Priority: detectionAnalysisPriorityMedium, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return a.IsPrimary && a.SemiSyncPrimaryEnabled && a.SemiSyncPrimaryStatus && a.SemiSyncPrimaryWaitForReplicaCount > 0 && a.SemiSyncPrimaryClients < a.SemiSyncPrimaryWaitForReplicaCount && isStaleBinlogCoordinates + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: LockedSemiSyncPrimaryHypothesis, + Description: "Semi sync primary seems to be locked, more samplings needed to validate", + Priority: detectionAnalysisPriorityMedium, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return a.IsPrimary && a.SemiSyncPrimaryEnabled && a.SemiSyncPrimaryStatus && a.SemiSyncPrimaryWaitForReplicaCount > 0 && a.SemiSyncPrimaryClients < a.SemiSyncPrimaryWaitForReplicaCount && !isStaleBinlogCoordinates + }, + }, + + // Primary replica health checks + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: PrimarySingleReplicaNotReplicating, + Description: "Primary is reachable but its single replica is not replicating", + Priority: detectionAnalysisPriorityMedium, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return a.IsPrimary && a.LastCheckValid && a.CountReplicas == 1 && a.CountValidReplicas == a.CountReplicas && a.CountValidReplicatingReplicas == 0 + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: PrimarySingleReplicaDead, + Description: "Primary is reachable but its single replica is dead", + Priority: detectionAnalysisPriorityMedium, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return a.IsPrimary && a.LastCheckValid && a.CountReplicas == 1 && a.CountValidReplicas == 0 + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: AllPrimaryReplicasNotReplicating, + Description: "Primary is reachable but none of its replicas is replicating", + Priority: detectionAnalysisPriorityLow, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return a.IsPrimary && a.LastCheckValid && a.CountReplicas > 1 && a.CountValidReplicas == a.CountReplicas && a.CountValidReplicatingReplicas == 0 + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: AllPrimaryReplicasNotReplicatingOrDead, + Description: "Primary is reachable but none of its replicas is replicating", + Priority: detectionAnalysisPriorityLow, + }, + MatchFunc: func(a *DetectionAnalysis, ca *clusterAnalysis, primary, tablet *topodatapb.Tablet, isInvalid, isStaleBinlogCoordinates bool) bool { + return a.IsPrimary && a.LastCheckValid && a.CountReplicas > 1 && a.CountValidReplicas < a.CountReplicas && a.CountValidReplicas > 0 && a.CountValidReplicatingReplicas == 0 + }, + }, +} + +func sortDetectionAnalysisMatchedProblems(allProblems []*DetectionAnalysisProblem) { + // use slices.SortStableFunc because it keeps the original order of equal elements. + slices.SortStableFunc(allProblems, compareDetectionAnalysisProblems) +} + +// compareDetectionAnalysisProblems compares two DetectionAnalysisProblems using +// the same logic as sortDetectionAnalysisMatchedProblems. +func compareDetectionAnalysisProblems(a, b *DetectionAnalysisProblem) int { + if a.Meta == nil || b.Meta == nil { + return 0 + } + + // handle before/after dependencies + aAnalysis := a.Meta.Analysis + bAnalysis := b.Meta.Analysis + if slices.Contains(b.BeforeAnalyses, aAnalysis) || slices.Contains(a.AfterAnalyses, bAnalysis) { + return 1 + } + if slices.Contains(a.BeforeAnalyses, bAnalysis) || slices.Contains(b.AfterAnalyses, aAnalysis) { + return -1 + } + + // effective priority (lower is better). + aPriority := a.GetPriority() + bPriority := b.GetPriority() + switch { + case aPriority > bPriority: + return 1 + case aPriority < bPriority: + return -1 + } + + return 0 +} + +// sortDetectionAnalyses sorts a slice of DetectionAnalysis by looking up each +// entry's Analysis code in detectionAnalysisProblems and comparing using the +// same priority/dependency logic as sortDetectionAnalysisMatchedProblems. +func sortDetectionAnalyses(analyses []*DetectionAnalysis) { + slices.SortStableFunc(analyses, func(a, b *DetectionAnalysis) int { + aProblem := GetDetectionAnalysisProblem(a.Analysis) + bProblem := GetDetectionAnalysisProblem(b.Analysis) + if aProblem == nil || bProblem == nil { + return 0 + } + return compareDetectionAnalysisProblems(aProblem, bProblem) + }) +} + +// GroupDetectionAnalysesByShard groups a slice of DetectionAnalysis by shard key +// (topoproto.KeyspaceShardString) and sorts each group by priority. +func GroupDetectionAnalysesByShard(analyses []*DetectionAnalysis) map[string][]*DetectionAnalysis { + result := make(map[string][]*DetectionAnalysis) + for _, a := range analyses { + key := topoproto.KeyspaceShardString(a.AnalyzedKeyspace, a.AnalyzedShard) + result[key] = append(result[key], a) + } + for _, group := range result { + sortDetectionAnalyses(group) + } + return result +} diff --git a/go/vt/vtorc/inst/analysis_problem_test.go b/go/vt/vtorc/inst/analysis_problem_test.go new file mode 100644 index 00000000000..740d40db1db --- /dev/null +++ b/go/vt/vtorc/inst/analysis_problem_test.go @@ -0,0 +1,311 @@ +/* +Copyright 2026 The Vitess Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package inst + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + topodatapb "vitess.io/vitess/go/vt/proto/topodata" +) + +func TestSortDetectionAnalysisMatchedProblems(t *testing.T) { + worstPriority := 10 + testCases := []struct { + name string + in []*DetectionAnalysisProblem + postSortByAnalysis []AnalysisCode + }{ + { + name: "default", + in: []*DetectionAnalysisProblem{ + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: InvalidReplica, + Description: "should be 2nd-last, not a shardWideAction, low priority", + Priority: detectionAnalysisPriorityLow, + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: InvalidReplica, + Description: "should be last, not a shardWideAction, worst priority", + Priority: worstPriority, + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: PrimaryIsReadOnly, + Description: "should be after DeadPrimary, high priority", + Priority: detectionAnalysisPriorityHigh, + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: PrimarySemiSyncMustBeSet, + Description: "should be after ReplicaSemiSyncMustBeSet, has an after dependency", + Priority: detectionAnalysisPriorityMedium, + }, + AfterAnalyses: []AnalysisCode{ReplicaSemiSyncMustBeSet}, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: ReplicaSemiSyncMustBeSet, + Description: "should be before PrimarySemiSyncMustBeSet, has a before dependency", + Priority: detectionAnalysisPriorityMedium, + }, + BeforeAnalyses: []AnalysisCode{PrimarySemiSyncMustBeSet}, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: DeadPrimary, + Description: "should be 1st, shard-wide action priority", + Priority: detectionAnalysisPriorityShardWideAction, + }, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: ReplicaSemiSyncMustNotBeSet, + Description: "should be after PrimarySemiSyncMustNotBeSet, has an after dependency", + Priority: detectionAnalysisPriorityMedium, + }, + AfterAnalyses: []AnalysisCode{PrimarySemiSyncMustNotBeSet}, + }, + { + Meta: &DetectionAnalysisProblemMeta{ + Analysis: PrimarySemiSyncMustNotBeSet, + Description: "should be before ReplicaSemiSyncMustNotBeSet, has a before dependency", + Priority: detectionAnalysisPriorityMedium, + }, + BeforeAnalyses: []AnalysisCode{ReplicaSemiSyncMustNotBeSet}, + }, + }, + postSortByAnalysis: []AnalysisCode{ + DeadPrimary, + PrimaryIsReadOnly, + ReplicaSemiSyncMustBeSet, + PrimarySemiSyncMustBeSet, + PrimarySemiSyncMustNotBeSet, + ReplicaSemiSyncMustNotBeSet, + InvalidReplica, + InvalidReplica, + }, + }, + } + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + sorted := testCase.in + sortDetectionAnalysisMatchedProblems(sorted) + + require.Len(t, sorted, len(testCase.postSortByAnalysis)) + for i, analysis := range testCase.postSortByAnalysis { + assert.Equal(t, analysis, sorted[i].Meta.Analysis) + } + + // confirm last problem has the worstPriority + require.Equal(t, worstPriority, sorted[len(sorted)-1].Meta.Priority) + }) + } +} + +func TestRequiresOrderedExecution(t *testing.T) { + tests := []struct { + name string + problem *DetectionAnalysisProblem + expected bool + }{ + { + name: "shard-wide action priority", + problem: &DetectionAnalysisProblem{ + Meta: &DetectionAnalysisProblemMeta{Priority: detectionAnalysisPriorityShardWideAction}, + }, + expected: true, + }, + { + name: "critical priority", + problem: &DetectionAnalysisProblem{ + Meta: &DetectionAnalysisProblemMeta{Priority: detectionAnalysisPriorityCritical}, + }, + expected: false, + }, + { + name: "has BeforeAnalyses", + problem: &DetectionAnalysisProblem{ + Meta: &DetectionAnalysisProblemMeta{Priority: detectionAnalysisPriorityMedium}, + BeforeAnalyses: []AnalysisCode{DeadPrimary}, + }, + expected: true, + }, + { + name: "has AfterAnalyses", + problem: &DetectionAnalysisProblem{ + Meta: &DetectionAnalysisProblemMeta{Priority: detectionAnalysisPriorityMedium}, + AfterAnalyses: []AnalysisCode{DeadPrimary}, + }, + expected: true, + }, + { + name: "referenced by another problem's BeforeAnalyses", + problem: &DetectionAnalysisProblem{ + Meta: &DetectionAnalysisProblemMeta{Analysis: ReplicaSemiSyncMustNotBeSet, Priority: detectionAnalysisPriorityMedium}, + }, + expected: true, + }, + { + name: "referenced by another problem's AfterAnalyses", + problem: &DetectionAnalysisProblem{ + Meta: &DetectionAnalysisProblemMeta{Analysis: PrimarySemiSyncMustNotBeSet, Priority: detectionAnalysisPriorityMedium}, + }, + expected: true, + }, + { + name: "independent problem", + problem: &DetectionAnalysisProblem{ + Meta: &DetectionAnalysisProblemMeta{Priority: detectionAnalysisPriorityLow}, + }, + expected: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.expected, tt.problem.RequiresOrderedExecution()) + }) + } +} + +func TestGetDetectionAnalysisProblem(t *testing.T) { + problem := GetDetectionAnalysisProblem(DeadPrimary) + require.NotNil(t, problem) + assert.Equal(t, DeadPrimary, problem.Meta.Analysis) + + problem = GetDetectionAnalysisProblem("NonExistentCode") + assert.Nil(t, problem) +} + +func TestCompareDetectionAnalysisProblems(t *testing.T) { + tests := []struct { + name string + a, b *DetectionAnalysisProblem + expected int + }{ + { + name: "shard-wide action beats non-shard-wide", + a: &DetectionAnalysisProblem{ + Meta: &DetectionAnalysisProblemMeta{Priority: detectionAnalysisPriorityShardWideAction}, + }, + b: &DetectionAnalysisProblem{ + Meta: &DetectionAnalysisProblemMeta{Priority: detectionAnalysisPriorityHigh}, + }, + expected: -1, + }, + { + name: "higher priority wins", + a: &DetectionAnalysisProblem{ + Meta: &DetectionAnalysisProblemMeta{Priority: detectionAnalysisPriorityHigh}, + }, + b: &DetectionAnalysisProblem{ + Meta: &DetectionAnalysisProblemMeta{Priority: detectionAnalysisPriorityLow}, + }, + expected: -1, + }, + { + name: "equal priority", + a: &DetectionAnalysisProblem{ + Meta: &DetectionAnalysisProblemMeta{Priority: detectionAnalysisPriorityMedium}, + }, + b: &DetectionAnalysisProblem{ + Meta: &DetectionAnalysisProblemMeta{Priority: detectionAnalysisPriorityMedium}, + }, + expected: 0, + }, + { + name: "before dependency - MustBeSet", + a: &DetectionAnalysisProblem{ + Meta: &DetectionAnalysisProblemMeta{Analysis: ReplicaSemiSyncMustBeSet}, + BeforeAnalyses: []AnalysisCode{PrimarySemiSyncMustBeSet}, + }, + b: &DetectionAnalysisProblem{ + Meta: &DetectionAnalysisProblemMeta{Analysis: PrimarySemiSyncMustBeSet}, + }, + expected: -1, + }, + { + name: "before dependency - MustNotBeSet", + a: &DetectionAnalysisProblem{ + Meta: &DetectionAnalysisProblemMeta{Analysis: PrimarySemiSyncMustNotBeSet}, + BeforeAnalyses: []AnalysisCode{ReplicaSemiSyncMustNotBeSet}, + }, + b: &DetectionAnalysisProblem{ + Meta: &DetectionAnalysisProblemMeta{Analysis: ReplicaSemiSyncMustNotBeSet}, + }, + expected: -1, + }, + { + name: "after dependency - MustNotBeSet", + a: &DetectionAnalysisProblem{ + Meta: &DetectionAnalysisProblemMeta{Analysis: ReplicaSemiSyncMustNotBeSet}, + AfterAnalyses: []AnalysisCode{PrimarySemiSyncMustNotBeSet}, + }, + b: &DetectionAnalysisProblem{ + Meta: &DetectionAnalysisProblemMeta{Analysis: PrimarySemiSyncMustNotBeSet}, + }, + expected: 1, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.expected, compareDetectionAnalysisProblems(tt.a, tt.b)) + }) + } +} + +func TestGroupDetectionAnalysesByShard(t *testing.T) { + analyses := []*DetectionAnalysis{ + { + Analysis: ReplicationStopped, + AnalyzedKeyspace: "ks1", + AnalyzedShard: "0", + TabletType: topodatapb.TabletType_REPLICA, + }, + { + Analysis: DeadPrimary, + AnalyzedKeyspace: "ks1", + AnalyzedShard: "0", + TabletType: topodatapb.TabletType_PRIMARY, + }, + { + Analysis: PrimaryIsReadOnly, + AnalyzedKeyspace: "ks2", + AnalyzedShard: "0", + TabletType: topodatapb.TabletType_PRIMARY, + }, + } + + result := GroupDetectionAnalysesByShard(analyses) + + require.Len(t, result, 2) + + // ks1/0 should have 2 entries, sorted with DeadPrimary first + ks1 := result["ks1/0"] + require.Len(t, ks1, 2) + assert.Equal(t, DeadPrimary, ks1[0].Analysis) + assert.Equal(t, ReplicationStopped, ks1[1].Analysis) + + // ks2/0 should have 1 entry + ks2 := result["ks2/0"] + require.Len(t, ks2, 1) + assert.Equal(t, PrimaryIsReadOnly, ks2[0].Analysis) +} diff --git a/go/vt/vtorc/inst/analysis_test.go b/go/vt/vtorc/inst/analysis_test.go new file mode 100644 index 00000000000..60aaeb790d0 --- /dev/null +++ b/go/vt/vtorc/inst/analysis_test.go @@ -0,0 +1,70 @@ +/* +Copyright 2026 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package inst + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + topodatapb "vitess.io/vitess/go/vt/proto/topodata" + "vitess.io/vitess/go/vt/vtctl/reparentutil/policy" +) + +func TestHasMinSemiSyncAckers(t *testing.T) { + durablerNone, _ := policy.GetDurabilityPolicy("none") + durablerCrossCell, _ := policy.GetDurabilityPolicy("cross_cell") + tablet := &topodatapb.Tablet{Keyspace: t.Name(), Shard: "-"} + + testCases := []struct { + name string + durabler policy.Durabler + analysis *DetectionAnalysis + expect bool + }{ + { + name: "durability policy none", + analysis: &DetectionAnalysis{ + CountValidSemiSyncReplicatingReplicas: 0, + }, + durabler: durablerNone, + expect: true, + }, + { + name: "durability policy cross_cell without min ackers", + durabler: durablerCrossCell, + analysis: &DetectionAnalysis{ + CountValidSemiSyncReplicatingReplicas: 0, + }, + expect: false, + }, + { + name: "durability policy cross_cell with min ackers", + durabler: durablerCrossCell, + analysis: &DetectionAnalysis{ + CountValidSemiSyncReplicatingReplicas: uint(durablerCrossCell.SemiSyncAckers(tablet)), + }, + expect: true, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + assert.Equal(t, testCase.expect, hasMinSemiSyncAckers(testCase.durabler, tablet, testCase.analysis)) + }) + } +} diff --git a/go/vt/vtorc/inst/instance_dao.go b/go/vt/vtorc/inst/instance_dao.go index eae38bc955f..f975008a1e6 100644 --- a/go/vt/vtorc/inst/instance_dao.go +++ b/go/vt/vtorc/inst/instance_dao.go @@ -405,27 +405,37 @@ Cleanup: func detectErrantGTIDs(instance *Instance, tablet *topodatapb.Tablet) (err error) { // If the tablet is not replicating from anyone, then it could be the previous primary. // We should check for errant GTIDs by finding the difference with the shard's current primary. - if instance.primaryExecutedGtidSet == "" && instance.SourceHost == "" { - var primaryInstance *Instance - primaryAlias, _, _ := ReadShardPrimaryInformation(tablet.Keyspace, tablet.Shard) - if primaryAlias != "" { - // Check if the current tablet is the primary. - // If it is, then we don't need to run errant gtid detection on it. - if primaryAlias == instance.InstanceAlias { - return nil - } - primaryInstance, _, _ = ReadInstance(primaryAlias) + primaryAlias, _, err := ReadShardPrimaryInformation(tablet.Keyspace, tablet.Shard) + if err != nil { + return fmt.Errorf("failed to read shard primary for %s/%s: %w", tablet.Keyspace, tablet.Shard, err) + } + + // Check if the current tablet is the primary. If it is, then we don't need to + // run errant GTID detection on it. + if primaryAlias == instance.InstanceAlias { + return nil + } + + var primaryInstance *Instance + if primaryAlias != "" { + primaryInstance, _, err = ReadInstance(primaryAlias) + if err != nil { + return fmt.Errorf("failed to read primary instance %q: %w", primaryAlias, err) } - // Only run errant GTID detection, if we are sure that the data read of the current primary - // is up-to-date enough to reflect that it has been promoted. This is needed to prevent - // flagging incorrect errant GTIDs. If we were to use old data, we could have some GTIDs - // accepted by the old primary (this tablet) that don't show in the new primary's set. - if primaryInstance != nil { - if primaryInstance.SourceHost == "" { - instance.primaryExecutedGtidSet = primaryInstance.ExecutedGtidSet - } + } + + // Only run errant GTID detection if we are sure that the data read of the current primary + // is up-to-date enough to reflect that it has been promoted. This is needed to prevent + // flagging incorrect errant GTIDs. If we were to use old data, we could have some GTIDs + // accepted by the old primary (this tablet) that don't show in the new primary's set. + if primaryInstance != nil && primaryInstance.SourceHost == "" { + // If the instance has no replication source and no primary GTID set yet, or if the instance's replication + // source is not the primary, use the shard primary's executed GTID set for comparison. + if (instance.SourceHost == "" && instance.primaryExecutedGtidSet == "") || !sourceIsPrimary(instance, primaryInstance) { + instance.primaryExecutedGtidSet = primaryInstance.ExecutedGtidSet } } + if instance.ExecutedGtidSet != "" && instance.primaryExecutedGtidSet != "" { // Compare primary & replica GTID sets, but ignore the sets that present the primary's UUID. // This is because vtorc may pool primary and replica at an inconvenient timing, @@ -458,6 +468,19 @@ func detectErrantGTIDs(instance *Instance, tablet *topodatapb.Tablet) (err error return err } +// sourceIsPrimary returns true if the instance's replication source is the given primary. +func sourceIsPrimary(instance *Instance, primaryInstance *Instance) bool { + if instance.SourceHost == "" { + return false + } + + if instance.SourceUUID != "" && primaryInstance.ServerUUID != "" { + return instance.SourceUUID == primaryInstance.ServerUUID + } + + return instance.SourceHost == primaryInstance.Hostname && instance.SourcePort == primaryInstance.Port +} + // getKeyspaceShardName returns a single string having both the keyspace and shard func getKeyspaceShardName(keyspace, shard string) string { return fmt.Sprintf("%v:%v", keyspace, shard) diff --git a/go/vt/vtorc/inst/instance_dao_test.go b/go/vt/vtorc/inst/instance_dao_test.go index c07f303b9d2..3c0e06c021b 100644 --- a/go/vt/vtorc/inst/instance_dao_test.go +++ b/go/vt/vtorc/inst/instance_dao_test.go @@ -898,6 +898,29 @@ func TestExpireTableData(t *testing.T) { } func TestDetectErrantGTIDs(t *testing.T) { + keyspaceName := "ks" + shardName := "0" + tablet := &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone-1", + Uid: 100, + }, + Keyspace: keyspaceName, + Shard: shardName, + } + primaryTablet := &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone-1", + Uid: 101, + }, + Keyspace: keyspaceName, + Shard: shardName, + Type: topodatapb.TabletType_PRIMARY, + + MysqlHostname: "primary-host", + MysqlPort: 6714, + } + tests := []struct { name string instance *Instance @@ -947,6 +970,8 @@ func TestDetectErrantGTIDs(t *testing.T) { primaryInstance: &Instance{ SourceHost: "", ExecutedGtidSet: "230ea8ea-81e3-11e4-972a-e25ec4bd140a:1-10589,8bc65c84-3fe4-11ed-a912-257f0fcdd6c9:1-34,316d193c-70e5-11e5-adb2-ecf4bb2262ff:1-341", + Hostname: primaryTablet.MysqlHostname, + Port: int(primaryTablet.MysqlPort), }, wantErrantGTID: "316d193c-70e5-11e5-adb2-ecf4bb2262ff:342", }, { @@ -963,24 +988,6 @@ func TestDetectErrantGTIDs(t *testing.T) { }, } - keyspaceName := "ks" - shardName := "0" - tablet := &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{ - Cell: "zone-1", - Uid: 100, - }, - Keyspace: keyspaceName, - Shard: shardName, - } - primaryTablet := &topodatapb.Tablet{ - Alias: &topodatapb.TabletAlias{ - Cell: "zone-1", - Uid: 101, - }, - Keyspace: keyspaceName, - Shard: shardName, - } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Clear the database after the test. The easiest way to do that is to run all the initialization commands again. @@ -997,6 +1004,7 @@ func TestDetectErrantGTIDs(t *testing.T) { if tt.primaryInstance != nil { tt.primaryInstance.InstanceAlias = topoproto.TabletAliasString(primaryTablet.Alias) + err = SaveTablet(primaryTablet) require.NoError(t, err) err = WriteInstance(tt.primaryInstance, true, nil) @@ -1015,6 +1023,109 @@ func TestDetectErrantGTIDs(t *testing.T) { } } +// TestDetectErrantGTIDsWithWrongPrimarySource ensures that errant GTIDs are +// detected by comparing against the shard primary when a replica is pointed at +// a different source. +func TestDetectErrantGTIDsWithWrongPrimarySource(t *testing.T) { + defer func() { + db.ClearVTOrcDatabase() + }() + db.ClearVTOrcDatabase() + + keyspaceName := "ks" + shardName := "0" + + primaryUUID := "a5ce8e8a-4e56-11ef-9f7d-92339a7d9f6c" + wrongPrimaryUUID := "bb1db5f6-4e56-11ef-8bda-3ae65c7f7f5e" + replicaUUID := "cc946b58-4e56-11ef-9e6f-3e527c1a9e9d" + + primaryTablet := &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone-1", + Uid: 101, + }, + Keyspace: keyspaceName, + Shard: shardName, + Type: topodatapb.TabletType_PRIMARY, + + MysqlHostname: "primary-host", + MysqlPort: 6714, + } + + replicaTablet := &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone-1", + Uid: 100, + }, + Keyspace: keyspaceName, + Shard: shardName, + } + + err := SaveShard(topo.NewShardInfo(keyspaceName, shardName, &topodatapb.Shard{ + PrimaryAlias: primaryTablet.Alias, + }, nil)) + require.NoError(t, err) + + err = SaveTablet(primaryTablet) + require.NoError(t, err) + + // Create the real shard primary instance and give it a GTID set that does + // not include the replica UUID. This represents the authoritative primary. + primaryInstance := &Instance{ + InstanceAlias: topoproto.TabletAliasString(primaryTablet.Alias), + Hostname: "primary-host", + Port: 6714, + SourceHost: "", + ExecutedGtidSet: primaryUUID + ":1-10", + ServerUUID: primaryUUID, + } + + err = WriteInstance(primaryInstance, true, nil) + require.NoError(t, err) + + // Create a wrong primary instance that contains the replica UUID in its + // executed GTID set. This masks errant GTIDs if the replica uses it for + // comparison + wrongPrimaryInstance := &Instance{ + InstanceAlias: "zone-1-0000000102", + Hostname: "wrong-primary", + Port: 6720, + SourceHost: "", + ExecutedGtidSet: fmt.Sprintf("%s:1-10,%s:1-5", wrongPrimaryUUID, replicaUUID), + ServerUUID: wrongPrimaryUUID, + AncestryUUID: wrongPrimaryUUID, + } + + err = WriteInstance(wrongPrimaryInstance, true, nil) + require.NoError(t, err) + + // Create a replica instance that is pointed at the wrong primary. The replica + // contains errant GTIDs that should be caught. + replicaInstance := &Instance{ + InstanceAlias: topoproto.TabletAliasString(replicaTablet.Alias), + Hostname: "replica-host", + Port: 6711, + SourceHost: wrongPrimaryInstance.Hostname, + SourcePort: wrongPrimaryInstance.Port, + SourceUUID: wrongPrimaryInstance.ServerUUID, + ExecutedGtidSet: fmt.Sprintf("%s:1-10,%s:1-5", wrongPrimaryUUID, replicaUUID), + ServerUUID: replicaUUID, + } + + err = ReadInstanceClusterAttributes(replicaInstance) + require.NoError(t, err) + require.Equal(t, wrongPrimaryInstance.ExecutedGtidSet, replicaInstance.primaryExecutedGtidSet) + require.Equal(t, wrongPrimaryInstance.AncestryUUID, replicaInstance.AncestryUUID) + + // Run errant GTID detection. We should find some. + err = detectErrantGTIDs(replicaInstance, replicaTablet) + require.NoError(t, err) + + // The replica's own UUID entries should be reported as errant because the + // real shard primary does not include them. + require.Equal(t, replicaUUID+":1-5", replicaInstance.GtidErrant) +} + // TestPrimaryErrantGTIDs tests that we don't run Errant GTID detection on the primary tablet itself! func TestPrimaryErrantGTIDs(t *testing.T) { // Clear the database after the test. The easiest way to do that is to run all the initialization commands again. diff --git a/go/vt/vtorc/logic/tablet_discovery.go b/go/vt/vtorc/logic/tablet_discovery.go index eee788bd9aa..694a03b675c 100644 --- a/go/vt/vtorc/logic/tablet_discovery.go +++ b/go/vt/vtorc/logic/tablet_discovery.go @@ -286,7 +286,7 @@ func refreshTabletInfoOfShard(ctx context.Context, keyspace, shard string) { } func refreshTabletsInKeyspaceShard(ctx context.Context, keyspace, shard string, loader func(tabletAlias string), forceRefresh bool, tabletsToIgnore []string) { - tablets, err := ts.GetTabletsByShard(ctx, keyspace, shard) + tablets, err := getShardTablets(ctx, keyspace, shard) if err != nil { log.Errorf("Error fetching tablets for keyspace/shard %v/%v: %v", keyspace, shard, err) return @@ -296,6 +296,14 @@ func refreshTabletsInKeyspaceShard(ctx context.Context, keyspace, shard string, refreshTablets(tablets, query, args, loader, forceRefresh, tabletsToIgnore) } +// getShardTablets gets tablets for the given keyspace and shard with a timeout. +func getShardTablets(ctx context.Context, keyspace, shard string) ([]*topo.TabletInfo, error) { + ctx, cancel := context.WithTimeout(ctx, topo.RemoteOperationTimeout) + defer cancel() + + return ts.GetTabletsByShard(ctx, keyspace, shard) +} + func refreshTablets(tablets []*topo.TabletInfo, query string, args []any, loader func(tabletAlias string), forceRefresh bool, tabletsToIgnore []string) { // Discover new tablets. latestInstances := make(map[string]bool) diff --git a/go/vt/vtorc/logic/topology_recovery.go b/go/vt/vtorc/logic/topology_recovery.go index 98cba60974e..77355d00a72 100644 --- a/go/vt/vtorc/logic/topology_recovery.go +++ b/go/vt/vtorc/logic/topology_recovery.go @@ -21,7 +21,10 @@ import ( "encoding/json" "errors" "fmt" + "maps" "math/rand/v2" + "slices" + "sync" "sync/atomic" "time" @@ -29,7 +32,9 @@ import ( "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/logutil" logutilpb "vitess.io/vitess/go/vt/proto/logutil" + replicationdatapb "vitess.io/vitess/go/vt/proto/replicationdata" topodatapb "vitess.io/vitess/go/vt/proto/topodata" + "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/topo/topoproto" "vitess.io/vitess/go/vt/vtctl/reparentutil" "vitess.io/vitess/go/vt/vtctl/reparentutil/policy" @@ -48,6 +53,10 @@ const ( FixPrimaryRecoveryName string = "FixPrimary" FixReplicaRecoveryName string = "FixReplica" RecoverErrantGTIDDetectedName string = "RecoverErrantGTIDDetected" + + // DemoteStaleTopoPrimaryRecoveryName is a recovery for tablets that have a stale type of PRIMARY + // in the topology but a newer primary has been elected. + DemoteStaleTopoPrimaryRecoveryName string = "DemoteStaleTopoPrimary" ) var ( @@ -105,12 +114,16 @@ const ( fixPrimaryFunc fixReplicaFunc recoverErrantGTIDDetectedFunc + + // demoteStaleTopoPrimaryFunc is the recovery function for when a tablet has a stale type of + // PRIMARY in the topology and should be demoted. + demoteStaleTopoPrimaryFunc ) // TopologyRecovery represents an entry in the topology_recovery table type TopologyRecovery struct { ID int64 - AnalysisEntry inst.ReplicationAnalysis + AnalysisEntry inst.DetectionAnalysis SuccessorAlias string IsSuccessful bool AllErrors []string @@ -119,9 +132,9 @@ type TopologyRecovery struct { DetectionID int64 } -func NewTopologyRecovery(replicationAnalysis inst.ReplicationAnalysis) *TopologyRecovery { +func NewTopologyRecovery(detectionAnalysis inst.DetectionAnalysis) *TopologyRecovery { topologyRecovery := &TopologyRecovery{} - topologyRecovery.AnalysisEntry = replicationAnalysis + topologyRecovery.AnalysisEntry = detectionAnalysis topologyRecovery.AllErrors = []string{} return topologyRecovery } @@ -224,7 +237,7 @@ func resolveRecovery(topologyRecovery *TopologyRecovery, successorInstance *inst } // recoverPrimaryHasPrimary resets the replication on the primary instance -func recoverPrimaryHasPrimary(ctx context.Context, analysisEntry *inst.ReplicationAnalysis, logger *log.PrefixedLogger) (recoveryAttempted bool, topologyRecovery *TopologyRecovery, err error) { +func recoverPrimaryHasPrimary(ctx context.Context, analysisEntry *inst.DetectionAnalysis, logger *log.PrefixedLogger) (recoveryAttempted bool, topologyRecovery *TopologyRecovery, err error) { topologyRecovery, err = AttemptRecoveryRegistration(analysisEntry) if topologyRecovery == nil { message := fmt.Sprintf("found an active or recent recovery on %+v. Will not issue another fixPrimaryHasPrimary.", analysisEntry.AnalyzedInstanceAlias) @@ -236,7 +249,9 @@ func recoverPrimaryHasPrimary(ctx context.Context, analysisEntry *inst.Replicati // This has to be done in the end; whether successful or not, we should mark that the recovery is done. // So that after the active period passes, we are able to run other recoveries. defer func() { - _ = resolveRecovery(topologyRecovery, nil) + if err := resolveRecovery(topologyRecovery, nil); err != nil { + logger.Errorf("failed to resolve recovery for %q: %v", RecoverPrimaryHasPrimaryRecoveryName, err) + } }() // Read the tablet information from the database to find the shard and keyspace of the tablet @@ -253,7 +268,7 @@ func recoverPrimaryHasPrimary(ctx context.Context, analysisEntry *inst.Replicati // runEmergencyReparentOp runs a recovery for which we have to run ERS. Here waitForAllTablets is a boolean telling ERS whether it should wait for all the tablets // or is it okay to skip 1. -func runEmergencyReparentOp(ctx context.Context, analysisEntry *inst.ReplicationAnalysis, recoveryName string, waitForAllTablets bool, logger *log.PrefixedLogger) (recoveryAttempted bool, topologyRecovery *TopologyRecovery, err error) { +func runEmergencyReparentOp(ctx context.Context, analysisEntry *inst.DetectionAnalysis, recoveryName string, waitForAllTablets bool, logger *log.PrefixedLogger) (recoveryAttempted bool, topologyRecovery *TopologyRecovery, err error) { // Read the tablet information from the database to find the shard and keyspace of the tablet tablet, err := inst.ReadTablet(analysisEntry.AnalyzedInstanceAlias) if err != nil { @@ -273,7 +288,9 @@ func runEmergencyReparentOp(ctx context.Context, analysisEntry *inst.Replication // This has to be done in the end; whether successful or not, we should mark that the recovery is done. // So that after the active period passes, we are able to run other recoveries. defer func() { - _ = resolveRecovery(topologyRecovery, promotedReplica) + if err := resolveRecovery(topologyRecovery, promotedReplica); err != nil { + logger.Errorf("failed to resolve recovery for %q: %v", recoveryName, err) + } }() ev, err := reparentutil.NewEmergencyReparenter(ts, tmc, logutil.NewCallbackLogger(func(event *logutilpb.Event) { @@ -312,16 +329,16 @@ func runEmergencyReparentOp(ctx context.Context, analysisEntry *inst.Replication // recoverDeadPrimary checks a given analysis, decides whether to take action, and possibly takes action // Returns true when action was taken. -func recoverDeadPrimary(ctx context.Context, analysisEntry *inst.ReplicationAnalysis, logger *log.PrefixedLogger) (recoveryAttempted bool, topologyRecovery *TopologyRecovery, err error) { +func recoverDeadPrimary(ctx context.Context, analysisEntry *inst.DetectionAnalysis, logger *log.PrefixedLogger) (recoveryAttempted bool, topologyRecovery *TopologyRecovery, err error) { return runEmergencyReparentOp(ctx, analysisEntry, "RecoverDeadPrimary", false, logger) } // recoverPrimaryTabletDeleted tries to run a recovery for the case where the primary tablet has been deleted. -func recoverPrimaryTabletDeleted(ctx context.Context, analysisEntry *inst.ReplicationAnalysis, logger *log.PrefixedLogger) (recoveryAttempted bool, topologyRecovery *TopologyRecovery, err error) { +func recoverPrimaryTabletDeleted(ctx context.Context, analysisEntry *inst.DetectionAnalysis, logger *log.PrefixedLogger) (recoveryAttempted bool, topologyRecovery *TopologyRecovery, err error) { return runEmergencyReparentOp(ctx, analysisEntry, "PrimaryTabletDeleted", true, logger) } -func postErsCompletion(topologyRecovery *TopologyRecovery, analysisEntry *inst.ReplicationAnalysis, recoveryName string, promotedReplica *inst.Instance) { +func postErsCompletion(topologyRecovery *TopologyRecovery, analysisEntry *inst.DetectionAnalysis, recoveryName string, promotedReplica *inst.Instance) { if promotedReplica != nil { message := fmt.Sprintf("promoted replica: %+v", promotedReplica.InstanceAlias) _ = AuditTopologyRecovery(topologyRecovery, message) @@ -331,13 +348,13 @@ func postErsCompletion(topologyRecovery *TopologyRecovery, analysisEntry *inst.R } // checkAndRecoverGenericProblem is a general-purpose recovery function -func checkAndRecoverLockedSemiSyncPrimary(ctx context.Context, analysisEntry *inst.ReplicationAnalysis, logger *log.PrefixedLogger) (recoveryAttempted bool, topologyRecovery *TopologyRecovery, err error) { +func checkAndRecoverLockedSemiSyncPrimary(ctx context.Context, analysisEntry *inst.DetectionAnalysis, logger *log.PrefixedLogger) (recoveryAttempted bool, topologyRecovery *TopologyRecovery, err error) { logger.Warning("No actions in checkAndRecoverLockedSemiSyncPrimary") return false, nil, nil } // checkAndRecoverGenericProblem is a general-purpose recovery function -func checkAndRecoverGenericProblem(ctx context.Context, analysisEntry *inst.ReplicationAnalysis, logger *log.PrefixedLogger) (bool, *TopologyRecovery, error) { +func checkAndRecoverGenericProblem(ctx context.Context, analysisEntry *inst.DetectionAnalysis, logger *log.PrefixedLogger) (bool, *TopologyRecovery, error) { logger.Warning("No actions in checkAndRecoverGenericProblem") return false, nil, nil } @@ -374,6 +391,8 @@ func getCheckAndRecoverFunctionCode(analysisCode inst.AnalysisCode, tabletAlias return electNewPrimaryFunc case inst.PrimaryIsReadOnly, inst.PrimarySemiSyncMustBeSet, inst.PrimarySemiSyncMustNotBeSet, inst.PrimaryCurrentTypeMismatch: return fixPrimaryFunc + case inst.StaleTopoPrimary: + return demoteStaleTopoPrimaryFunc // replica case inst.NotConnectedToPrimary, inst.ConnectedToWrongPrimary, inst.ReplicationStopped, inst.ReplicaIsWritable, inst.ReplicaSemiSyncMustBeSet, inst.ReplicaSemiSyncMustNotBeSet, inst.ReplicaMisconfigured: @@ -421,6 +440,8 @@ func hasActionableRecovery(recoveryFunctionCode recoveryFunction) bool { return true case recoverErrantGTIDDetectedFunc: return true + case demoteStaleTopoPrimaryFunc: + return true default: return false } @@ -428,7 +449,7 @@ func hasActionableRecovery(recoveryFunctionCode recoveryFunction) bool { // getCheckAndRecoverFunction gets the recovery function for the given code. func getCheckAndRecoverFunction(recoveryFunctionCode recoveryFunction) ( - checkAndRecoverFunction func(ctx context.Context, analysisEntry *inst.ReplicationAnalysis, logger *log.PrefixedLogger) (recoveryAttempted bool, topologyRecovery *TopologyRecovery, err error), + checkAndRecoverFunction func(ctx context.Context, analysisEntry *inst.DetectionAnalysis, logger *log.PrefixedLogger) (recoveryAttempted bool, topologyRecovery *TopologyRecovery, err error), ) { switch recoveryFunctionCode { case noRecoveryFunc: @@ -451,6 +472,8 @@ func getCheckAndRecoverFunction(recoveryFunctionCode recoveryFunction) ( return fixReplica case recoverErrantGTIDDetectedFunc: return recoverErrantGTIDDetected + case demoteStaleTopoPrimaryFunc: + return demoteStaleTopoPrimary default: return nil } @@ -480,6 +503,8 @@ func getRecoverFunctionName(recoveryFunctionCode recoveryFunction) string { return FixReplicaRecoveryName case recoverErrantGTIDDetectedFunc: return RecoverErrantGTIDDetectedName + case demoteStaleTopoPrimaryFunc: + return DemoteStaleTopoPrimaryRecoveryName default: return "" } @@ -496,7 +521,7 @@ func isClusterWideRecovery(recoveryFunctionCode recoveryFunction) bool { } // analysisEntriesHaveSameRecovery tells whether the two analysis entries have the same recovery function or not -func analysisEntriesHaveSameRecovery(prevAnalysis, newAnalysis *inst.ReplicationAnalysis) bool { +func analysisEntriesHaveSameRecovery(prevAnalysis, newAnalysis *inst.DetectionAnalysis) bool { prevRecoveryFunctionCode := getCheckAndRecoverFunctionCode(prevAnalysis.Analysis, prevAnalysis.AnalyzedInstanceAlias) newRecoveryFunctionCode := getCheckAndRecoverFunctionCode(newAnalysis.Analysis, newAnalysis.AnalyzedInstanceAlias) return prevRecoveryFunctionCode == newRecoveryFunctionCode @@ -504,7 +529,7 @@ func analysisEntriesHaveSameRecovery(prevAnalysis, newAnalysis *inst.Replication // executeCheckAndRecoverFunction will choose the correct check & recovery function based on analysis. // It executes the function synchronously -func executeCheckAndRecoverFunction(analysisEntry *inst.ReplicationAnalysis) (err error) { +func executeCheckAndRecoverFunction(analysisEntry *inst.DetectionAnalysis) (err error) { countPendingRecoveries.Add(1) defer countPendingRecoveries.Add(-1) @@ -672,9 +697,9 @@ func executeCheckAndRecoverFunction(analysisEntry *inst.ReplicationAnalysis) (er } // checkIfAlreadyFixed checks whether the problem that the analysis entry represents has already been fixed by another agent or not -func checkIfAlreadyFixed(analysisEntry *inst.ReplicationAnalysis) (bool, error) { +func checkIfAlreadyFixed(analysisEntry *inst.DetectionAnalysis) (bool, error) { // Run a replication analysis again. We will check if the problem persisted - analysisEntries, err := inst.GetReplicationAnalysis(analysisEntry.ClusterDetails.Keyspace, analysisEntry.ClusterDetails.Shard, &inst.ReplicationAnalysisHints{}) + analysisEntries, err := inst.GetDetectionAnalysis(analysisEntry.ClusterDetails.Keyspace, analysisEntry.ClusterDetails.Shard, &inst.DetectionAnalysisHints{}) if err != nil { return false, err } @@ -690,31 +715,63 @@ func checkIfAlreadyFixed(analysisEntry *inst.ReplicationAnalysis) (bool, error) return true, nil } +// recoverShardAnalyses executes recoveries for a shard's analyses. Analyses +// that require ordered execution run sequentially first, then the remaining +// independent analyses fan out concurrently. +func recoverShardAnalyses(analyses []*inst.DetectionAnalysis, recoverFunc func(*inst.DetectionAnalysis) error) { + var concurrent []*inst.DetectionAnalysis + for _, analysisEntry := range analyses { + problem := inst.GetDetectionAnalysisProblem(analysisEntry.Analysis) + if problem != nil && problem.RequiresOrderedExecution() { + if err := recoverFunc(analysisEntry); err != nil { + log.Error(fmt.Sprintf("Failed to execute CheckAndRecover function: %+v", err)) + } + } else { + concurrent = append(concurrent, analysisEntry) + } + } + var wg sync.WaitGroup + for _, analysisEntry := range concurrent { + wg.Add(1) + go func() { + defer wg.Done() + if err := recoverFunc(analysisEntry); err != nil { + log.Error(fmt.Sprintf("Failed to execute CheckAndRecover function: %+v", err)) + } + }() + } + wg.Wait() +} + // CheckAndRecover is the main entry point for the recovery mechanism func CheckAndRecover() { // Allow the analysis to run even if we don't want to recover - replicationAnalysis, err := inst.GetReplicationAnalysis("", "", &inst.ReplicationAnalysisHints{AuditAnalysis: true}) + detectionAnalysis, err := inst.GetDetectionAnalysis("", "", &inst.DetectionAnalysisHints{AuditAnalysis: true}) if err != nil { log.Error(err) return } + analysisByShard := inst.GroupDetectionAnalysesByShard(detectionAnalysis) + // Regardless of if the problem is solved or not we want to monitor active // issues, we use a map of labels and set a counter to `1` for each problem // then we reset any counter that is not present in the current analysis. active := make(map[string]struct{}) - for _, e := range replicationAnalysis { - if e.Analysis != inst.NoProblem { - names := [...]string{ - string(e.Analysis), - e.AnalyzedInstanceAlias, - e.AnalyzedKeyspace, - e.AnalyzedShard, + for _, shardAnalyses := range analysisByShard { + for _, e := range shardAnalyses { + if e.Analysis != inst.NoProblem { + names := [...]string{ + string(e.Analysis), + e.AnalyzedInstanceAlias, + e.AnalyzedKeyspace, + e.AnalyzedShard, + } + + key := detectedProblems.GetLabelName(names[:]...) + active[key] = struct{}{} + detectedProblems.Set(names[:], 1) } - - key := detectedProblems.GetLabelName(names[:]...) - active[key] = struct{}{} - detectedProblems.Set(names[:], 1) } } @@ -725,19 +782,23 @@ func CheckAndRecover() { } } - // intentionally iterating entries in random order - for _, j := range rand.Perm(len(replicationAnalysis)) { - analysisEntry := replicationAnalysis[j] - + // Shuffle shard keys to ensure random processing order. Randomness helps reduce + // global shard lock contention when many VTOrcs watch the same shard(s). Within + // each shard, analyses are sorted by priority. Problems that require ordered + // execution (shard-wide actions or those with Before/After dependencies) run + // sequentially first, then independent problems fan out concurrently. + shardKeys := slices.Collect(maps.Keys(analysisByShard)) + rand.Shuffle(len(shardKeys), func(i, j int) { + shardKeys[i], shardKeys[j] = shardKeys[j], shardKeys[i] + }) + for _, key := range shardKeys { go func() { - if err := executeCheckAndRecoverFunction(analysisEntry); err != nil { - log.Error(err) - } + recoverShardAnalyses(analysisByShard[key], executeCheckAndRecoverFunction) }() } } -func postPrsCompletion(topologyRecovery *TopologyRecovery, analysisEntry *inst.ReplicationAnalysis, promotedReplica *inst.Instance) { +func postPrsCompletion(topologyRecovery *TopologyRecovery, analysisEntry *inst.DetectionAnalysis, promotedReplica *inst.Instance) { if promotedReplica != nil { message := fmt.Sprintf("promoted replica: %+v", promotedReplica.InstanceAlias) _ = AuditTopologyRecovery(topologyRecovery, message) @@ -747,7 +808,7 @@ func postPrsCompletion(topologyRecovery *TopologyRecovery, analysisEntry *inst.R } // electNewPrimary elects a new primary while none were present before. -func electNewPrimary(ctx context.Context, analysisEntry *inst.ReplicationAnalysis, logger *log.PrefixedLogger) (recoveryAttempted bool, topologyRecovery *TopologyRecovery, err error) { +func electNewPrimary(ctx context.Context, analysisEntry *inst.DetectionAnalysis, logger *log.PrefixedLogger) (recoveryAttempted bool, topologyRecovery *TopologyRecovery, err error) { topologyRecovery, err = AttemptRecoveryRegistration(analysisEntry) if topologyRecovery == nil || err != nil { message := fmt.Sprintf("found an active or recent recovery on %+v. Will not issue another electNewPrimary.", analysisEntry.AnalyzedInstanceAlias) @@ -761,7 +822,9 @@ func electNewPrimary(ctx context.Context, analysisEntry *inst.ReplicationAnalysi // This has to be done in the end; whether successful or not, we should mark that the recovery is done. // So that after the active period passes, we are able to run other recoveries. defer func() { - _ = resolveRecovery(topologyRecovery, promotedReplica) + if err := resolveRecovery(topologyRecovery, promotedReplica); err != nil { + logger.Errorf("failed to resolve recovery for %q: %v", ElectNewPrimaryRecoveryName, err) + } }() analyzedTablet, err := inst.ReadTablet(analysisEntry.AnalyzedInstanceAlias) @@ -799,7 +862,7 @@ func electNewPrimary(ctx context.Context, analysisEntry *inst.ReplicationAnalysi } // fixPrimary sets the primary as read-write. -func fixPrimary(ctx context.Context, analysisEntry *inst.ReplicationAnalysis, logger *log.PrefixedLogger) (recoveryAttempted bool, topologyRecovery *TopologyRecovery, err error) { +func fixPrimary(ctx context.Context, analysisEntry *inst.DetectionAnalysis, logger *log.PrefixedLogger) (recoveryAttempted bool, topologyRecovery *TopologyRecovery, err error) { topologyRecovery, err = AttemptRecoveryRegistration(analysisEntry) if topologyRecovery == nil { message := fmt.Sprintf("found an active or recent recovery on %+v. Will not issue another fixPrimary.", analysisEntry.AnalyzedInstanceAlias) @@ -811,7 +874,9 @@ func fixPrimary(ctx context.Context, analysisEntry *inst.ReplicationAnalysis, lo // This has to be done in the end; whether successful or not, we should mark that the recovery is done. // So that after the active period passes, we are able to run other recoveries. defer func() { - _ = resolveRecovery(topologyRecovery, nil) + if err := resolveRecovery(topologyRecovery, nil); err != nil { + logger.Errorf("failed to resolve recovery for %q: %v", FixPrimaryRecoveryName, err) + } }() analyzedTablet, err := inst.ReadTablet(analysisEntry.AnalyzedInstanceAlias) @@ -833,7 +898,7 @@ func fixPrimary(ctx context.Context, analysisEntry *inst.ReplicationAnalysis, lo } // fixReplica sets the replica as read-only and points it at the current primary. -func fixReplica(ctx context.Context, analysisEntry *inst.ReplicationAnalysis, logger *log.PrefixedLogger) (recoveryAttempted bool, topologyRecovery *TopologyRecovery, err error) { +func fixReplica(ctx context.Context, analysisEntry *inst.DetectionAnalysis, logger *log.PrefixedLogger) (recoveryAttempted bool, topologyRecovery *TopologyRecovery, err error) { topologyRecovery, err = AttemptRecoveryRegistration(analysisEntry) if topologyRecovery == nil { message := fmt.Sprintf("found an active or recent recovery on %+v. Will not issue another fixReplica.", analysisEntry.AnalyzedInstanceAlias) @@ -845,7 +910,9 @@ func fixReplica(ctx context.Context, analysisEntry *inst.ReplicationAnalysis, lo // This has to be done in the end; whether successful or not, we should mark that the recovery is done. // So that after the active period passes, we are able to run other recoveries. defer func() { - _ = resolveRecovery(topologyRecovery, nil) + if err := resolveRecovery(topologyRecovery, nil); err != nil { + logger.Errorf("failed to resolve recovery for %q: %v", FixReplicaRecoveryName, err) + } }() analyzedTablet, err := inst.ReadTablet(analysisEntry.AnalyzedInstanceAlias) @@ -876,8 +943,81 @@ func fixReplica(ctx context.Context, analysisEntry *inst.ReplicationAnalysis, lo return true, topologyRecovery, err } +// demoteStaleTopoPrimary demotes a tablet that has a stale type of PRIMARY in the topology when a newer primary has +// been elected. It demotes the tablet, updates its type to REPLICA in the topology, and sets its replication source +// to the current primary. +func demoteStaleTopoPrimary(ctx context.Context, analysisEntry *inst.DetectionAnalysis, logger *log.PrefixedLogger) (recoveryAttempted bool, topologyRecovery *TopologyRecovery, err error) { + alias := analysisEntry.AnalyzedInstanceAlias + + // Register the recovery before touching topology so multiple VTOrc instances do not race the demotion. + topologyRecovery, err = AttemptRecoveryRegistration(analysisEntry) + if topologyRecovery == nil { + message := fmt.Sprintf("found an active or recent recovery on %+v. Will not issue another demoteStaleTopoPrimary.", analysisEntry.AnalyzedInstanceAlias) + logger.Warning(message) + _ = AuditTopologyRecovery(topologyRecovery, message) + return false, nil, err + } + + logger.Infof("Analysis: %v, will demote stale topo primary %+v", analysisEntry.Analysis, analysisEntry.AnalyzedInstanceAlias) + // This has to be done in the end; whether successful or not, we should mark that the recovery is done. + // So that after the active period passes, we are able to run other recoveries. + defer func() { + if err := resolveRecovery(topologyRecovery, nil); err != nil { + logger.Errorf("failed to resolve recovery for %q: %v", DemoteStaleTopoPrimaryRecoveryName, err) + } + }() + + analyzedTablet, err := inst.ReadTablet(alias) + if err != nil { + logger.Errorf("Failed to read instance %q, aborting recovery", analysisEntry.AnalyzedInstanceAlias) + return false, topologyRecovery, fmt.Errorf("failed to read instance: %w", err) + } + + primaryTablet, err := shardPrimary(analyzedTablet.Keyspace, analyzedTablet.Shard) + if err != nil { + logger.Infof("Could not compute primary for %s/%s", analyzedTablet.Keyspace, analyzedTablet.Shard) + return false, topologyRecovery, fmt.Errorf("failed to find primary for shard: %w", err) + } + + durabilityPolicy, err := inst.GetDurabilityPolicy(analyzedTablet.Keyspace) + if err != nil { + logger.Infof("Could not read the durability policy for %s/%s", analyzedTablet.Keyspace, analyzedTablet.Shard) + return false, topologyRecovery, fmt.Errorf("failed to read the durability policy for the keyspace: %w", err) + } + + // Demote the tablet, forcing it to drop any pending transactions that are waiting for an ack. + _, err = forceDemotePrimary(ctx, analyzedTablet) + if err != nil { + return true, topologyRecovery, fmt.Errorf("failed to demote stale primary: %w", err) + } + logger.Info("Successfully demoted the stale primary " + analysisEntry.AnalyzedInstanceAlias) + + // Set tablet to REPLICA in topology. + semiSync := policy.IsReplicaSemiSync(durabilityPolicy, primaryTablet, analyzedTablet) + err = changeTabletType(ctx, analyzedTablet, topodatapb.TabletType_REPLICA, semiSync) + if err != nil { + return true, topologyRecovery, fmt.Errorf("failed to set tablet type to REPLICA in topology: %w", err) + } + + // Set the instance's replication source to the current primary. + err = setReplicationSource(ctx, analyzedTablet, primaryTablet, semiSync, float64(analysisEntry.ReplicaNetTimeout)/2) + if err != nil { + return true, topologyRecovery, fmt.Errorf("failed to repoint replication to primary: %w", err) + } + + return true, topologyRecovery, err +} + +// forceDemotePrimary calls the DemotePrimary RPC for the given tablet. +func forceDemotePrimary(ctx context.Context, tablet *topodatapb.Tablet) (*replicationdatapb.PrimaryStatus, error) { + ctx, cancel := context.WithTimeout(ctx, topo.RemoteOperationTimeout) + defer cancel() + + return tmc.DemotePrimary(ctx, tablet, true) +} + // recoverErrantGTIDDetected changes the tablet type of a replica tablet that has errant GTIDs. -func recoverErrantGTIDDetected(ctx context.Context, analysisEntry *inst.ReplicationAnalysis, logger *log.PrefixedLogger) (recoveryAttempted bool, topologyRecovery *TopologyRecovery, err error) { +func recoverErrantGTIDDetected(ctx context.Context, analysisEntry *inst.DetectionAnalysis, logger *log.PrefixedLogger) (recoveryAttempted bool, topologyRecovery *TopologyRecovery, err error) { topologyRecovery, err = AttemptRecoveryRegistration(analysisEntry) if topologyRecovery == nil { message := fmt.Sprintf("found an active or recent recovery on %+v. Will not issue another recoverErrantGTIDDetected.", analysisEntry.AnalyzedInstanceAlias) @@ -889,7 +1029,9 @@ func recoverErrantGTIDDetected(ctx context.Context, analysisEntry *inst.Replicat // This has to be done in the end; whether successful or not, we should mark that the recovery is done. // So that after the active period passes, we are able to run other recoveries. defer func() { - _ = resolveRecovery(topologyRecovery, nil) + if err := resolveRecovery(topologyRecovery, nil); err != nil { + logger.Errorf("failed to resolve recovery for %q: %v", RecoverErrantGTIDDetectedName, err) + } }() analyzedTablet, err := inst.ReadTablet(analysisEntry.AnalyzedInstanceAlias) diff --git a/go/vt/vtorc/logic/topology_recovery_dao.go b/go/vt/vtorc/logic/topology_recovery_dao.go index 137251c4fc8..ff6cf3755bb 100644 --- a/go/vt/vtorc/logic/topology_recovery_dao.go +++ b/go/vt/vtorc/logic/topology_recovery_dao.go @@ -29,7 +29,7 @@ import ( ) // InsertRecoveryDetection inserts the recovery analysis that has been detected. -func InsertRecoveryDetection(analysisEntry *inst.ReplicationAnalysis) error { +func InsertRecoveryDetection(analysisEntry *inst.DetectionAnalysis) error { sqlResult, err := db.ExecVTOrc(`INSERT OR IGNORE INTO recovery_detection ( alias, @@ -109,7 +109,7 @@ func writeTopologyRecovery(topologyRecovery *TopologyRecovery) (*TopologyRecover } // AttemptRecoveryRegistration tries to add a recovery entry; if this fails that means recovery is already in place. -func AttemptRecoveryRegistration(analysisEntry *inst.ReplicationAnalysis) (*TopologyRecovery, error) { +func AttemptRecoveryRegistration(analysisEntry *inst.DetectionAnalysis) (*TopologyRecovery, error) { // Check if there is an active recovery in progress for the cluster of the given instance. recoveries, err := ReadActiveClusterRecoveries(analysisEntry.ClusterDetails.Keyspace, analysisEntry.ClusterDetails.Shard) if err != nil { @@ -180,7 +180,7 @@ func readRecoveries(whereCondition string, limit string, args []any) ([]*Topolog limit, ) err := db.QueryVTOrc(query, args, func(m sqlutils.RowMap) error { - topologyRecovery := *NewTopologyRecovery(inst.ReplicationAnalysis{}) + topologyRecovery := *NewTopologyRecovery(inst.DetectionAnalysis{}) topologyRecovery.ID = m.GetInt64("recovery_id") topologyRecovery.RecoveryStartTimestamp = m.GetString("start_recovery") diff --git a/go/vt/vtorc/logic/topology_recovery_dao_test.go b/go/vt/vtorc/logic/topology_recovery_dao_test.go index 6a1d7c4c48f..a84c2bb1fca 100644 --- a/go/vt/vtorc/logic/topology_recovery_dao_test.go +++ b/go/vt/vtorc/logic/topology_recovery_dao_test.go @@ -39,7 +39,7 @@ func TestTopologyRecovery(t *testing.T) { require.NoError(t, err) }() - replicationAnalysis := inst.ReplicationAnalysis{ + detectionAnalysis := inst.DetectionAnalysis{ AnalyzedInstanceAlias: "zone1-0000000101", TabletType: tab101.Type, ClusterDetails: inst.ClusterInfo{ @@ -51,7 +51,7 @@ func TestTopologyRecovery(t *testing.T) { Analysis: inst.ReplicaIsWritable, IsReadOnly: false, } - topologyRecovery := NewTopologyRecovery(replicationAnalysis) + topologyRecovery := NewTopologyRecovery(detectionAnalysis) t.Run("writing to topology recovery", func(t *testing.T) { topologyRecovery, err = writeTopologyRecovery(topologyRecovery) @@ -142,7 +142,7 @@ func TestInsertRecoveryDetection(t *testing.T) { defer func() { db.ClearVTOrcDatabase() }() - ra := &inst.ReplicationAnalysis{ + ra := &inst.DetectionAnalysis{ AnalyzedInstanceAlias: "alias-1", Analysis: inst.ClusterHasNoPrimary, ClusterDetails: inst.ClusterInfo{ diff --git a/go/vt/vtorc/logic/topology_recovery_test.go b/go/vt/vtorc/logic/topology_recovery_test.go index de9ecd02848..069b5225074 100644 --- a/go/vt/vtorc/logic/topology_recovery_test.go +++ b/go/vt/vtorc/logic/topology_recovery_test.go @@ -18,6 +18,7 @@ package logic import ( "context" + "sync" "testing" "vitess.io/vitess/go/vt/log" @@ -105,7 +106,7 @@ func TestAnalysisEntriesHaveSameRecovery(t *testing.T) { t.Parallel() for _, tt := range tests { t.Run(string(tt.prevAnalysisCode)+","+string(tt.newAnalysisCode), func(t *testing.T) { - res := analysisEntriesHaveSameRecovery(&inst.ReplicationAnalysis{Analysis: tt.prevAnalysisCode}, &inst.ReplicationAnalysis{Analysis: tt.newAnalysisCode}) + res := analysisEntriesHaveSameRecovery(&inst.DetectionAnalysis{Analysis: tt.prevAnalysisCode}, &inst.DetectionAnalysis{Analysis: tt.newAnalysisCode}) require.Equal(t, tt.shouldBeEqual, res) }) } @@ -135,7 +136,7 @@ func TestElectNewPrimaryPanic(t *testing.T) { } err = inst.SaveTablet(tablet) require.NoError(t, err) - analysisEntry := &inst.ReplicationAnalysis{ + analysisEntry := &inst.DetectionAnalysis{ AnalyzedInstanceAlias: topoproto.TabletAliasString(tablet.Alias), } ctx, cancel := context.WithCancel(context.Background()) @@ -185,11 +186,11 @@ func TestRecoveryRegistration(t *testing.T) { require.NoError(t, err) err = inst.SaveTablet(replica) require.NoError(t, err) - primaryAnalysisEntry := inst.ReplicationAnalysis{ + primaryAnalysisEntry := inst.DetectionAnalysis{ AnalyzedInstanceAlias: topoproto.TabletAliasString(primary.Alias), Analysis: inst.ReplicationStopped, } - replicaAnalysisEntry := inst.ReplicationAnalysis{ + replicaAnalysisEntry := inst.DetectionAnalysis{ AnalyzedInstanceAlias: topoproto.TabletAliasString(replica.Alias), Analysis: inst.DeadPrimary, } @@ -311,3 +312,34 @@ func TestGetCheckAndRecoverFunctionCode(t *testing.T) { }) } } + +func TestRecoverShardAnalyses(t *testing.T) { + // DeadPrimary and PrimaryHasPrimary have detectionAnalysisPriorityShardWideAction, + // so they require ordered execution. ReplicationStopped and ReplicaIsWritable are + // medium priority with no shard-wide action or before/after dependencies, + // so they run concurrently. + analyses := []*inst.DetectionAnalysis{ + {Analysis: inst.ReplicationStopped, AnalyzedInstanceAlias: "replica1"}, + {Analysis: inst.DeadPrimary, AnalyzedInstanceAlias: "primary1"}, + {Analysis: inst.ReplicaIsWritable, AnalyzedInstanceAlias: "replica2"}, + {Analysis: inst.PrimaryHasPrimary, AnalyzedInstanceAlias: "primary2"}, + } + + var mu sync.Mutex + var order []inst.AnalysisCode + recoverFunc := func(entry *inst.DetectionAnalysis) error { + mu.Lock() + defer mu.Unlock() + order = append(order, entry.Analysis) + return nil + } + + recoverShardAnalyses(analyses, recoverFunc) + + require.Len(t, order, 4) + // Ordered recoveries must come first, in their original order. + require.Equal(t, inst.DeadPrimary, order[0]) + require.Equal(t, inst.PrimaryHasPrimary, order[1]) + // Concurrent recoveries come after, in any order. + require.ElementsMatch(t, []inst.AnalysisCode{inst.ReplicationStopped, inst.ReplicaIsWritable}, order[2:]) +} diff --git a/go/vt/vtorc/logic/vtorc.go b/go/vt/vtorc/logic/vtorc.go index 45568cd745c..e76d04ccab4 100644 --- a/go/vt/vtorc/logic/vtorc.go +++ b/go/vt/vtorc/logic/vtorc.go @@ -201,8 +201,10 @@ func DiscoverInstance(tabletAlias string, forceDiscovery bool) { discoverInstanceTimings.Add("Instance", instanceLatency) discoverInstanceTimings.Add("Other", otherLatency) - if forceDiscovery { - log.Infof("Force discovered - %+v, err - %v", instance, err) + if err != nil { + log.Errorf("Failed to discover %s (force: %t), err: %v", tabletAlias, forceDiscovery, err) + } else { + log.Infof("Discovered %s (force: %t): %+v", tabletAlias, forceDiscovery, instance) } if instance == nil { @@ -217,7 +219,7 @@ func DiscoverInstance(tabletAlias string, forceDiscovery bool) { } _ = discoveryMetrics.Append(metric) if util.ClearToLog("discoverInstance", tabletAlias) { - log.Warningf(" DiscoverInstance(%+v) instance is nil in %.3fs (Backend: %.3fs, Instance: %.3fs), error=%+v", + log.Warningf("DiscoverInstance(%+v) instance is nil in %.3fs (Backend: %.3fs, Instance: %.3fs), error=%+v", tabletAlias, totalLatency.Seconds(), backendLatency.Seconds(), diff --git a/go/vt/vtorc/server/api.go b/go/vt/vtorc/server/api.go index 177f2c80333..8b524c5c238 100644 --- a/go/vt/vtorc/server/api.go +++ b/go/vt/vtorc/server/api.go @@ -250,14 +250,14 @@ func replicationAnalysisAPIHandler(response http.ResponseWriter, request *http.R http.Error(response, shardWithoutKeyspaceFilteringErrorStr, http.StatusBadRequest) return } - analysis, err := inst.GetReplicationAnalysis(keyspace, shard, &inst.ReplicationAnalysisHints{}) + analysis, err := inst.GetDetectionAnalysis(keyspace, shard, &inst.DetectionAnalysisHints{}) if err != nil { http.Error(response, err.Error(), http.StatusInternalServerError) return } // TODO: We can also add filtering for a specific instance too based on the tablet alias. - // Currently inst.ReplicationAnalysis doesn't store the tablet alias, but once it does we can filter on that too + // Currently inst.DetectionAnalysis doesn't store the tablet alias, but once it does we can filter on that too returnAsJSON(response, http.StatusOK, analysis) } diff --git a/go/vt/vtorc/test/recovery_analysis.go b/go/vt/vtorc/test/recovery_analysis.go index 0335fba17b9..ea1c25708e3 100644 --- a/go/vt/vtorc/test/recovery_analysis.go +++ b/go/vt/vtorc/test/recovery_analysis.go @@ -76,6 +76,7 @@ type InfoForRecoveryAnalysis struct { CountMixedBasedLoggingReplicas uint CountRowBasedLoggingReplicas uint CountDistinctMajorVersionsLoggingReplicas uint + CountValidSemiSyncReplicatingReplicas uint CountDelayedReplicas uint CountLaggingReplicas uint MinReplicaGTIDMode string @@ -106,7 +107,7 @@ func (info *InfoForRecoveryAnalysis) ConvertToRowMap() sqlutils.RowMap { rowMap["count_valid_oracle_gtid_replicas"] = sqlutils.CellData{String: fmt.Sprintf("%v", info.CountValidOracleGTIDReplicas), Valid: true} rowMap["count_valid_replicas"] = sqlutils.CellData{String: fmt.Sprintf("%v", info.CountValidReplicas), Valid: true} rowMap["count_valid_replicating_replicas"] = sqlutils.CellData{String: fmt.Sprintf("%v", info.CountValidReplicatingReplicas), Valid: true} - rowMap["data_center"] = sqlutils.CellData{String: info.DataCenter, Valid: true} + rowMap["count_valid_semi_sync_replicating_replicas"] = sqlutils.CellData{String: fmt.Sprintf("%v", info.CountValidSemiSyncReplicatingReplicas), Valid: true} rowMap["downtime_end_timestamp"] = sqlutils.CellData{String: info.DowntimeEndTimestamp, Valid: true} rowMap["downtime_remaining_seconds"] = sqlutils.CellData{String: fmt.Sprintf("%v", info.DowntimeRemainingSeconds), Valid: true} rowMap["durability_policy"] = sqlutils.CellData{String: info.DurabilityPolicy, Valid: true} @@ -137,7 +138,13 @@ func (info *InfoForRecoveryAnalysis) ConvertToRowMap() sqlutils.RowMap { res, _ := prototext.Marshal(info.PrimaryTabletInfo) rowMap["primary_tablet_info"] = sqlutils.CellData{String: string(res), Valid: true} } - rowMap["primary_timestamp"] = sqlutils.CellData{String: fmt.Sprintf("%v", info.PrimaryTimestamp), Valid: true} + + primaryTimestamp := fmt.Sprintf("%v", info.PrimaryTimestamp) + if info.PrimaryTimestamp != nil { + primaryTimestamp = info.PrimaryTimestamp.UTC().Format(sqlutils.DateTimeFormat) + } + rowMap["primary_timestamp"] = sqlutils.CellData{String: primaryTimestamp, Valid: true} + rowMap["read_only"] = sqlutils.CellData{String: fmt.Sprintf("%v", info.ReadOnly), Valid: true} rowMap["region"] = sqlutils.CellData{String: info.Region, Valid: true} rowMap["replication_stopped"] = sqlutils.CellData{String: fmt.Sprintf("%v", info.ReplicationStopped), Valid: true} diff --git a/go/vt/vttablet/faketmclient/fake_client.go b/go/vt/vttablet/faketmclient/fake_client.go index 5a5cd33535f..6ee84bb5926 100644 --- a/go/vt/vttablet/faketmclient/fake_client.go +++ b/go/vt/vttablet/faketmclient/fake_client.go @@ -363,7 +363,7 @@ func (client *FakeTabletManagerClient) ReadReparentJournalInfo(ctx context.Conte } // DemotePrimary is part of the tmclient.TabletManagerClient interface. -func (client *FakeTabletManagerClient) DemotePrimary(ctx context.Context, tablet *topodatapb.Tablet) (*replicationdatapb.PrimaryStatus, error) { +func (client *FakeTabletManagerClient) DemotePrimary(ctx context.Context, tablet *topodatapb.Tablet, force bool) (*replicationdatapb.PrimaryStatus, error) { return nil, nil } diff --git a/go/vt/vttablet/grpctmclient/client.go b/go/vt/vttablet/grpctmclient/client.go index f6d154570eb..b9bb6bdf101 100644 --- a/go/vt/vttablet/grpctmclient/client.go +++ b/go/vt/vttablet/grpctmclient/client.go @@ -577,7 +577,7 @@ func (client *Client) ExecuteFetchAsDba(ctx context.Context, tablet *topodatapb. DbName: topoproto.TabletDbName(tablet), MaxRows: req.MaxRows, DisableBinlogs: req.DisableBinlogs, - ReloadSchema: req.DisableBinlogs, + ReloadSchema: req.ReloadSchema, DisableForeignKeyChecks: req.DisableForeignKeyChecks, }) if err != nil { @@ -613,7 +613,7 @@ func (client *Client) ExecuteMultiFetchAsDba(ctx context.Context, tablet *topoda DbName: topoproto.TabletDbName(tablet), MaxRows: req.MaxRows, DisableBinlogs: req.DisableBinlogs, - ReloadSchema: req.DisableBinlogs, + ReloadSchema: req.ReloadSchema, DisableForeignKeyChecks: req.DisableForeignKeyChecks, }) if err != nil { @@ -1154,13 +1154,13 @@ func (client *Client) InitReplica(ctx context.Context, tablet *topodatapb.Tablet } // DemotePrimary is part of the tmclient.TabletManagerClient interface. -func (client *Client) DemotePrimary(ctx context.Context, tablet *topodatapb.Tablet) (*replicationdatapb.PrimaryStatus, error) { +func (client *Client) DemotePrimary(ctx context.Context, tablet *topodatapb.Tablet, force bool) (*replicationdatapb.PrimaryStatus, error) { c, closer, err := client.dialer.dial(ctx, tablet) if err != nil { return nil, err } defer closer.Close() - response, err := c.DemotePrimary(ctx, &tabletmanagerdatapb.DemotePrimaryRequest{}) + response, err := c.DemotePrimary(ctx, &tabletmanagerdatapb.DemotePrimaryRequest{Force: force}) if err != nil { return nil, err } diff --git a/go/vt/vttablet/grpctmserver/server.go b/go/vt/vttablet/grpctmserver/server.go index be1b8ae9372..4d2db680276 100644 --- a/go/vt/vttablet/grpctmserver/server.go +++ b/go/vt/vttablet/grpctmserver/server.go @@ -18,6 +18,7 @@ package grpctmserver import ( "context" + "path/filepath" "time" "google.golang.org/grpc" @@ -35,6 +36,7 @@ import ( querypb "vitess.io/vitess/go/vt/proto/query" tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" tabletmanagerservicepb "vitess.io/vitess/go/vt/proto/tabletmanagerservice" + vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" ) // server is the gRPC implementation of the RPC server @@ -64,6 +66,9 @@ func (s *server) Sleep(ctx context.Context, request *tabletmanagerdatapb.SleepRe func (s *server) ExecuteHook(ctx context.Context, request *tabletmanagerdatapb.ExecuteHookRequest) (response *tabletmanagerdatapb.ExecuteHookResponse, err error) { defer s.tm.HandleRPCPanic(ctx, "ExecuteHook", request, response, true /*verbose*/, &err) ctx = callinfo.GRPCCallInfo(ctx) + if request.Name == "" || filepath.Base(request.Name) != request.Name { + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "hook name must be a basename, got %q", request.Name) + } response = &tabletmanagerdatapb.ExecuteHookResponse{} hr := s.tm.ExecuteHook(ctx, &hook.Hook{ Name: request.Name, @@ -586,7 +591,7 @@ func (s *server) DemotePrimary(ctx context.Context, request *tabletmanagerdatapb defer s.tm.HandleRPCPanic(ctx, "DemotePrimary", request, response, true /*verbose*/, &err) ctx = callinfo.GRPCCallInfo(ctx) response = &tabletmanagerdatapb.DemotePrimaryResponse{} - status, err := s.tm.DemotePrimary(ctx) + status, err := s.tm.DemotePrimary(ctx, request.Force) if err == nil { response.PrimaryStatus = status } diff --git a/go/vt/vttablet/onlineddl/executor.go b/go/vt/vttablet/onlineddl/executor.go index c8f9c261aff..fba86a6f2e2 100644 --- a/go/vt/vttablet/onlineddl/executor.go +++ b/go/vt/vttablet/onlineddl/executor.go @@ -74,18 +74,18 @@ var ( ErrMigrationNotFound = errors.New("migration not found") ) +// fixCompletedTimestampDone fixes a nil `completed_timestamp` columns, see +// https://github.com/vitessio/vitess/issues/13927 +// The fix is in release-18.0 +// TODO: remove in release-19.0 +var fixCompletedTimestampDone bool + var ( - // fixCompletedTimestampDone fixes a nil `completed_timestamp` columns, see - // https://github.com/vitessio/vitess/issues/13927 - // The fix is in release-18.0 - // TODO: remove in release-19.0 - fixCompletedTimestampDone bool + emptyResult = &sqltypes.Result{} + acceptableDropTableIfExistsErrorCodes = []sqlerror.ErrorCode{sqlerror.ERCantFindFile, sqlerror.ERNoSuchTable} + copyAlgorithm = sqlparser.AlgorithmValue(sqlparser.CopyStr) ) -var emptyResult = &sqltypes.Result{} -var acceptableDropTableIfExistsErrorCodes = []sqlerror.ErrorCode{sqlerror.ERCantFindFile, sqlerror.ERNoSuchTable} -var copyAlgorithm = sqlparser.AlgorithmValue(sqlparser.CopyStr) - var ( migrationCheckInterval = 1 * time.Minute retainOnlineDDLTables = 24 * time.Hour @@ -96,9 +96,10 @@ var ( ) const ( - defaultCutOverThreshold = 10 * time.Second - minCutOverThreshold = 5 * time.Second - maxCutOverThreshold = 30 * time.Second + defaultCutOverThreshold = 10 * time.Second + minCutOverThreshold = 5 * time.Second + maxCutOverThreshold = 30 * time.Second + waitTimeoutDuringCutOver = 365 * 24 * time.Hour // maximum MySQL wait_timeout ) func init() { @@ -498,7 +499,6 @@ func (e *Executor) executeDirectly(ctx context.Context, onlineDDL *schema.Online defer conn.ExecuteFetch("SET foreign_key_checks=@vt_onlineddl_foreign_key_checks", 0, false) } _, err = conn.ExecuteFetch(onlineDDL.SQL, 0, false) - if err != nil { // let's see if this error is actually acceptable if merr, ok := err.(*sqlerror.SQLError); ok { @@ -876,11 +876,26 @@ func (e *Executor) cutOverVReplMigration(ctx context.Context, s *VReplStream, sh e.updateMigrationStage(ctx, onlineDDL.UUID, "post-sentry pos reached") } + renameWasSuccessful := false lockConn, err := e.pool.Get(ctx, nil) if err != nil { return vterrors.Wrapf(err, "failed getting locking connection") } defer lockConn.Recycle() + defer func() { + // Always attempt UNLOCK TABLES first, as it releases locks immediately on this + // connection. Then kill the connection as a fallback to guarantee any held locks + // are released, even if UNLOCK TABLES were to fail. + unlockCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + if _, err := lockConn.Conn.Exec(unlockCtx, sqlUnlockTables, 1, false); err != nil { + log.Warningf("Failed to UNLOCK TABLES in OnlineDDL migration %s: %v", onlineDDL.UUID, err) + } + if err := lockConn.Conn.Kill("closing lock tables connection", 0); err != nil { + log.Errorf("Failed to kill lock tables connection in OnlineDDL migration %s: %v", onlineDDL.UUID, err) + } + }() + // Set large enough `@@lock_wait_timeout` so that it does not interfere with the cut-over operation. // The code will ensure everything that needs to be terminated by `onlineDDL.CutOverThreshold` will be terminated. lockConnRestoreLockWaitTimeout, err := e.initConnectionLockWaitTimeout(ctx, lockConn.Conn, 5*onlineDDL.CutOverThreshold) @@ -888,20 +903,17 @@ func (e *Executor) cutOverVReplMigration(ctx context.Context, s *VReplStream, sh return vterrors.Wrapf(err, "failed setting lock_wait_timeout on locking connection") } defer lockConnRestoreLockWaitTimeout() - defer lockConn.Conn.Exec(ctx, sqlUnlockTables, 1, false) + lockConnRestoreWaitTimeout, err := e.initConnectionSessionTimeout(ctx, lockConn.Conn, "wait_timeout", waitTimeoutDuringCutOver) + if err != nil { + return vterrors.Wrapf(err, "failed ensuring wait_timeout on locking connection") + } + defer lockConnRestoreWaitTimeout() renameCompleteChan := make(chan error) - renameWasSuccessful := false renameConn, err := e.pool.Get(ctx, nil) if err != nil { return vterrors.Wrapf(err, "failed getting rename connection") } - // Set large enough `@@lock_wait_timeout` so that it does not interfere with the cut-over operation. - // The code will ensure everything that needs to be terminated by `onlineDDL.CutOverThreshold` will be terminated. - renameConnRestoreLockWaitTimeout, err := e.initConnectionLockWaitTimeout(ctx, renameConn.Conn, 5*onlineDDL.CutOverThreshold*4) - if err != nil { - return vterrors.Wrapf(err, "failed setting lock_wait_timeout on rename connection") - } defer renameConn.Recycle() defer func() { if !renameWasSuccessful { @@ -911,7 +923,18 @@ func (e *Executor) cutOverVReplMigration(ctx context.Context, s *VReplStream, sh } } }() + // Set large enough `@@lock_wait_timeout` so that it does not interfere with the cut-over operation. + // The code will ensure everything that needs to be terminated by `onlineDDL.CutOverThreshold` will be terminated. + renameConnRestoreLockWaitTimeout, err := e.initConnectionLockWaitTimeout(ctx, renameConn.Conn, 2*onlineDDL.CutOverThreshold) + if err != nil { + return vterrors.Wrapf(err, "failed setting lock_wait_timeout on rename connection") + } defer renameConnRestoreLockWaitTimeout() + renameConnRestoreWaitTimeout, err := e.initConnectionSessionTimeout(ctx, renameConn.Conn, "wait_timeout", waitTimeoutDuringCutOver) + if err != nil { + return vterrors.Wrapf(err, "failed ensuring wait_timeout on rename connection") + } + defer renameConnRestoreWaitTimeout() // See if backend MySQL server supports 'rename_table_preserve_foreign_key' variable preserveFKSupported, err := e.isPreserveForeignKeySupported(ctx) @@ -1191,20 +1214,63 @@ func (e *Executor) initMigrationSQLMode(ctx context.Context, onlineDDL *schema.O return deferFunc, nil } -// initConnectionLockWaitTimeout sets the given lock_wait_timeout for the given connection, with a deferred value restoration function -func (e *Executor) initConnectionLockWaitTimeout(ctx context.Context, conn *connpool.Conn, lockWaitTimeout time.Duration) (deferFunc func(), err error) { +// initConnectionSessionTimeout saves the current value of the given session variable, sets it to the given duration, +// and returns a deferred restore function. +func (e *Executor) initConnectionSessionTimeout(ctx context.Context, conn *connpool.Conn, variable string, timeout time.Duration) (deferFunc func(), err error) { + deferFunc = func() {} + + saveQuery, err := sqlparser.ParseAndBind( + fmt.Sprintf("set @%s=@@session.%s", variable, variable), + ) + if err != nil { + return deferFunc, err + } + if _, err := conn.Exec(ctx, saveQuery, 0, false); err != nil { + return deferFunc, vterrors.Wrapf(err, "could not read %s", variable) + } + setQuery, err := sqlparser.ParseAndBind( + fmt.Sprintf("set @@session.%s=%%a", variable), + sqltypes.Int64BindVariable(int64(timeout.Seconds())), + ) + if err != nil { + return deferFunc, err + } + if _, err := conn.Exec(ctx, setQuery, 0, false); err != nil { + return deferFunc, err + } + restoreQuery, err := sqlparser.ParseAndBind( + fmt.Sprintf("set @@session.%s=@%s", variable, variable), + ) + if err != nil { + return deferFunc, err + } + deferFunc = func() { + restoreCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + conn.Exec(restoreCtx, restoreQuery, 0, false) + } + return deferFunc, nil +} + +// initConnectionLockWaitTimeout sets the given lock_wait_timeout for the given connection, with a deferred value restoration function. +func (e *Executor) initConnectionLockWaitTimeout(ctx context.Context, conn *connpool.Conn, timeout time.Duration) (func(), error) { + return e.initConnectionSessionTimeout(ctx, conn, "lock_wait_timeout", timeout) +} + +// initDBConnectionLockWaitTimeout sets the given lock_wait_timeout for the given direct connection, with a deferred value restoration function. +func (e *Executor) initDBConnectionLockWaitTimeout(conn *dbconnpool.DBConnection, lockWaitTimeout time.Duration) (deferFunc func(), err error) { deferFunc = func() {} - if _, err := conn.Exec(ctx, `set @lock_wait_timeout=@@session.lock_wait_timeout`, 0, false); err != nil { - return deferFunc, vterrors.Errorf(vtrpcpb.Code_UNKNOWN, "could not read lock_wait_timeout: %v", err) + if _, err := conn.ExecuteFetch("set @lock_wait_timeout=@@session.lock_wait_timeout", 0, false); err != nil { + return deferFunc, vterrors.Wrap(err, "could not read lock_wait_timeout") } timeoutSeconds := int64(lockWaitTimeout.Seconds()) setQuery := fmt.Sprintf("set @@session.lock_wait_timeout=%d", timeoutSeconds) - if _, err := conn.Exec(ctx, setQuery, 0, false); err != nil { + if _, err := conn.ExecuteFetch(setQuery, 0, false); err != nil { return deferFunc, err } deferFunc = func() { - conn.Exec(ctx, "set @@session.lock_wait_timeout=@lock_wait_timeout", 0, false) + conn.ExecuteFetch("set @@session.lock_wait_timeout=@lock_wait_timeout", 0, false) } return deferFunc, nil } @@ -1463,7 +1529,6 @@ func (e *Executor) ExecuteWithVReplication(ctx context.Context, onlineDDL *schem } func (e *Executor) readMigration(ctx context.Context, uuid string) (onlineDDL *schema.OnlineDDL, row sqltypes.RowNamedValues, err error) { - query, err := sqlparser.ParseAndBind(sqlSelectMigration, sqltypes.StringBindVariable(uuid), ) @@ -2100,7 +2165,6 @@ func (e *Executor) executeRevert(ctx context.Context, onlineDDL *schema.OnlineDD // - empty, in which case the migration is noop and implicitly successful, or // - non-empty, in which case the migration turns to be an ALTER func (e *Executor) evaluateDeclarativeDiff(ctx context.Context, onlineDDL *schema.OnlineDDL) (diff schemadiff.EntityDiff, err error) { - // Modify the CREATE TABLE statement to indicate a different, made up table name, known as the "comparison table" ddlStmt, _, err := schema.ParseOnlineDDLStatement(onlineDDL.SQL, e.env.Environment().Parser()) if err != nil { @@ -3694,7 +3758,8 @@ func (e *Executor) updateSchemaAnalysis(ctx context.Context, uuid string, addedUniqueKeys, removedUniqueKeys int, removedUniqueKeyNames string, removedForeignKeyNames string, droppedNoDefaultColumnNames string, expandedColumnNames string, - revertibleNotes []string) error { + revertibleNotes []string, +) error { notes := strings.Join(revertibleNotes, "\n") query, err := sqlparser.ParseAndBind(sqlUpdateSchemaAnalysis, sqltypes.Int64BindVariable(int64(addedUniqueKeys)), @@ -4417,7 +4482,6 @@ func (e *Executor) SubmitMigration( ) if err != nil { return nil, vterrors.Wrapf(err, "submitting migration %v", onlineDDL.UUID) - } log.Infof("SubmitMigration: migration %s submitted", onlineDDL.UUID) @@ -4486,7 +4550,8 @@ func (e *Executor) ShowMigrationLogs(ctx context.Context, stmt *sqlparser.ShowMi // onSchemaMigrationStatus is called when a status is set/changed for a running migration func (e *Executor) onSchemaMigrationStatus(ctx context.Context, - uuid string, status schema.OnlineDDLStatus, dryRun bool, progressPct float64, etaSeconds int64, rowsCopied int64, hint string) (err error) { + uuid string, status schema.OnlineDDLStatus, dryRun bool, progressPct float64, etaSeconds int64, rowsCopied int64, hint string, +) (err error) { if dryRun && status != schema.OnlineDDLStatusFailed { // We don't consider dry-run reports unless there's a failure return nil diff --git a/go/vt/vttablet/tabletconntest/fakequeryservice.go b/go/vt/vttablet/tabletconntest/fakequeryservice.go index e63cd028d05..faa4f59b96e 100644 --- a/go/vt/vttablet/tabletconntest/fakequeryservice.go +++ b/go/vt/vttablet/tabletconntest/fakequeryservice.go @@ -459,6 +459,16 @@ var StreamExecuteQueryResult1 = sqltypes.Result{ // StreamExecuteQueryResult2 is the second packet of a streaming result. var StreamExecuteQueryResult2 = sqltypes.Result{ + Fields: []*querypb.Field{ + { + Name: "field1", + Type: sqltypes.Int8, + }, + { + Name: "field2", + Type: sqltypes.Char, + }, + }, Rows: [][]sqltypes.Value{ { sqltypes.TestValue(sqltypes.Int8, "1"), diff --git a/go/vt/vttablet/tabletmanager/framework_test.go b/go/vt/vttablet/tabletmanager/framework_test.go index 8e03f73bf79..70bfa3c50af 100644 --- a/go/vt/vttablet/tabletmanager/framework_test.go +++ b/go/vt/vttablet/tabletmanager/framework_test.go @@ -23,6 +23,7 @@ import ( "strconv" "strings" "sync" + "sync/atomic" "testing" "github.com/stretchr/testify/require" @@ -59,6 +60,8 @@ const ( gtidPosition = "16b1039f-22b6-11ed-b765-0a43f95f28a3:1-220" ) +var testEnvCounter atomic.Int64 + func init() { tabletconn.RegisterDialer("grpc", func(ctx context.Context, tablet *topodatapb.Tablet, failFast grpcclient.FailFast) (queryservice.QueryService, error) { return &tabletconntest.FakeQueryService{ @@ -90,12 +93,13 @@ type testEnv struct { func newTestEnv(t *testing.T, ctx context.Context, sourceKeyspace string, sourceShards []string) *testEnv { vttablet.InitVReplicationConfigDefaults() + protoName := fmt.Sprintf("%s_%d", t.Name(), testEnvCounter.Add(1)) tenv := &testEnv{ ctx: context.Background(), tmc: newFakeTMClient(), cells: []string{"zone1"}, dbName: "tmtestdb", - protoName: t.Name(), + protoName: protoName, } tenv.mu.Lock() defer tenv.mu.Unlock() @@ -104,7 +108,7 @@ func newTestEnv(t *testing.T, ctx context.Context, sourceKeyspace string, source tenv.tmc.sourceShards = sourceShards tenv.tmc.schema = defaultSchema - tabletconn.RegisterDialer(t.Name(), func(ctx context.Context, tablet *topodatapb.Tablet, failFast grpcclient.FailFast) (queryservice.QueryService, error) { + tabletconn.RegisterDialer(protoName, func(ctx context.Context, tablet *topodatapb.Tablet, failFast grpcclient.FailFast) (queryservice.QueryService, error) { tenv.mu.Lock() defer tenv.mu.Unlock() if qs, ok := tenv.tmc.tablets[int(tablet.Alias.Uid)]; ok { @@ -112,11 +116,11 @@ func newTestEnv(t *testing.T, ctx context.Context, sourceKeyspace string, source } return nil, fmt.Errorf("tablet %d not found", tablet.Alias.Uid) }) - tabletconntest.SetProtocol(fmt.Sprintf("go.vt.vttablet.tabletmanager.framework_test_%s", t.Name()), tenv.protoName) - tmclient.RegisterTabletManagerClientFactory(t.Name(), func() tmclient.TabletManagerClient { + tabletconntest.SetProtocol("go.vt.vttablet.tabletmanager.framework_test_"+protoName, protoName) + tmclient.RegisterTabletManagerClientFactory(protoName, func() tmclient.TabletManagerClient { return tenv.tmc }) - tmclienttest.SetProtocol(fmt.Sprintf("go.vt.vttablet.tabletmanager.framework_test_%s", t.Name()), tenv.protoName) + tmclienttest.SetProtocol("go.vt.vttablet.tabletmanager.framework_test_"+protoName, protoName) tenv.db = fakesqldb.New(t) tenv.mysqld = mysqlctl.NewFakeMysqlDaemon(tenv.db) diff --git a/go/vt/vttablet/tabletmanager/restore.go b/go/vt/vttablet/tabletmanager/restore.go index 54813e11bf3..05c29d19d0a 100644 --- a/go/vt/vttablet/tabletmanager/restore.go +++ b/go/vt/vttablet/tabletmanager/restore.go @@ -333,7 +333,7 @@ func (tm *TabletManager) disableReplication(ctx context.Context) error { return vterrors.Wrap(err, "failed to reset replication") } - if err := tm.MysqlDaemon.SetReplicationSource(ctx, "//", 0, 0, false, true); err != nil { + if err := tm.setReplicationSourceRecoverable(ctx, "//", 0, 0, false, true); err != nil { return vterrors.Wrap(err, "failed to disable replication") } diff --git a/go/vt/vttablet/tabletmanager/rpc_agent.go b/go/vt/vttablet/tabletmanager/rpc_agent.go index e779cfa8ff5..e055043ef4f 100644 --- a/go/vt/vttablet/tabletmanager/rpc_agent.go +++ b/go/vt/vttablet/tabletmanager/rpc_agent.go @@ -144,7 +144,7 @@ type RPCTM interface { InitReplica(ctx context.Context, parent *topodatapb.TabletAlias, replicationPosition string, timeCreatedNS int64, semiSync bool) error - DemotePrimary(ctx context.Context) (*replicationdatapb.PrimaryStatus, error) + DemotePrimary(ctx context.Context, force bool) (*replicationdatapb.PrimaryStatus, error) UndoDemotePrimary(ctx context.Context, semiSync bool) error diff --git a/go/vt/vttablet/tabletmanager/rpc_query.go b/go/vt/vttablet/tabletmanager/rpc_query.go index b0da7d9d71f..aa4fa1f130b 100644 --- a/go/vt/vttablet/tabletmanager/rpc_query.go +++ b/go/vt/vttablet/tabletmanager/rpc_query.go @@ -277,6 +277,9 @@ func (tm *TabletManager) ExecuteFetchAsApp(ctx context.Context, req *tabletmanag // MysqlHostMetrics gets system metrics from mysqlctl[d] func (tm *TabletManager) MysqlHostMetrics(ctx context.Context, req *tabletmanagerdatapb.MysqlHostMetricsRequest) (*tabletmanagerdatapb.MysqlHostMetricsResponse, error) { + if tm.Cnf == nil { + return &tabletmanagerdatapb.MysqlHostMetricsResponse{}, nil + } mysqlResp, err := tm.MysqlDaemon.HostMetrics(ctx, tm.Cnf) if err != nil { return nil, err diff --git a/go/vt/vttablet/tabletmanager/rpc_query_test.go b/go/vt/vttablet/tabletmanager/rpc_query_test.go index e30f63b362b..f7d11fa5a12 100644 --- a/go/vt/vttablet/tabletmanager/rpc_query_test.go +++ b/go/vt/vttablet/tabletmanager/rpc_query_test.go @@ -114,6 +114,20 @@ func TestAnalyzeExecuteFetchAsDbaMultiQuery(t *testing.T) { } } +func TestTabletManager_MysqlHostMetricsNilCnf(t *testing.T) { + ctx := context.Background() + // When using external MySQL (e.g. Cloud SQL, RDS), Cnf is nil because + // vttablet skips loading my.cnf when connection parameters are specified. + // MysqlHostMetrics should return an empty response instead of panicking. + tm := &TabletManager{ + Cnf: nil, + } + resp, err := tm.MysqlHostMetrics(ctx, &tabletmanagerdatapb.MysqlHostMetricsRequest{}) + require.NoError(t, err) + require.NotNil(t, resp) + assert.Nil(t, resp.HostMetrics) +} + func TestTabletManager_ExecuteFetchAsDba(t *testing.T) { ctx := context.Background() cp := mysql.ConnParams{} diff --git a/go/vt/vttablet/tabletmanager/rpc_replication.go b/go/vt/vttablet/tabletmanager/rpc_replication.go index 67a252c3290..1303d3f40c7 100644 --- a/go/vt/vttablet/tabletmanager/rpc_replication.go +++ b/go/vt/vttablet/tabletmanager/rpc_replication.go @@ -20,7 +20,6 @@ import ( "context" "fmt" "runtime" - "strings" "time" "vitess.io/vitess/go/mysql" @@ -306,7 +305,7 @@ func (tm *TabletManager) StartReplication(ctx context.Context, semiSync bool) er if err := tm.fixSemiSync(ctx, tm.Tablet().Type, semiSyncAction); err != nil { return err } - return tm.MysqlDaemon.StartReplication(ctx, tm.hookExtraEnv()) + return tm.startReplicationRecoverable(ctx) } // StartReplicationUntilAfter will start the replication and let it catch up @@ -496,7 +495,8 @@ func (tm *TabletManager) InitReplica(ctx context.Context, parent *topodatapb.Tab if err := tm.MysqlDaemon.SetReplicationPosition(ctx, pos); err != nil { return err } - if err := tm.MysqlDaemon.SetReplicationSource(ctx, ti.Tablet.MysqlHostname, ti.Tablet.MysqlPort, 0, false, true); err != nil { + + if err := tm.setReplicationSourceRecoverable(ctx, ti.Tablet.MysqlHostname, ti.Tablet.MysqlPort, 0, false, true); err != nil { return err } @@ -519,20 +519,20 @@ func (tm *TabletManager) InitReplica(ctx context.Context, parent *topodatapb.Tab // or on a tablet that already transitioned to REPLICA. // // If a step fails in the middle, it will try to undo any changes it made. -func (tm *TabletManager) DemotePrimary(ctx context.Context) (*replicationdatapb.PrimaryStatus, error) { +func (tm *TabletManager) DemotePrimary(ctx context.Context, force bool) (*replicationdatapb.PrimaryStatus, error) { log.Infof("DemotePrimary") if err := tm.waitForGrantsToHaveApplied(ctx); err != nil { return nil, err } // The public version always reverts on partial failure. - return tm.demotePrimary(ctx, true /* revertPartialFailure */) + return tm.demotePrimary(ctx, true /* revertPartialFailure */, force) } // demotePrimary implements DemotePrimary with an additional, private option. // // If revertPartialFailure is true, and a step fails in the middle, it will try // to undo any changes it made. -func (tm *TabletManager) demotePrimary(ctx context.Context, revertPartialFailure bool) (primaryStatus *replicationdatapb.PrimaryStatus, finalErr error) { +func (tm *TabletManager) demotePrimary(ctx context.Context, revertPartialFailure bool, force bool) (primaryStatus *replicationdatapb.PrimaryStatus, finalErr error) { if err := tm.lock(ctx); err != nil { return nil, err } @@ -594,13 +594,66 @@ func (tm *TabletManager) demotePrimary(ctx context.Context, revertPartialFailure }() } - // Now we know no writes are in-flight and no new writes can occur. - // We just need to wait for no write being blocked on semi-sync ACKs. - err = tm.SemiSyncMonitor.WaitUntilSemiSyncUnblocked(ctx) + isSemiSyncBlocked, err := tm.MysqlDaemon.IsSemiSyncBlocked(ctx) if err != nil { return nil, err } + // `force` is true when `DemotePrimary` is called for `EmergencyReparentShard` or when a primary notices + // that a different tablet has been promoted to primary and demotes itself. + // + // In both cases, the reason for semi sync being blocked is very likely that there's no replica + // connected that can send semi-sync ACKs, so we need to disable semi-sync to enable read-only mode. + // And in either of these cases, it's almost guaranteed that no semi-sync enabled replica will connect + // to this tablet again. + // + // The only way for us to finish the demotion in this scenario is to disable semi-sync - otherwise + // enabling ``super_read_only` will end up waiting indefinitely for in-flight transactions + // to complete, which won't happen as they are waiting for semi-sync ACKs. + // + // By disabling semi-sync, we allow the blocking in-flight transactions to complete. Note that at this point, + // the query service is already disabled, so the original sessions that issued those writes + // will never have seen their transactions commit - they will already have received an error. + // + // The demoted primary will end up with errant GTIDs, but that's unavoidable in this scenario. + if force && isSemiSyncBlocked { + if tm.isPrimarySideSemiSyncEnabled(ctx) { + // Disable the primary side semi-sync to unblock the writes. + if err := tm.fixSemiSync(ctx, topodatapb.TabletType_REPLICA, SemiSyncActionSet); err != nil { + return nil, err + } + defer func() { + if finalErr != nil && revertPartialFailure && wasPrimary { + // enable primary-side semi-sync again + if err := tm.fixSemiSync(ctx, topodatapb.TabletType_PRIMARY, SemiSyncActionSet); err != nil { + log.Warningf("fixSemiSync(PRIMARY) failed during revert: %v", err) + } + } + }() + } + } else { + // If `force` is false, we're demoting this primary as part of a `PlannedReparentShard` operation, + // but we might be blocked on semi-sync ACKs. + // + // If there's any in-flight transactions waiting for semi-sync ACKs, + // we won't be able to change the MySQL `super_read_only` because turning on + // read only mode requires all in-flight transactions to complete. + // + // So we're doing a last-ditch effort here trying to wait for in-flight transactions to complete. + // This will only be successful if at least one semi-sync enabled replica connects back to this primary + // and a new transaction commit unblocks the semi-sync wait. + // + // The scenario where this could happen is some sort of network hiccup during a + // `PlannedReparentShard` call, where the primary temporarily loses connectivity to + // all semi-sync enabled replicas. + // + // If we can't unblock within the context timeout, the `PlannedReparentShard` operation will fail. + err = tm.SemiSyncMonitor.WaitUntilSemiSyncUnblocked(ctx) + if err != nil { + return nil, err + } + } + // We can now set MySQL to super_read_only mode. If we are already super_read_only because of a // previous demotion, or because we are not primary anyway, this should be // idempotent. @@ -622,8 +675,7 @@ func (tm *TabletManager) demotePrimary(ctx context.Context, revertPartialFailure } }() - // Here, we check if the primary side semi sync is enabled or not. If it isn't enabled then we do not need to take any action. - // If it is enabled then we should turn it off and revert in case of failure. + // If we haven't disabled the primary side semi-sync so far, do it now. if tm.isPrimarySideSemiSyncEnabled(ctx) { // If using semi-sync, we need to disable primary-side. if err := tm.fixSemiSync(ctx, topodatapb.TabletType_REPLICA, SemiSyncActionSet); err != nil { @@ -869,23 +921,19 @@ func (tm *TabletManager) setReplicationSourceLocked(ctx context.Context, parentA } if status.SourceHost != host || status.SourcePort != port || heartbeatInterval != 0 { // This handles both changing the address and starting replication. - if err := tm.MysqlDaemon.SetReplicationSource(ctx, host, port, heartbeatInterval, wasReplicating, shouldbeReplicating); err != nil { - if err := tm.handleRelayLogError(ctx, err); err != nil { - return err - } + if err := tm.setReplicationSourceRecoverable(ctx, host, port, heartbeatInterval, wasReplicating, shouldbeReplicating); err != nil { + return err } } else if shouldbeReplicating { // The address is correct. We need to restart replication so that any semi-sync changes if any - // are taken into account + // are taken into account. We don't attempt to recover from the known recoverable errors here + // because recovery requires running `STOP REPLICA` in order to reset the replication metadata. + // If we error the first time, we're likely to error the second time as well. if err := tm.MysqlDaemon.StopReplication(ctx, tm.hookExtraEnv()); err != nil { - if err := tm.handleRelayLogError(ctx, err); err != nil { - return err - } + return err } - if err := tm.MysqlDaemon.StartReplication(ctx, tm.hookExtraEnv()); err != nil { - if err := tm.handleRelayLogError(ctx, err); err != nil { - return err - } + if err := tm.startReplicationRecoverable(ctx); err != nil { + return err } } @@ -1147,25 +1195,113 @@ func (tm *TabletManager) fixSemiSyncAndReplication(ctx context.Context, tabletTy if err := tm.MysqlDaemon.StopReplication(ctx, tm.hookExtraEnv()); err != nil { return vterrors.Wrap(err, "failed to StopReplication") } - if err := tm.MysqlDaemon.StartReplication(ctx, tm.hookExtraEnv()); err != nil { + if err := tm.startReplicationRecoverable(ctx); err != nil { return vterrors.Wrap(err, "failed to StartReplication") } return nil } -// handleRelayLogError resets replication of the instance. -// This is required because sometimes MySQL gets stuck due to improper initialization of -// master info structure or related failures and throws errors like -// ERROR 1201 (HY000): Could not initialize master info structure; more error messages can be found in the MySQL error log -// These errors can only be resolved by resetting the replication, otherwise START REPLICA fails. -func (tm *TabletManager) handleRelayLogError(ctx context.Context, err error) error { - // attempt to fix this error: - // Replica failed to initialize relay log info structure from the repository (errno 1872) (sqlstate HY000) during query: START REPLICA +// startReplicationRecoverable starts replication and handles recoverable errors by resetting replication. +func (tm *TabletManager) startReplicationRecoverable(ctx context.Context) error { + err := tm.MysqlDaemon.StartReplication(ctx, tm.hookExtraEnv()) + if err == nil { + return nil + } + + // Try to recover from the error. + if err := tm.handleRecoverableReplicationInitError(ctx, err); err != nil { + return err + } + + return nil +} + +// setReplicationSourceRecoverable configures the requested replication source and optionally starts +// replication afterward. When possible, certain errors are recovered by reinitializing replication +// metadata. +func (tm *TabletManager) setReplicationSourceRecoverable(ctx context.Context, host string, port int32, heartbeatInterval float64, wasReplicating bool, shouldStartReplication bool) error { + // Let's first try to apply the requested source without starting replication afterwards. If the + // replica was replicating before, we stop replication first. + err := tm.MysqlDaemon.SetReplicationSource(ctx, host, port, heartbeatInterval, wasReplicating, false) + if err == nil { + // We succeeded, let's start replication but only if it was requested. + if !shouldStartReplication { + return nil + } + + return tm.startReplicationRecoverable(ctx) + } + + // We hit an error. If the error is not one of the recoverable ones, we can't recover and should return it. + if !isRecoverableReplicationInitializationError(err) { + return err + } + + log.Warningf( + "Encountered recoverable replication initialization error while changing replication source, resetting "+ + "replication parameters and reapplying source: source_host=%s, source_port=%d, error=%v", + host, port, err, + ) + + // If the replica was running when the source-change attempt failed, stop it + // explicitly before resetting replication metadata. + if wasReplicating { + if err := tm.MysqlDaemon.StopReplication(ctx, tm.hookExtraEnv()); err != nil { + return err + } + } + + // Recover from the error by reinitializing replication metadata through + // `RESET REPLICA ALL`. + if err := tm.MysqlDaemon.ResetReplicationParameters(ctx); err != nil { + return err + } + + // Now that we've reinitialized the replication metadata, try setting the source again. + if err := tm.MysqlDaemon.SetReplicationSource(ctx, host, port, heartbeatInterval, false, false); err != nil { + return err + } + + // The replication source has finally been set. Let's also start replication if it was requested. + if shouldStartReplication { + return tm.startReplicationRecoverable(ctx) + } + + return nil +} + +// recoverableReplicationInitializationErrorCodes is the set of replication initialization error +// codes that can be recovered from by reinitializing replication metadata. +// MySQL used 1871/1872 for master-info and relay-log-info initialization errors +// through 8.0.32, and reassigned those numbers in 8.0.33 to connection-metadata +// and applier-metadata initialization errors. +var recoverableReplicationInitializationErrorCodes = map[sqlerror.ErrorCode]struct{}{ + sqlerror.ERMasterInfo: {}, + sqlerror.ERReplicaConnectionMetadataInitRepository: {}, + sqlerror.ERReplicaApplierMetadataInitRepository: {}, +} + +// isRecoverableReplicationInitializationError reports whether an error can be recovered from by +// reinitializing replication metadata. +func isRecoverableReplicationInitializationError(err error) bool { + sqlErr, ok := sqlerror.NewSQLErrorFromError(err).(*sqlerror.SQLError) + if !ok || sqlErr == nil { + return false + } + + _, ok = recoverableReplicationInitializationErrorCodes[sqlErr.Number()] + return ok +} + +// handleRecoverableReplicationInitError repairs recoverable replication initialization +// failures by restarting replication. +func (tm *TabletManager) handleRecoverableReplicationInitError(ctx context.Context, err error) error { + // Attempt to self-heal by restarting replication when initialization fails. // see https://bugs.mysql.com/bug.php?id=83713 or https://github.com/vitessio/vitess/issues/5067 // The same fix also works for https://github.com/vitessio/vitess/issues/10955. - if strings.Contains(err.Error(), "Replica failed to initialize relay log info structure from the repository") || - strings.Contains(err.Error(), "Could not initialize master info structure") { - // Stop, reset and start replication again to resolve this error + if isRecoverableReplicationInitializationError(err) { + log.Warningf("Encountered recoverable replication initialization error, restarting replication: %v", err) + if err := tm.MysqlDaemon.RestartReplication(ctx, tm.hookExtraEnv()); err != nil { return err } diff --git a/go/vt/vttablet/tabletmanager/rpc_replication_test.go b/go/vt/vttablet/tabletmanager/rpc_replication_test.go index 7ba8fc6729c..1bbc5e74290 100644 --- a/go/vt/vttablet/tabletmanager/rpc_replication_test.go +++ b/go/vt/vttablet/tabletmanager/rpc_replication_test.go @@ -18,6 +18,8 @@ package tabletmanager import ( "context" + "errors" + "fmt" "sync/atomic" "testing" "time" @@ -25,6 +27,7 @@ import ( "github.com/stretchr/testify/require" "golang.org/x/sync/semaphore" + "vitess.io/vitess/go/mysql/sqlerror" "vitess.io/vitess/go/protoutil" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/mysqlctl" @@ -36,6 +39,28 @@ import ( topodatapb "vitess.io/vitess/go/vt/proto/topodata" ) +func newTestReplicationTM(tablet *topodatapb.Tablet, mysqlDaemon *mysqlctl.FakeMysqlDaemon, ts *topo.Server) *TabletManager { + waitForGrantsComplete := make(chan struct{}) + close(waitForGrantsComplete) + + return &TabletManager{ + actionSema: semaphore.NewWeighted(1), + TopoServer: ts, + MysqlDaemon: mysqlDaemon, + tabletAlias: tablet.Alias, + _waitForGrantsComplete: waitForGrantsComplete, + tmState: &tmState{ + displayState: displayState{ + tablet: tablet, + }, + }, + } +} + +func recoverableReplicationInitError() error { + return sqlerror.NewSQLError(sqlerror.ERMasterInfo, sqlerror.SSUnknownSQLState, "Could not initialize master info structure; more error messages can be found in the MySQL error log") +} + // TestWaitForGrantsToHaveApplied tests that waitForGrantsToHaveApplied only succeeds after waitForDBAGrants has been called. func TestWaitForGrantsToHaveApplied(t *testing.T) { tm := &TabletManager{ @@ -98,7 +123,7 @@ func TestDemotePrimaryStalled(t *testing.T) { } go func() { - tm.demotePrimary(context.Background(), false) + tm.demotePrimary(context.Background(), false /* revertPartialFailure */, false /* force */) }() // We make IsServing stall by making it wait on a channel. // This should cause the demote primary operation to be stalled. @@ -149,7 +174,7 @@ func TestDemotePrimaryWaitingForSemiSyncUnblock(t *testing.T) { // Start the demote primary operation in a go routine. var demotePrimaryFinished atomic.Bool go func() { - _, err := tm.demotePrimary(ctx, false) + _, err := tm.demotePrimary(ctx, false /* revertPartialFailure */, false /* force */) require.NoError(t, err) demotePrimaryFinished.Store(true) }() @@ -220,7 +245,7 @@ func TestDemotePrimaryWithSemiSyncProgressDetection(t *testing.T) { // Start the demote primary operation in a go routine. var demotePrimaryFinished atomic.Bool go func() { - _, err := tm.demotePrimary(ctx, false) + _, err := tm.demotePrimary(ctx, false /* revertPartialFailure */, false /* force */) require.NoError(t, err) demotePrimaryFinished.Store(true) }() @@ -278,7 +303,7 @@ func TestDemotePrimaryWhenSemiSyncBecomesUnblockedBetweenChecks(t *testing.T) { // Start the demote primary operation in a go routine. var demotePrimaryFinished atomic.Bool go func() { - _, err := tm.demotePrimary(ctx, false) + _, err := tm.demotePrimary(ctx, false /* revertPartialFailure */, false /* force */) require.NoError(t, err) demotePrimaryFinished.Store(true) }() @@ -326,3 +351,354 @@ func TestUndoDemotePrimaryStateChange(t *testing.T) { require.NoError(t, err) require.False(t, isReadOnly) } + +func TestHandleRecoverableReplicationInitializationError(t *testing.T) { + testCases := []struct { + name string + inputErr error + shouldRestart bool + }{ + { + name: "relay log info repository error", + inputErr: sqlerror.NewSQLError(sqlerror.ERReplicaRelayLogInfoInitRepository, sqlerror.SSUnknownSQLState, "Replica failed to initialize relay log info structure from the repository"), + shouldRestart: true, + }, + { + name: "master info error", + inputErr: sqlerror.NewSQLError(sqlerror.ERMasterInfo, sqlerror.SSUnknownSQLState, "Could not initialize master info structure; more error messages can be found in the MySQL error log"), + shouldRestart: true, + }, + { + name: "connection metadata repository error", + inputErr: sqlerror.NewSQLError(sqlerror.ERReplicaConnectionMetadataInitRepository, sqlerror.SSUnknownSQLState, "Replica failed to initialize connection metadata structure from the repository"), + shouldRestart: true, + }, + { + name: "applier metadata message with wrong errno", + inputErr: sqlerror.NewSQLError(sqlerror.ERUnknownError, sqlerror.SSUnknownSQLState, "Replica failed to initialize applier metadata structure from the repository"), + shouldRestart: false, + }, + { + name: "mysqlctl wrapped master info error", + inputErr: errors.New("ExecuteFetch(START REPLICA) failed: Could not initialize master info structure; more error messages can be found in the MySQL error log (errno 1201) (sqlstate HY000)"), + shouldRestart: true, + }, + { + name: "native mysql master info error", + inputErr: errors.New("ERROR 1201 (HY000): Could not initialize master info structure; more error messages can be found in the MySQL error log"), + shouldRestart: true, + }, + { + name: "unrelated error", + inputErr: errors.New("unexpected replication failure"), + shouldRestart: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + fakeMysqlDaemon := newTestMysqlDaemon(t, 1) + if tc.shouldRestart { + fakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ + "STOP REPLICA", + "RESET REPLICA", + "START REPLICA", + } + } + + tablet := newTestTablet(t, 100, "ks", "0", nil) + tm := &TabletManager{ + MysqlDaemon: fakeMysqlDaemon, + tabletAlias: tablet.Alias, + tmState: &tmState{ + displayState: displayState{ + tablet: tablet, + }, + }, + } + + err := tm.handleRecoverableReplicationInitError(t.Context(), tc.inputErr) + if tc.shouldRestart { + require.NoError(t, err) + } else { + require.ErrorIs(t, err, tc.inputErr) + } + + require.NoError(t, fakeMysqlDaemon.CheckSuperQueryList()) + }) + } +} + +// TestStartReplicationRecoversFromRecoverableReplicationInitError verifies StartReplication self-heals recoverable init failures. +func TestStartReplicationRecoversFromRecoverableReplicationInitError(t *testing.T) { + fakeMysqlDaemon := newTestMysqlDaemon(t, 1) + fakeMysqlDaemon.StartReplicationError = recoverableReplicationInitError() + fakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ + "STOP REPLICA", + "RESET REPLICA", + "START REPLICA", + } + + tm := newTestReplicationTM(newTestTablet(t, 100, "ks", "0", nil), fakeMysqlDaemon, nil) + err := tm.StartReplication(t.Context(), false) + require.NoError(t, err) + require.NoError(t, fakeMysqlDaemon.CheckSuperQueryList()) +} + +// TestFixSemiSyncAndReplicationRecoversFromRecoverableReplicationInitializationError verifies semi-sync restart path self-heals recoverable init failures. +func TestFixSemiSyncAndReplicationRecoversFromRecoverableReplicationInitializationError(t *testing.T) { + fakeMysqlDaemon := newTestMysqlDaemon(t, 1) + fakeMysqlDaemon.Replicating = true + fakeMysqlDaemon.StartReplicationError = recoverableReplicationInitError() + fakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ + "STOP REPLICA", + "STOP REPLICA", + "RESET REPLICA", + "START REPLICA", + } + + tm := newTestReplicationTM(newTestTablet(t, 100, "ks", "0", nil), fakeMysqlDaemon, nil) + err := tm.fixSemiSyncAndReplication(t.Context(), topodatapb.TabletType_REPLICA, SemiSyncActionUnset) + require.NoError(t, err) + require.NoError(t, fakeMysqlDaemon.CheckSuperQueryList()) +} + +func TestSetReplicationSourceRecovery(t *testing.T) { + t.Run("InitReplica recovers from start replication error", func(t *testing.T) { + ctx := t.Context() + ts := memorytopo.NewServer(ctx, "cell1") + + // Create a shard with a primary that InitReplica will point to. + _, err := ts.GetOrCreateShard(ctx, "ks", "0") + require.NoError(t, err) + + parent := &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "cell1", + Uid: 200, + }, + Keyspace: "ks", + Shard: "0", + Type: topodatapb.TabletType_PRIMARY, + MysqlHostname: "mysql-primary", + MysqlPort: 3306, + } + require.NoError(t, ts.CreateTablet(ctx, parent)) + + fakeMysqlDaemon := newTestMysqlDaemon(t, 1) + + // Let the source change succeed, then fail the explicit START REPLICA so + // the recovery path is exercised after the source is already configured. + fakeMysqlDaemon.SetReplicationSourceInputs = []string{"mysql-primary:3306"} + fakeMysqlDaemon.StartReplicationError = recoverableReplicationInitError() + fakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ + "FAKE RESET BINARY LOGS AND GTIDS", + "FAKE SET GLOBAL gtid_purged", + "FAKE SET SOURCE", + "STOP REPLICA", + "RESET REPLICA", + "START REPLICA", + } + + tm := newTestReplicationTM(newTestTablet(t, 100, "ks", "0", nil), fakeMysqlDaemon, ts) + + // InitReplica should recover the start failure and still complete. + err = tm.InitReplica(ctx, parent.Alias, "", 0, false) + require.NoError(t, err) + require.Equal(t, "mysql-primary", fakeMysqlDaemon.CurrentSourceHost) + require.EqualValues(t, 3306, fakeMysqlDaemon.CurrentSourcePort) + require.NoError(t, fakeMysqlDaemon.CheckSuperQueryList()) + }) + + t.Run("SetReplicationSource recovers on source change for running replica", func(t *testing.T) { + ctx := t.Context() + ts := memorytopo.NewServer(ctx, "cell1") + + tablet := newTestTablet(t, 100, "ks", "0", nil) + fakeMysqlDaemon := newTestMysqlDaemon(t, 1) + + // Start from a running replica that still points at the old primary. + fakeMysqlDaemon.Replicating = true + fakeMysqlDaemon.CurrentSourceHost = "mysql-old-primary" + fakeMysqlDaemon.CurrentSourcePort = 3305 + fakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ + "STOP REPLICA", + "STOP REPLICA", + "FAKE RESET REPLICA ALL", + "FAKE SET SOURCE", + "START REPLICA", + } + + setSourceCalls := 0 + + // Fail the first source-change attempt after the internal STOP REPLICA. + // The second attempt should succeed after recovery has cleared the broken + // metadata and reapplied the requested source. + fakeMysqlDaemon.SetReplicationSourceFunc = func(ctx context.Context, host string, port int32, heartbeatInterval float64, stopReplicationBefore bool, startReplicationAfter bool) error { + setSourceCalls++ + + require.Equal(t, "mysql-new-primary", host) + require.EqualValues(t, 3306, port) + require.Zero(t, heartbeatInterval) + require.False(t, startReplicationAfter) + + if setSourceCalls == 1 { + require.True(t, stopReplicationBefore) + require.NoError(t, fakeMysqlDaemon.ExecuteSuperQueryList(ctx, []string{"STOP REPLICA"})) + return recoverableReplicationInitError() + } + + if setSourceCalls == 2 { + require.False(t, stopReplicationBefore) + require.NoError(t, fakeMysqlDaemon.ExecuteSuperQueryList(ctx, []string{"FAKE SET SOURCE"})) + + fakeMysqlDaemon.CurrentSourceHost = host + fakeMysqlDaemon.CurrentSourcePort = port + + return nil + } + + return fmt.Errorf("unexpected SetReplicationSource call %d", setSourceCalls) + } + + tm := &TabletManager{ + actionSema: semaphore.NewWeighted(1), + BatchCtx: ctx, + TopoServer: ts, + MysqlDaemon: fakeMysqlDaemon, + tmc: newFakeTMClient(), + tabletAlias: tablet.Alias, + _waitForGrantsComplete: make(chan struct{}), + tmState: &tmState{ + displayState: displayState{ + tablet: tablet, + }, + }, + } + close(tm._waitForGrantsComplete) + + // Register both the replica and the new primary in topo. + _, err := ts.GetOrCreateShard(ctx, "ks", "0") + require.NoError(t, err) + require.NoError(t, ts.CreateTablet(ctx, tablet)) + + parent := &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "cell1", + Uid: 200, + }, + Keyspace: "ks", + Shard: "0", + Type: topodatapb.TabletType_PRIMARY, + MysqlHostname: "mysql-new-primary", + MysqlPort: 3306, + } + require.NoError(t, ts.CreateTablet(ctx, parent)) + + // SetReplicationSource should recover the source-change error, then + // leave the replica configured for the new primary. + err = tm.SetReplicationSource(ctx, parent.Alias, 0, "", false, false, 0) + require.NoError(t, err) + + require.Equal(t, 2, setSourceCalls) + require.Equal(t, "mysql-new-primary", fakeMysqlDaemon.CurrentSourceHost) + require.EqualValues(t, 3306, fakeMysqlDaemon.CurrentSourcePort) + require.NoError(t, fakeMysqlDaemon.CheckSuperQueryList()) + }) + + t.Run("non-running replica reapplies source after recoverable source error", func(t *testing.T) { + fakeMysqlDaemon := newTestMysqlDaemon(t, 1) + fakeMysqlDaemon.CurrentSourceHost = "mysql-old-primary" + fakeMysqlDaemon.CurrentSourcePort = 3305 + fakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ + "FAKE RESET REPLICA ALL", + "FAKE SET SOURCE", + } + + setSourceCalls := 0 + + // When replication was not running, recovery should clear any stale source + // settings and reapply the requested source without starting replication. + fakeMysqlDaemon.SetReplicationSourceFunc = func(ctx context.Context, host string, port int32, heartbeatInterval float64, stopReplicationBefore bool, startReplicationAfter bool) error { + setSourceCalls++ + + require.Equal(t, "mysql-new-primary", host) + require.EqualValues(t, 3306, port) + require.False(t, stopReplicationBefore) + require.False(t, startReplicationAfter) + + if setSourceCalls == 1 { + return recoverableReplicationInitError() + } + + if setSourceCalls == 2 { + require.NoError(t, fakeMysqlDaemon.ExecuteSuperQueryList(ctx, []string{"FAKE SET SOURCE"})) + + fakeMysqlDaemon.CurrentSourceHost = host + fakeMysqlDaemon.CurrentSourcePort = port + + return nil + } + + return fmt.Errorf("unexpected SetReplicationSource call %d", setSourceCalls) + } + + tm := newTestReplicationTM(newTestTablet(t, 100, "ks", "0", nil), fakeMysqlDaemon, nil) + + err := tm.setReplicationSourceRecoverable(t.Context(), "mysql-new-primary", 3306, 0, false, false) + require.NoError(t, err) + require.Equal(t, 2, setSourceCalls) + require.Equal(t, "mysql-new-primary", fakeMysqlDaemon.CurrentSourceHost) + require.EqualValues(t, 3306, fakeMysqlDaemon.CurrentSourcePort) + require.NoError(t, fakeMysqlDaemon.CheckSuperQueryList()) + }) + + t.Run("non-running replica with start requested reapplies source and starts replication", func(t *testing.T) { + fakeMysqlDaemon := newTestMysqlDaemon(t, 1) + fakeMysqlDaemon.CurrentSourceHost = "mysql-old-primary" + fakeMysqlDaemon.CurrentSourcePort = 3305 + fakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ + "FAKE RESET REPLICA ALL", + "FAKE SET SOURCE", + "START REPLICA", + } + + setSourceCalls := 0 + + // A source-change failure can happen before the new source is applied. + // Recovery should clear the old source settings, reapply the requested + // source, and only then start replication. + fakeMysqlDaemon.SetReplicationSourceFunc = func(ctx context.Context, host string, port int32, heartbeatInterval float64, stopReplicationBefore bool, startReplicationAfter bool) error { + setSourceCalls++ + + require.Equal(t, "mysql-new-primary", host) + require.EqualValues(t, 3306, port) + require.False(t, stopReplicationBefore) + require.False(t, startReplicationAfter) + + if setSourceCalls == 1 { + return recoverableReplicationInitError() + } + + if setSourceCalls == 2 { + require.NoError(t, fakeMysqlDaemon.ExecuteSuperQueryList(ctx, []string{"FAKE SET SOURCE"})) + + fakeMysqlDaemon.CurrentSourceHost = host + fakeMysqlDaemon.CurrentSourcePort = port + + return nil + } + + return fmt.Errorf("unexpected SetReplicationSource call %d", setSourceCalls) + } + + tm := newTestReplicationTM(newTestTablet(t, 100, "ks", "0", nil), fakeMysqlDaemon, nil) + + err := tm.setReplicationSourceRecoverable(t.Context(), "mysql-new-primary", 3306, 0, false, true) + require.NoError(t, err) + require.Equal(t, 2, setSourceCalls) + require.Equal(t, "mysql-new-primary", fakeMysqlDaemon.CurrentSourceHost) + require.EqualValues(t, 3306, fakeMysqlDaemon.CurrentSourcePort) + require.NoError(t, fakeMysqlDaemon.CheckSuperQueryList()) + }) +} diff --git a/go/vt/vttablet/tabletmanager/rpc_vreplication.go b/go/vt/vttablet/tabletmanager/rpc_vreplication.go index ad4dbe97f73..937794ef905 100644 --- a/go/vt/vttablet/tabletmanager/rpc_vreplication.go +++ b/go/vt/vttablet/tabletmanager/rpc_vreplication.go @@ -59,7 +59,7 @@ const ( // Delete VReplication records for the given workflow. sqlDeleteVReplicationWorkflow = "delete from %s.vreplication where workflow = %a and db_name = %a" // Retrieve the current configuration values for a workflow's vreplication stream(s). - sqlSelectVReplicationWorkflowConfig = "select id, source, cell, tablet_types, state, message from %s.vreplication where workflow = %a" + sqlSelectVReplicationWorkflowConfig = "select id, source, cell, tablet_types, state, message from %s.vreplication where workflow = %a and db_name = %a" // Update the configuration values for a workflow's vreplication stream. sqlUpdateVReplicationWorkflowStreamConfig = "update %s.vreplication set state = %a, source = %a, cell = %a, tablet_types = %a, message = %a %s where id = %a" // Update field values for multiple workflows. The final format specifier is @@ -524,8 +524,9 @@ func isStreamCopying(tm *TabletManager, id int64) (bool, error) { func (tm *TabletManager) UpdateVReplicationWorkflow(ctx context.Context, req *tabletmanagerdatapb.UpdateVReplicationWorkflowRequest) (*tabletmanagerdatapb.UpdateVReplicationWorkflowResponse, error) { bindVars := map[string]*querypb.BindVariable{ "wf": sqltypes.StringBindVariable(req.Workflow), + "db": sqltypes.StringBindVariable(tm.DBConfigs.DBName), } - parsed := sqlparser.BuildParsedQuery(sqlSelectVReplicationWorkflowConfig, sidecar.GetIdentifier(), ":wf") + parsed := sqlparser.BuildParsedQuery(sqlSelectVReplicationWorkflowConfig, sidecar.GetIdentifier(), ":wf", ":db") stmt, err := parsed.GenerateQuery(bindVars, nil) if err != nil { return nil, err diff --git a/go/vt/vttablet/tabletmanager/rpc_vreplication_test.go b/go/vt/vttablet/tabletmanager/rpc_vreplication_test.go index bb2ef7bfead..bc33ea29eb7 100644 --- a/go/vt/vttablet/tabletmanager/rpc_vreplication_test.go +++ b/go/vt/vttablet/tabletmanager/rpc_vreplication_test.go @@ -80,7 +80,7 @@ const ( readAllWorkflows = "select workflow, id, source, pos, stop_pos, max_tps, max_replication_lag, cell, tablet_types, time_updated, transaction_timestamp, state, message, db_name, rows_copied, tags, time_heartbeat, workflow_type, time_throttled, component_throttled, workflow_sub_type, defer_secondary_keys, options from _vt.vreplication where db_name = '%s'%s order by workflow, id" readWorkflowsLimited = "select workflow, id, source, pos, stop_pos, max_tps, max_replication_lag, cell, tablet_types, time_updated, transaction_timestamp, state, message, db_name, rows_copied, tags, time_heartbeat, workflow_type, time_throttled, component_throttled, workflow_sub_type, defer_secondary_keys, options from _vt.vreplication where db_name = '%s' and workflow in ('%s') order by workflow, id" readWorkflow = "select id, source, pos, stop_pos, max_tps, max_replication_lag, cell, tablet_types, time_updated, transaction_timestamp, state, message, db_name, rows_copied, tags, time_heartbeat, workflow_type, time_throttled, component_throttled, workflow_sub_type, defer_secondary_keys, options from _vt.vreplication where workflow = '%s' and db_name = '%s'" - readWorkflowConfig = "select id, source, cell, tablet_types, state, message from _vt.vreplication where workflow = '%s'" + readWorkflowConfig = "select id, source, cell, tablet_types, state, message from _vt.vreplication where workflow = '%s' and db_name = '%s'" updateWorkflow = "update _vt.vreplication set state = '%s', source = '%s', cell = '%s', tablet_types = '%s', message = '%s' where id in (%d)" getNonEmptyTableQuery = "select 1 from `%s` limit 1" ) @@ -438,7 +438,7 @@ func TestMoveTablesUnsharded(t *testing.T) { ), fmt.Sprintf("%d|%s|%s|NULL|0|0|||1686577659|0|Stopped||%s|1||0|0|0||0|1|{}", vreplID, bls, position, targetKs), )) - ftc.vrdbClient.ExpectRequest(fmt.Sprintf(readWorkflowConfig, wf), sqltypes.MakeTestResult( + ftc.vrdbClient.ExpectRequest(fmt.Sprintf(readWorkflowConfig, wf, tenv.dbName), sqltypes.MakeTestResult( sqltypes.MakeTestFields( "id|source|cell|tablet_types|state|message", "int64|blob|varchar|varchar|varchar|varchar", @@ -707,7 +707,7 @@ func TestMoveTablesSharded(t *testing.T) { ), fmt.Sprintf("%d|%s|%s|NULL|0|0|||1686577659|0|Stopped||%s|1||0|0|0||0|1|{}", vreplID, bls, position, targetKs), )) - ftc.vrdbClient.ExpectRequest(fmt.Sprintf(readWorkflowConfig, wf), sqltypes.MakeTestResult( + ftc.vrdbClient.ExpectRequest(fmt.Sprintf(readWorkflowConfig, wf, tenv.dbName), sqltypes.MakeTestResult( sqltypes.MakeTestFields( "id|source|cell|tablet_types|state|message", "int64|blob|varchar|varchar|varchar|varchar", @@ -890,9 +890,10 @@ func TestUpdateVReplicationWorkflow(t *testing.T) { tablet := tenv.addTablet(t, tabletUID, keyspace, shard) defer tenv.deleteTablet(tablet.tablet) - parsed := sqlparser.BuildParsedQuery(sqlSelectVReplicationWorkflowConfig, sidecar.GetIdentifier(), ":wf") + parsed := sqlparser.BuildParsedQuery(sqlSelectVReplicationWorkflowConfig, sidecar.GetIdentifier(), ":wf", ":db") bindVars := map[string]*querypb.BindVariable{ "wf": sqltypes.StringBindVariable(workflow), + "db": sqltypes.StringBindVariable(tenv.dbName), } selectQuery, err := parsed.GenerateQuery(bindVars, nil) require.NoError(t, err) @@ -1847,7 +1848,7 @@ func addInvariants(dbClient *binlogplayer.MockDBClient, vreplID, sourceTabletUID "0", )) dbClient.AddInvariant(fmt.Sprintf(updatePickedSourceTablet, cell, sourceTabletUID, vreplID), &sqltypes.Result{}) - dbClient.AddInvariant("update _vt.vreplication set state='Running', message='' where id=1", &sqltypes.Result{}) + dbClient.AddInvariant("update _vt.vreplication set state='Running', message=left('', 1000) where id=1", &sqltypes.Result{}) dbClient.AddInvariant(vreplication.SqlMaxAllowedPacket, sqltypes.MakeTestResult( sqltypes.MakeTestFields( "max_allowed_packet", @@ -2155,7 +2156,7 @@ func TestExternalizeLookupVindex(t *testing.T) { targetTablet.vrdbClient.ExpectRequest(fmt.Sprintf(readWorkflow, tcase.request.Name, tenv.dbName), tcase.vrResponse, nil) // Update queries are required only if the Vindex is owned. if tcase.expectStopped && len(tcase.expectedVschema.Vindexes) > 0 && tcase.expectedVschema.Vindexes[tcase.request.Name].Owner != "" { - targetTablet.vrdbClient.ExpectRequest(fmt.Sprintf(readWorkflowConfig, tcase.request.Name), sqltypes.MakeTestResult( + targetTablet.vrdbClient.ExpectRequest(fmt.Sprintf(readWorkflowConfig, tcase.request.Name, tenv.dbName), sqltypes.MakeTestResult( sqltypes.MakeTestFields( "id|source|cell|tablet_types|state|message", "int64|blob|varchar|varchar|varchar|varchar", diff --git a/go/vt/vttablet/tabletmanager/semisyncmonitor/monitor_test.go b/go/vt/vttablet/tabletmanager/semisyncmonitor/monitor_test.go index 5137d77ef97..b26cccfa549 100644 --- a/go/vt/vttablet/tabletmanager/semisyncmonitor/monitor_test.go +++ b/go/vt/vttablet/tabletmanager/semisyncmonitor/monitor_test.go @@ -656,12 +656,12 @@ func TestMonitorWriteBlocked(t *testing.T) { m.mu.Lock() defer m.mu.Unlock() return m.inProgressWriteCount > 0 - }, 2*time.Second, 5*time.Microsecond) + }, 15*time.Second, 1*time.Microsecond) // Check that the writes finished successfully. require.Eventually(t, func() bool { return writeFinished.Load() - }, 2*time.Second, 100*time.Millisecond) + }, 10*time.Second, 100*time.Millisecond) // After write completes, count should be back to zero. m.mu.Lock() diff --git a/go/vt/vttablet/tabletmanager/shard_sync.go b/go/vt/vttablet/tabletmanager/shard_sync.go index 4afbaa1a639..dcb9245b06a 100644 --- a/go/vt/vttablet/tabletmanager/shard_sync.go +++ b/go/vt/vttablet/tabletmanager/shard_sync.go @@ -241,7 +241,7 @@ func (tm *TabletManager) endPrimaryTerm(ctx context.Context, primaryAlias *topod log.Infof("Active reparents are enabled; converting MySQL to replica.") demotePrimaryCtx, cancelDemotePrimary := context.WithTimeout(ctx, topo.RemoteOperationTimeout) defer cancelDemotePrimary() - if _, err := tm.demotePrimary(demotePrimaryCtx, false /* revertPartialFailure */); err != nil { + if _, err := tm.demotePrimary(demotePrimaryCtx, false /* revertPartialFailure */, true /* force */); err != nil { return vterrors.Wrap(err, "failed to demote primary") } setPrimaryCtx, cancelSetPrimary := context.WithTimeout(ctx, topo.RemoteOperationTimeout) diff --git a/go/vt/vttablet/tabletmanager/tm_init.go b/go/vt/vttablet/tabletmanager/tm_init.go index 92fd5ffb19d..8aafb7366ab 100644 --- a/go/vt/vttablet/tabletmanager/tm_init.go +++ b/go/vt/vttablet/tabletmanager/tm_init.go @@ -1067,8 +1067,8 @@ func (tm *TabletManager) initializeReplication(ctx context.Context, tabletType t return "", vterrors.New(vtrpc.Code_FAILED_PRECONDITION, fmt.Sprintf("Errant GTID detected - %s; Primary GTID - %s, Replica GTID - %s", errantGtid, primaryPosition, replicaPos.String())) } - if err := tm.MysqlDaemon.SetReplicationSource(ctx, currentPrimary.Tablet.MysqlHostname, currentPrimary.Tablet.MysqlPort, 0, true, true); err != nil { - return "", vterrors.Wrap(err, "MysqlDaemon.SetReplicationSource failed") + if err := tm.setReplicationSourceRecoverable(ctx, currentPrimary.Tablet.MysqlHostname, currentPrimary.Tablet.MysqlPort, 0, true, true); err != nil { + return "", vterrors.Wrap(err, "failed to configure replication source") } return primaryStatus.Position, nil diff --git a/go/vt/vttablet/tabletmanager/tm_init_test.go b/go/vt/vttablet/tabletmanager/tm_init_test.go index a6c5d33c975..2245b78fd35 100644 --- a/go/vt/vttablet/tabletmanager/tm_init_test.go +++ b/go/vt/vttablet/tabletmanager/tm_init_test.go @@ -24,10 +24,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "golang.org/x/sync/semaphore" "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/mysql/collations" "vitess.io/vitess/go/mysql/fakesqldb" + "vitess.io/vitess/go/mysql/replication" "vitess.io/vitess/go/protoutil" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/test/utils" @@ -39,6 +41,8 @@ import ( "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/topo/memorytopo" "vitess.io/vitess/go/vt/topotools" + "vitess.io/vitess/go/vt/vtctl/reparentutil/policy" + "vitess.io/vitess/go/vt/vtctl/reparentutil/reparenttestutil" "vitess.io/vitess/go/vt/vttablet/tabletmanager/semisyncmonitor" "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" "vitess.io/vitess/go/vt/vttablet/tabletservermock" @@ -684,9 +688,7 @@ func newTestMysqlDaemon(t *testing.T, port int32) *mysqlctl.FakeMysqlDaemon { return mysqld } -var ( - exporter = servenv.NewExporter("TestTabletManager", "") -) +var exporter = servenv.NewExporter("TestTabletManager", "") func newTestTM(t *testing.T, ts *topo.Server, uid int, keyspace, shard string, tags map[string]string) *TabletManager { // reset stats @@ -824,7 +826,8 @@ func TestWaitForDBAGrants(t *testing.T) { cluster.TearDown() } }, - }, { + }, + { name: "Failure due to timeout", waitTime: 300 * time.Millisecond, errWanted: "timed out after 300ms waiting for the dba user to have the required permissions", @@ -845,7 +848,8 @@ func TestWaitForDBAGrants(t *testing.T) { cluster.TearDown() } }, - }, { + }, + { name: "Success for externally managed tablet", waitTime: 300 * time.Millisecond, errWanted: "", @@ -868,7 +872,8 @@ func TestWaitForDBAGrants(t *testing.T) { cluster.TearDown() } }, - }, { + }, + { name: "Empty timeout", waitTime: 0, errWanted: "", @@ -878,7 +883,8 @@ func TestWaitForDBAGrants(t *testing.T) { } return tc, func() {} }, - }, { + }, + { name: "Empty config", waitTime: 300 * time.Millisecond, errWanted: "", @@ -961,3 +967,82 @@ func grantAllPrivilegesToUser(t *testing.T, connParams mysql.ConnParams, testUse require.NoError(t, err) conn.Close() } + +// TestInitReplicationRecovery verifies replica startup initialization self-heals recoverable +// init failures returned from SetReplicationSource. +func TestInitReplicationRecovery(t *testing.T) { + ctx := t.Context() + ts := memorytopo.NewServer(ctx, "cell1") + tablet := newTestTablet(t, 1, "ks", "0", nil) + fakeMysqlDaemon := newTestMysqlDaemon(t, 1) + + tm := &TabletManager{ + actionSema: semaphore.NewWeighted(1), + BatchCtx: ctx, + TopoServer: ts, + MysqlDaemon: fakeMysqlDaemon, + tmc: newFakeTMClient(), + tabletAlias: tablet.Alias, + _waitForGrantsComplete: make(chan struct{}), + tmState: &tmState{ + displayState: displayState{ + tablet: tablet, + }, + }, + } + close(tm._waitForGrantsComplete) + + _, err := ts.GetOrCreateShard(ctx, "ks", "0") + require.NoError(t, err) + require.NoError(t, ts.CreateTablet(ctx, tablet)) + + reparenttestutil.SetKeyspaceDurability(ctx, t, ts, "ks", policy.DurabilityNone) + + primary := &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "cell1", + Uid: 2, + }, + Hostname: "primary-host", + PortMap: map[string]int32{ + "vt": 1234, + "grpc": 3456, + }, + Keyspace: "ks", + Shard: "0", + Type: topodatapb.TabletType_PRIMARY, + MysqlHostname: "mysql-primary", + MysqlPort: 3306, + } + require.NoError(t, ts.CreateTablet(ctx, primary)) + _, err = ts.UpdateShardFields(ctx, "ks", "0", func(si *topo.ShardInfo) error { + si.PrimaryAlias = primary.Alias + return nil + }) + require.NoError(t, err) + + pos, err := replication.ParsePosition(gtidFlavor, gtidPosition) + require.NoError(t, err) + + // Make StartReplication return a recoverable init error and expect the + // startup path to self-heal by restarting replication. SetReplicationSource + // is called with startReplicationAfter=false so recovery only applies to + // the separate StartReplication call. + fakeMysqlDaemon.SetPrimaryPositionLocked(pos) + fakeMysqlDaemon.SetReplicationSourceInputs = []string{"mysql-primary:3306"} + fakeMysqlDaemon.StartReplicationError = recoverableReplicationInitError() + fakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ + "STOP REPLICA", + "FAKE SET SOURCE", + "STOP REPLICA", + "RESET REPLICA", + "START REPLICA", + } + + // initializeReplication should now succeed and return the primary position + // after self-healing the recoverable error. + gotPosition, err := tm.initializeReplication(ctx, topodatapb.TabletType_REPLICA) + require.NoError(t, err) + require.Equal(t, fmt.Sprintf("%s/%s", gtidFlavor, gtidPosition), gotPosition) + require.NoError(t, fakeMysqlDaemon.CheckSuperQueryList()) +} diff --git a/go/vt/vttablet/tabletmanager/vdiff/action.go b/go/vt/vttablet/tabletmanager/vdiff/action.go index 9cfb145c1e0..c238a11f772 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/action.go +++ b/go/vt/vttablet/tabletmanager/vdiff/action.go @@ -118,7 +118,7 @@ func (vde *Engine) getVDiffSummary(vdiffID int64, dbClient binlogplayer.DBClient var qr *sqltypes.Result var err error - query, err := sqlparser.ParseAndBind(sqlVDiffSummary, sqltypes.Int64BindVariable(vdiffID)) + query, err := sqlparser.ParseAndBind(sqlVDiffSummary, sqltypes.Int64BindVariable(vdiffID), sqltypes.StringBindVariable(vde.dbName)) if err != nil { return nil, err } @@ -176,7 +176,7 @@ func (vde *Engine) handleCreateResumeAction(ctx context.Context, dbClient binlog var qr *sqltypes.Result options := req.GetOptions() - query, err := sqlparser.ParseAndBind(sqlGetVDiffID, sqltypes.StringBindVariable(req.VdiffUuid)) + query, err := sqlparser.ParseAndBind(sqlGetVDiffID, sqltypes.StringBindVariable(req.VdiffUuid), sqltypes.StringBindVariable(vde.dbName)) if err != nil { return err } @@ -235,6 +235,7 @@ func (vde *Engine) handleCreateResumeAction(ctx context.Context, dbClient binlog execResume := func(query string) (rowsAffected uint64, err error) { query, err = sqlparser.ParseAndBind(query, sqltypes.StringBindVariable(req.VdiffUuid), + sqltypes.StringBindVariable(vde.dbName), ) if err != nil { return 0, err @@ -296,6 +297,7 @@ func (vde *Engine) handleShowAction(ctx context.Context, dbClient binlogplayer.D query, err := sqlparser.ParseAndBind(sqlGetMostRecentVDiffByKeyspaceWorkflow, sqltypes.StringBindVariable(req.Keyspace), sqltypes.StringBindVariable(req.Workflow), + sqltypes.StringBindVariable(vde.dbName), sqltypes.Int64BindVariable(1), ) if err != nil { @@ -319,6 +321,7 @@ func (vde *Engine) handleShowAction(ctx context.Context, dbClient binlogplayer.D sqltypes.StringBindVariable(req.Keyspace), sqltypes.StringBindVariable(req.Workflow), sqltypes.StringBindVariable(vdiffUUID), + sqltypes.StringBindVariable(vde.dbName), ) if err != nil { return err @@ -348,6 +351,7 @@ func (vde *Engine) handleShowAction(ctx context.Context, dbClient binlogplayer.D query, err := sqlparser.ParseAndBind(sqlGetMostRecentVDiffByKeyspaceWorkflow, sqltypes.StringBindVariable(req.Keyspace), sqltypes.StringBindVariable(req.Workflow), + sqltypes.StringBindVariable(vde.dbName), sqltypes.Int64BindVariable(maxVDiffsToReport), ) if err != nil { @@ -404,6 +408,7 @@ func (vde *Engine) handleDeleteAction(ctx context.Context, dbClient binlogplayer query, err := sqlparser.ParseAndBind(sqlGetVDiffIDsByKeyspaceWorkflow, sqltypes.StringBindVariable(req.Keyspace), sqltypes.StringBindVariable(req.Workflow), + sqltypes.StringBindVariable(vde.dbName), ) if err != nil { return err @@ -418,6 +423,7 @@ func (vde *Engine) handleDeleteAction(ctx context.Context, dbClient binlogplayer deleteQuery, err = sqlparser.ParseAndBind(sqlDeleteVDiffs, sqltypes.StringBindVariable(req.Keyspace), sqltypes.StringBindVariable(req.Workflow), + sqltypes.StringBindVariable(vde.dbName), ) if err != nil { return err @@ -431,6 +437,7 @@ func (vde *Engine) handleDeleteAction(ctx context.Context, dbClient binlogplayer // it's still running, before we delete the vdiff record. query, err := sqlparser.ParseAndBind(sqlGetVDiffID, sqltypes.StringBindVariable(uuid.String()), + sqltypes.StringBindVariable(vde.dbName), ) if err != nil { return err @@ -447,6 +454,7 @@ func (vde *Engine) handleDeleteAction(ctx context.Context, dbClient binlogplayer cleanupController(vde.controllers[row.AsInt64("id", -1)]) deleteQuery, err = sqlparser.ParseAndBind(sqlDeleteVDiffByUUID, sqltypes.StringBindVariable(uuid.String()), + sqltypes.StringBindVariable(vde.dbName), ) if err != nil { return err diff --git a/go/vt/vttablet/tabletmanager/vdiff/action_test.go b/go/vt/vttablet/tabletmanager/vdiff/action_test.go index 6bdc7044878..d885f7b180b 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/action_test.go +++ b/go/vt/vttablet/tabletmanager/vdiff/action_test.go @@ -85,7 +85,7 @@ func TestPerformVDiffAction(t *testing.T) { }, expectQueries: []queryAndResult{ { - query: fmt.Sprintf("select id as id from _vt.vdiff where vdiff_uuid = %s", encodeString(uuid)), + query: "select id as id from _vt.vdiff where vdiff_uuid = " + encodeString(uuid) + " and db_name = " + encodeString(vdiffDBName), }, { query: fmt.Sprintf(`insert into _vt.vdiff(keyspace, workflow, state, options, shard, db_name, vdiff_uuid) values('', '', 'pending', '{"picker_options":{"source_cell":"cell1,zone100_test","target_cell":"cell1,zone100_test"}}', '0', 'vt_vttest', %s)`, encodeString(uuid)), @@ -109,7 +109,7 @@ func TestPerformVDiffAction(t *testing.T) { }, expectQueries: []queryAndResult{ { - query: fmt.Sprintf("select id as id from _vt.vdiff where vdiff_uuid = %s", encodeString(uuid)), + query: "select id as id from _vt.vdiff where vdiff_uuid = " + encodeString(uuid) + " and db_name = " + encodeString(vdiffDBName), }, { query: fmt.Sprintf(`insert into _vt.vdiff(keyspace, workflow, state, options, shard, db_name, vdiff_uuid) values('', '', 'stopped', '{"picker_options":{"source_cell":"cell1","target_cell":"cell1"},"core_options":{"auto_start":false}}', '0', 'vt_vttest', %s)`, encodeString(uuid)), @@ -140,7 +140,7 @@ func TestPerformVDiffAction(t *testing.T) { }, expectQueries: []queryAndResult{ { - query: fmt.Sprintf("select id as id from _vt.vdiff where vdiff_uuid = %s", encodeString(uuid)), + query: "select id as id from _vt.vdiff where vdiff_uuid = " + encodeString(uuid) + " and db_name = " + encodeString(vdiffDBName), }, { query: fmt.Sprintf(`insert into _vt.vdiff(keyspace, workflow, state, options, shard, db_name, vdiff_uuid) values('', '', 'pending', '{"picker_options":{"source_cell":"all","target_cell":"all"}}', '0', 'vt_vttest', %s)`, encodeString(uuid)), @@ -163,7 +163,7 @@ func TestPerformVDiffAction(t *testing.T) { }, expectQueries: []queryAndResult{ { - query: fmt.Sprintf("select id as id from _vt.vdiff where vdiff_uuid = %s", encodeString(uuid)), + query: "select id as id from _vt.vdiff where vdiff_uuid = " + encodeString(uuid) + " and db_name = " + encodeString(vdiffDBName), result: sqltypes.MakeTestResult( sqltypes.MakeTestFields( "id", @@ -174,23 +174,23 @@ func TestPerformVDiffAction(t *testing.T) { }, { query: fmt.Sprintf(`update _vt.vdiff as vd, _vt.vdiff_table as vdt set vd.started_at = NULL, vd.completed_at = NULL, vd.state = 'pending', - vdt.state = 'pending' where vd.vdiff_uuid = %s and vd.id = vdt.vdiff_id and vd.state in ('completed', 'stopped') - and vdt.state in ('completed', 'stopped')`, encodeString(uuid)), + vdt.state = 'pending' where vd.vdiff_uuid = %s and vd.db_name = %s and vd.id = vdt.vdiff_id and vd.state in ('completed', 'stopped') + and vdt.state in ('completed', 'stopped')`, encodeString(uuid), encodeString(vdiffDBName)), result: &sqltypes.Result{ RowsAffected: 0, // No _vt.vdiff_table records }, }, { - query: fmt.Sprintf(`update _vt.vdiff as vd set vd.state = 'pending' where vd.vdiff_uuid = %s and vd.state = 'stopped' and + query: fmt.Sprintf(`update _vt.vdiff as vd set vd.state = 'pending' where vd.vdiff_uuid = %s and vd.db_name = %s and vd.state = 'stopped' and vd.started_at is NULL and vd.completed_at is NULL and (select count(*) as cnt from _vt.vdiff_table as vdt where vd.id = vdt.vdiff_id) = 0`, - encodeString(uuid)), + encodeString(uuid), encodeString(vdiffDBName)), result: &sqltypes.Result{ RowsAffected: 1, }, }, { - query: "select * from _vt.vdiff where id = 1", + query: "select * from _vt.vdiff where id = 1 and db_name = " + encodeString(vdiffDBName), }, }, }, @@ -204,7 +204,7 @@ func TestPerformVDiffAction(t *testing.T) { }, expectQueries: []queryAndResult{ { - query: fmt.Sprintf("select id as id from _vt.vdiff where vdiff_uuid = %s", encodeString(uuid)), + query: "select id as id from _vt.vdiff where vdiff_uuid = " + encodeString(uuid) + " and db_name = " + encodeString(vdiffDBName), result: sqltypes.MakeTestResult( sqltypes.MakeTestFields( "id", @@ -215,14 +215,14 @@ func TestPerformVDiffAction(t *testing.T) { }, { query: fmt.Sprintf(`update _vt.vdiff as vd, _vt.vdiff_table as vdt set vd.started_at = NULL, vd.completed_at = NULL, vd.state = 'pending', - vdt.state = 'pending' where vd.vdiff_uuid = %s and vd.id = vdt.vdiff_id and vd.state in ('completed', 'stopped') - and vdt.state in ('completed', 'stopped')`, encodeString(uuid)), + vdt.state = 'pending' where vd.vdiff_uuid = %s and vd.db_name = %s and vd.id = vdt.vdiff_id and vd.state in ('completed', 'stopped') + and vdt.state in ('completed', 'stopped')`, encodeString(uuid), encodeString(vdiffDBName)), result: &sqltypes.Result{ RowsAffected: 1, }, }, { - query: "select * from _vt.vdiff where id = 1", + query: "select * from _vt.vdiff where id = 1 and db_name = " + encodeString(vdiffDBName), }, }, }, @@ -234,7 +234,7 @@ func TestPerformVDiffAction(t *testing.T) { }, expectQueries: []queryAndResult{ { - query: fmt.Sprintf("select id as id from _vt.vdiff where vdiff_uuid = %s", encodeString(uuid)), + query: "select id as id from _vt.vdiff where vdiff_uuid = " + encodeString(uuid) + " and db_name = " + encodeString(vdiffDBName), result: sqltypes.MakeTestResult( sqltypes.MakeTestFields( "id", @@ -244,8 +244,7 @@ func TestPerformVDiffAction(t *testing.T) { ), }, { - query: fmt.Sprintf(`delete from vd, vdt using _vt.vdiff as vd left join _vt.vdiff_table as vdt on (vd.id = vdt.vdiff_id) - where vd.vdiff_uuid = %s`, encodeString(uuid)), + query: "delete from vd, vdt using _vt.vdiff as vd left join _vt.vdiff_table as vdt on (vd.id = vdt.vdiff_id)\n\t\t\t\t\t\t\twhere vd.vdiff_uuid = " + encodeString(uuid) + " and vd.db_name = " + encodeString(vdiffDBName), }, }, }, @@ -259,7 +258,7 @@ func TestPerformVDiffAction(t *testing.T) { }, expectQueries: []queryAndResult{ { - query: fmt.Sprintf("select id as id from _vt.vdiff where keyspace = %s and workflow = %s", encodeString(keyspace), encodeString(workflow)), + query: fmt.Sprintf("select id as id from _vt.vdiff where keyspace = %s and workflow = %s and db_name = %s", encodeString(keyspace), encodeString(workflow), encodeString(vdiffDBName)), result: sqltypes.MakeTestResult( sqltypes.MakeTestFields( "id", @@ -272,7 +271,7 @@ func TestPerformVDiffAction(t *testing.T) { { query: fmt.Sprintf(`delete from vd, vdt, vdl using _vt.vdiff as vd left join _vt.vdiff_table as vdt on (vd.id = vdt.vdiff_id) left join _vt.vdiff_log as vdl on (vd.id = vdl.vdiff_id) - where vd.keyspace = %s and vd.workflow = %s`, encodeString(keyspace), encodeString(workflow)), + where vd.keyspace = %s and vd.workflow = %s and vd.db_name = %s`, encodeString(keyspace), encodeString(workflow), encodeString(vdiffDBName)), }, }, }, @@ -286,8 +285,8 @@ func TestPerformVDiffAction(t *testing.T) { }, expectQueries: []queryAndResult{ { - query: fmt.Sprintf("select * from _vt.vdiff where keyspace = %s and workflow = %s order by id desc limit %d", - encodeString(keyspace), encodeString(workflow), 1), + query: fmt.Sprintf("select * from _vt.vdiff where keyspace = %s and workflow = %s and db_name = %s order by id desc limit %d", + encodeString(keyspace), encodeString(workflow), encodeString(vdiffDBName), 1), result: noResults, }, }, @@ -302,8 +301,8 @@ func TestPerformVDiffAction(t *testing.T) { }, expectQueries: []queryAndResult{ { - query: fmt.Sprintf("select * from _vt.vdiff where keyspace = %s and workflow = %s order by id desc limit %d", - encodeString(keyspace), encodeString(workflow), maxVDiffsToReport), + query: fmt.Sprintf("select * from _vt.vdiff where keyspace = %s and workflow = %s and db_name = %s order by id desc limit %d", + encodeString(keyspace), encodeString(workflow), encodeString(vdiffDBName), maxVDiffsToReport), result: noResults, }, }, diff --git a/go/vt/vttablet/tabletmanager/vdiff/controller.go b/go/vt/vttablet/tabletmanager/vdiff/controller.go index 7b5e1311066..a0acdc98c4c 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/controller.go +++ b/go/vt/vttablet/tabletmanager/vdiff/controller.go @@ -114,8 +114,11 @@ func (ct *controller) Stop() { func (ct *controller) run(ctx context.Context) { defer func() { - log.Infof("Run finished for vdiff %s", ct.uuid) + log.Info("Run finished for vdiff " + ct.uuid) + // Unblock Stop() callers waiting on <-ct.done. close(ct.done) + // Release gRPC connections held by this controller's tablet manager client. + ct.tmc.Close() }() dbClient := ct.vde.dbClientFactoryFiltered() @@ -176,6 +179,7 @@ func (ct *controller) updateState(dbClient binlogplayer.DBClient, state VDiffSta encodeString(err.Error()), extraCols, ct.id, + encodeString(ct.vde.dbName), ) if _, err := dbClient.ExecuteFetch(query.Query, 1); err != nil { return err @@ -274,7 +278,7 @@ func (ct *controller) markStoppedByRequest() error { } defer dbClient.Close() - query, err := sqlparser.ParseAndBind(sqlUpdateVDiffStopped, sqltypes.Int64BindVariable(ct.id)) + query, err := sqlparser.ParseAndBind(sqlUpdateVDiffStopped, sqltypes.Int64BindVariable(ct.id), sqltypes.StringBindVariable(ct.vde.dbName)) if err != nil { return err } diff --git a/go/vt/vttablet/tabletmanager/vdiff/engine.go b/go/vt/vttablet/tabletmanager/vdiff/engine.go index cd3771accfd..cb27e4c84f0 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/engine.go +++ b/go/vt/vttablet/tabletmanager/vdiff/engine.go @@ -292,7 +292,11 @@ func (vde *Engine) getVDiffsToRun(ctx context.Context) (*sqltypes.Result, error) // We have to use ExecIgnore here so as not to block quick tablet state // transitions from primary to non-primary when starting the engine - qr, err := dbClient.ExecuteFetch(sqlGetVDiffsToRun, -1) + query, err := sqlparser.ParseAndBind(sqlGetVDiffsToRun, sqltypes.StringBindVariable(vde.dbName)) + if err != nil { + return nil, err + } + qr, err := dbClient.ExecuteFetch(query, -1) if err != nil { return nil, err } @@ -303,7 +307,11 @@ func (vde *Engine) getVDiffsToRun(ctx context.Context) (*sqltypes.Result, error) } func (vde *Engine) getVDiffsToRetry(ctx context.Context, dbClient binlogplayer.DBClient) (*sqltypes.Result, error) { - qr, err := dbClient.ExecuteFetch(sqlGetVDiffsToRetry, -1) + query, err := sqlparser.ParseAndBind(sqlGetVDiffsToRetry, sqltypes.StringBindVariable(vde.dbName)) + if err != nil { + return nil, err + } + qr, err := dbClient.ExecuteFetch(query, -1) if err != nil { return nil, err } @@ -314,7 +322,7 @@ func (vde *Engine) getVDiffsToRetry(ctx context.Context, dbClient binlogplayer.D } func (vde *Engine) getVDiffByID(ctx context.Context, dbClient binlogplayer.DBClient, id int64) (*sqltypes.Result, error) { - query, err := sqlparser.ParseAndBind(sqlGetVDiffByID, sqltypes.Int64BindVariable(id)) + query, err := sqlparser.ParseAndBind(sqlGetVDiffByID, sqltypes.Int64BindVariable(id), sqltypes.StringBindVariable(vde.dbName)) if err != nil { return nil, err } @@ -360,8 +368,8 @@ func (vde *Engine) retryVDiffs(ctx context.Context) error { if err != nil { return err } - log.Infof("Retrying vdiff %s that had an ephemeral error of '%v'", uuid, lastError) - query, err := sqlparser.ParseAndBind(sqlRetryVDiff, sqltypes.Int64BindVariable(id)) + log.Info(fmt.Sprintf("Retrying vdiff %s that had an ephemeral error of '%v'", uuid, lastError)) + query, err := sqlparser.ParseAndBind(sqlRetryVDiff, sqltypes.Int64BindVariable(id), sqltypes.StringBindVariable(vde.dbName)) if err != nil { return err } diff --git a/go/vt/vttablet/tabletmanager/vdiff/engine_test.go b/go/vt/vttablet/tabletmanager/vdiff/engine_test.go index 374756418c6..94aa99b0737 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/engine_test.go +++ b/go/vt/vttablet/tabletmanager/vdiff/engine_test.go @@ -69,8 +69,8 @@ func TestEngineOpen(t *testing.T) { fmt.Sprintf("1|%s|%s|%s|%s|%s|%s|%s|", UUID, vdenv.workflow, tstenv.KeyspaceName, tstenv.ShardName, vdiffDBName, tt.state, optionsJS), ) - vdenv.dbClient.ExpectRequest("select * from _vt.vdiff where state in ('started','pending')", initialQR, nil) - vdenv.dbClient.ExpectRequest("select * from _vt.vdiff where id = 1", sqltypes.MakeTestResult(sqltypes.MakeTestFields( + vdenv.dbClient.ExpectRequest("select * from _vt.vdiff where state in ('started','pending') and db_name = "+encodeString(vdiffDBName), initialQR, nil) + vdenv.dbClient.ExpectRequest("select * from _vt.vdiff where id = 1 and db_name = "+encodeString(vdiffDBName), sqltypes.MakeTestResult(sqltypes.MakeTestFields( vdiffTestCols, vdiffTestColTypes, ), @@ -84,7 +84,7 @@ func TestEngineOpen(t *testing.T) { ), nil) // Now let's short circuit the vdiff as we know that the open has worked as expected. - shortCircuitTestAfterQuery("update _vt.vdiff set state = 'started', last_error = left('', 1024) , started_at = utc_timestamp() where id = 1", vdiffenv.dbClient) + shortCircuitTestAfterQuery("update _vt.vdiff set state = 'started', last_error = left('', 1024) , started_at = utc_timestamp() where id = 1 and db_name = 'vttest'", vdiffenv.dbClient) vdenv.vde.Open(context.Background(), vdiffenv.vre) defer vdenv.vde.Close() @@ -124,14 +124,14 @@ func TestVDiff(t *testing.T) { fmt.Sprintf("1|%s|%s|%s|%s|%s|pending|%s|", UUID, vdenv.workflow, tstenv.KeyspaceName, tstenv.ShardName, vdiffDBName, optionsJS), ) - vdenv.dbClient.ExpectRequest("select * from _vt.vdiff where id = 1", controllerQR, nil) + vdenv.dbClient.ExpectRequest("select * from _vt.vdiff where id = 1 and db_name = "+encodeString(vdiffDBName), controllerQR, nil) vdenv.dbClient.ExpectRequest(fmt.Sprintf("select * from _vt.vreplication where workflow = '%s' and db_name = '%s'", vdiffenv.workflow, vdiffDBName), sqltypes.MakeTestResult(sqltypes.MakeTestFields( "id|workflow|source|pos|stop_pos|max_tps|max_replication_lag|cell|tablet_types|time_updated|transaction_timestamp|state|message|db_name|rows_copied|tags|time_heartbeat|workflow_type|time_throttled|component_throttled|workflow_sub_type|options", "int64|varbinary|blob|varbinary|varbinary|int64|int64|varbinary|varbinary|int64|int64|varbinary|varbinary|varbinary|int64|varbinary|int64|int64|int64|varchar|int64|varchar", ), fmt.Sprintf("1|%s|%s|%s||9223372036854775807|9223372036854775807||PRIMARY,REPLICA|1669511347|0|Running||%s|200||1669511347|1|0||1|{}", vdiffenv.workflow, vreplSource, vdiffSourceGtid, vdiffDBName), ), nil) - vdenv.dbClient.ExpectRequest("update _vt.vdiff set state = 'started', last_error = left('', 1024) , started_at = utc_timestamp() where id = 1", singleRowAffected, nil) + vdenv.dbClient.ExpectRequest("update _vt.vdiff set state = 'started', last_error = left('', 1024) , started_at = utc_timestamp() where id = 1 and db_name = 'vttest'", singleRowAffected, nil) vdenv.dbClient.ExpectRequest("insert into _vt.vdiff_log(vdiff_id, message) values (1, 'State changed to: started')", singleRowAffected, nil) vdenv.dbClient.ExpectRequest(`select vdt.lastpk as lastpk, vdt.mismatch as mismatch, vdt.report as report from _vt.vdiff as vd inner join _vt.vdiff_table as vdt on (vd.id = vdt.vdiff_id) @@ -193,7 +193,7 @@ func TestVDiff(t *testing.T) { vdenv.dbClient.ExpectRequest("update _vt.vdiff_table set state = 'completed' where vdiff_id = 1 and table_name = 't1'", singleRowAffected, nil) vdenv.dbClient.ExpectRequest(`insert into _vt.vdiff_log(vdiff_id, message) values (1, 'completed: table \'t1\'')`, singleRowAffected, nil) vdenv.dbClient.ExpectRequest("select table_name as table_name from _vt.vdiff_table where vdiff_id = 1 and state != 'completed' order by table_name", singleRowAffected, nil) - vdenv.dbClient.ExpectRequest("update _vt.vdiff set state = 'completed', last_error = left('', 1024) , completed_at = utc_timestamp() where id = 1", singleRowAffected, nil) + vdenv.dbClient.ExpectRequest("update _vt.vdiff set state = 'completed', last_error = left('', 1024) , completed_at = utc_timestamp() where id = 1 and db_name = 'vttest'", singleRowAffected, nil) vdenv.dbClient.ExpectRequest("insert into _vt.vdiff_log(vdiff_id, message) values (1, 'State changed to: completed')", singleRowAffected, nil) vdenv.vde.mu.Lock() @@ -243,7 +243,7 @@ func TestEngineRetryErroredVDiffs(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - vdiffenv.dbClient.ExpectRequest("select * from _vt.vdiff where state = 'error' and json_unquote(json_extract(options, '$.core_options.auto_retry')) = 'true'", tt.retryQueryResults, nil) + vdiffenv.dbClient.ExpectRequest("select * from _vt.vdiff where state = 'error' and json_unquote(json_extract(options, '$.core_options.auto_retry')) = 'true' and db_name = "+encodeString(vdiffDBName), tt.retryQueryResults, nil) // Right now this only supports a single row as with multiple rows we have // multiple controllers in separate goroutines and the order is not @@ -255,8 +255,8 @@ func TestEngineRetryErroredVDiffs(t *testing.T) { for _, row := range tt.retryQueryResults.Rows { id := row[0].ToString() if tt.expectRetry { - vdiffenv.dbClient.ExpectRequestRE("update _vt.vdiff as vd left join _vt.vdiff_table as vdt on \\(vd.id = vdt.vdiff_id\\) set vd.state = 'pending'.*", singleRowAffected, nil) - vdiffenv.dbClient.ExpectRequest(fmt.Sprintf("select * from _vt.vdiff where id = %s", id), sqltypes.MakeTestResult(sqltypes.MakeTestFields( + vdiffenv.dbClient.ExpectRequestRE("update _vt.vdiff as vd left join _vt.vdiff_table as vdt on \\(vd.id = vdt.vdiff_id\\) set vd.state = 'pending'[\\s\\S]*vd.db_name[\\s\\S]*", singleRowAffected, nil) + vdiffenv.dbClient.ExpectRequest("select * from _vt.vdiff where id = "+id+" and db_name = "+encodeString(vdiffDBName), sqltypes.MakeTestResult(sqltypes.MakeTestFields( vdiffTestCols, vdiffTestColTypes, ), @@ -270,12 +270,10 @@ func TestEngineRetryErroredVDiffs(t *testing.T) { ), nil) // At this point we know that we kicked off the expected retry so we can short circuit the vdiff. - shortCircuitTestAfterQuery(fmt.Sprintf("update _vt.vdiff set state = 'started', last_error = left('', 1024) , started_at = utc_timestamp() where id = %s", id), vdiffenv.dbClient) - + shortCircuitTestAfterQuery("update _vt.vdiff set state = 'started', last_error = left('', 1024) , started_at = utc_timestamp() where id = "+id+" and db_name = 'vttest'", vdiffenv.dbClient) expectedControllerCnt++ } } - err := vdiffenv.vde.retryVDiffs(vdiffenv.vde.ctx) assert.NoError(t, err) assert.Equal(t, expectedControllerCnt, len(vdiffenv.vde.controllers)) diff --git a/go/vt/vttablet/tabletmanager/vdiff/framework_test.go b/go/vt/vttablet/tabletmanager/vdiff/framework_test.go index 4c1c7e8f3b8..5c8d336929f 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/framework_test.go +++ b/go/vt/vttablet/tabletmanager/vdiff/framework_test.go @@ -18,6 +18,7 @@ package vdiff import ( "context" + "errors" "fmt" "io" "os" @@ -210,8 +211,8 @@ func resetBinlogClient() { // This can be used to end a vdiff, by returning an error from the specified query, once the test // has verified the necessary behavior. func shortCircuitTestAfterQuery(query string, dbClient *binlogplayer.MockDBClient) { - dbClient.ExpectRequest(query, singleRowAffected, fmt.Errorf("Short circuiting test")) - dbClient.ExpectRequest("update _vt.vdiff set state = 'error', last_error = left('Short circuiting test', 1024) where id = 1", singleRowAffected, nil) + dbClient.ExpectRequest(query, singleRowAffected, errors.New("Short circuiting test")) + dbClient.ExpectRequest("update _vt.vdiff set state = 'error', last_error = left('Short circuiting test', 1024) where id = 1 and db_name = "+encodeString(vdiffDBName), singleRowAffected, nil) dbClient.ExpectRequest("insert into _vt.vdiff_log(vdiff_id, message) values (1, 'State changed to: error')", singleRowAffected, nil) dbClient.ExpectRequest("insert into _vt.vdiff_log(vdiff_id, message) values (1, 'Error: Short circuiting test')", singleRowAffected, nil) } @@ -455,6 +456,9 @@ func newFakeTMClient() *fakeTMClient { } } +// Close satisfies the TabletManagerClient interface. +func (tmc *fakeTMClient) Close() {} + func (tmc *fakeTMClient) GetSchema(ctx context.Context, tablet *topodatapb.Tablet, request *tabletmanagerdatapb.GetSchemaRequest) (*tabletmanagerdatapb.SchemaDefinition, error) { return tmc.schema, nil } @@ -610,7 +614,7 @@ func newTestVDiffEnv(t *testing.T) *testVDiffEnv { // vdiff.restartTargets vdiffenv.tmc.setVRResults(primary.tablet, fmt.Sprintf("update _vt.vreplication set state='Running', message='', stop_pos='' where db_name='%s' and workflow='%s'", vdiffDBName, vdiffenv.workflow), singleRowAffected) - vdiffenv.dbClient.ExpectRequest("select * from _vt.vdiff where state in ('started','pending')", noResults, nil) + vdiffenv.dbClient.ExpectRequest("select * from _vt.vdiff where state in ('started','pending') and db_name = "+encodeString(vdiffDBName), noResults, nil) vdiffenv.vde.Open(context.Background(), vdiffenv.vre) assert.True(t, vdiffenv.vde.IsOpen()) assert.Equal(t, 0, len(vdiffenv.vde.controllers)) @@ -675,7 +679,7 @@ func (tvde *testVDiffEnv) createController(t *testing.T, id int) *controller { ), fmt.Sprintf("%d|%s|%s|%s|%s|%s|%s|%s|", id, uuid.New(), tvde.workflow, tstenv.KeyspaceName, tstenv.ShardName, vdiffDBName, PendingState, optionsJS), ) - tvde.dbClient.ExpectRequest(fmt.Sprintf("select * from _vt.vdiff where id = %d", id), noResults, nil) + tvde.dbClient.ExpectRequest(fmt.Sprintf("select * from _vt.vdiff where id = %d and db_name = %s", id, encodeString(vdiffDBName)), noResults, nil) ct := tvde.newController(t, controllerQR) ct.sources = map[string]*migrationSource{ tstenv.ShardName: { diff --git a/go/vt/vttablet/tabletmanager/vdiff/schema.go b/go/vt/vttablet/tabletmanager/vdiff/schema.go index bb238cb8a7a..f87bd9cd970 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/schema.go +++ b/go/vt/vttablet/tabletmanager/vdiff/schema.go @@ -20,37 +20,37 @@ const ( sqlAnalyzeTable = "analyze table `%s`.`%s`" sqlNewVDiff = "insert into _vt.vdiff(keyspace, workflow, state, options, shard, db_name, vdiff_uuid) values(%a, %a, %a, %a, %a, %a, %a)" sqlResumeVDiff = `update _vt.vdiff as vd, _vt.vdiff_table as vdt set vd.started_at = NULL, vd.completed_at = NULL, vd.state = 'pending', - vdt.state = 'pending' where vd.vdiff_uuid = %a and vd.id = vdt.vdiff_id and vd.state in ('completed', 'stopped') + vdt.state = 'pending' where vd.vdiff_uuid = %a and vd.db_name = %a and vd.id = vdt.vdiff_id and vd.state in ('completed', 'stopped') and vdt.state in ('completed', 'stopped')` - sqlStartVDiff = `update _vt.vdiff as vd set vd.state = 'pending' where vd.vdiff_uuid = %a and vd.state = 'stopped' and + sqlStartVDiff = `update _vt.vdiff as vd set vd.state = 'pending' where vd.vdiff_uuid = %a and vd.db_name = %a and vd.state = 'stopped' and vd.started_at is NULL and vd.completed_at is NULL and (select count(*) as cnt from _vt.vdiff_table as vdt where vd.id = vdt.vdiff_id) = 0` sqlRetryVDiff = `update _vt.vdiff as vd left join _vt.vdiff_table as vdt on (vd.id = vdt.vdiff_id) set vd.state = 'pending', - vd.last_error = '', vdt.state = 'pending' where vd.id = %a and (vd.state = 'error' or vdt.state = 'error')` - sqlGetVDiffByKeyspaceWorkflowUUID = "select * from _vt.vdiff where keyspace = %a and workflow = %a and vdiff_uuid = %a" - sqlGetMostRecentVDiffByKeyspaceWorkflow = "select * from _vt.vdiff where keyspace = %a and workflow = %a order by id desc limit %a" - sqlGetVDiffByID = "select * from _vt.vdiff where id = %a" + vd.last_error = '', vdt.state = 'pending' where vd.id = %a and vd.db_name = %a and (vd.state = 'error' or vdt.state = 'error')` + sqlGetVDiffByKeyspaceWorkflowUUID = "select * from _vt.vdiff where keyspace = %a and workflow = %a and vdiff_uuid = %a and db_name = %a" + sqlGetMostRecentVDiffByKeyspaceWorkflow = "select * from _vt.vdiff where keyspace = %a and workflow = %a and db_name = %a order by id desc limit %a" + sqlGetVDiffByID = "select * from _vt.vdiff where id = %a and db_name = %a" sqlDeleteVDiffs = `delete from vd, vdt, vdl using _vt.vdiff as vd left join _vt.vdiff_table as vdt on (vd.id = vdt.vdiff_id) left join _vt.vdiff_log as vdl on (vd.id = vdl.vdiff_id) - where vd.keyspace = %a and vd.workflow = %a` + where vd.keyspace = %a and vd.workflow = %a and vd.db_name = %a` sqlDeleteVDiffByUUID = `delete from vd, vdt using _vt.vdiff as vd left join _vt.vdiff_table as vdt on (vd.id = vdt.vdiff_id) - where vd.vdiff_uuid = %a` + where vd.vdiff_uuid = %a and vd.db_name = %a` sqlVDiffSummary = `select vd.state as vdiff_state, vd.last_error as last_error, vdt.table_name as table_name, vd.vdiff_uuid as 'uuid', vdt.state as table_state, vdt.table_rows as table_rows, vd.started_at as started_at, vdt.rows_compared as rows_compared, vd.completed_at as completed_at, IF(vdt.mismatch = 1, 1, 0) as has_mismatch, vdt.report as report from _vt.vdiff as vd left join _vt.vdiff_table as vdt on (vd.id = vdt.vdiff_id) - where vd.id = %a` + where vd.id = %a and vd.db_name = %a` // sqlUpdateVDiffState has a penultimate placeholder for any additional columns you want to update, e.g. `, foo = 1`. // It also truncates the error if needed to ensure that we can save the state when the error text is very long. - sqlUpdateVDiffState = "update _vt.vdiff set state = %s, last_error = left(%s, 1024) %s where id = %d" + sqlUpdateVDiffState = "update _vt.vdiff set state = %s, last_error = left(%s, 1024) %s where id = %d and db_name = %s" sqlUpdateVDiffStopped = `update _vt.vdiff as vd, _vt.vdiff_table as vdt set vd.state = 'stopped', vdt.state = 'stopped', vd.last_error = '' - where vd.id = vdt.vdiff_id and vd.id = %a and vd.state != 'completed'` - sqlGetVReplicationEntry = "select * from _vt.vreplication %s" // A filter/where is added by the caller - sqlGetVDiffsToRun = "select * from _vt.vdiff where state in ('started','pending')" // what VDiffs have not been stopped or completed - sqlGetVDiffsToRetry = "select * from _vt.vdiff where state = 'error' and json_unquote(json_extract(options, '$.core_options.auto_retry')) = 'true'" - sqlGetVDiffID = "select id as id from _vt.vdiff where vdiff_uuid = %a" - sqlGetVDiffIDsByKeyspaceWorkflow = "select id as id from _vt.vdiff where keyspace = %a and workflow = %a" + where vd.id = vdt.vdiff_id and vd.id = %a and vd.db_name = %a and vd.state != 'completed'` + sqlGetVReplicationEntry = "select * from _vt.vreplication %s" // A filter/where is added by the caller + sqlGetVDiffsToRun = "select * from _vt.vdiff where state in ('started','pending') and db_name = %a" // what VDiffs have not been stopped or completed + sqlGetVDiffsToRetry = "select * from _vt.vdiff where state = 'error' and json_unquote(json_extract(options, '$.core_options.auto_retry')) = 'true' and db_name = %a" + sqlGetVDiffID = "select id as id from _vt.vdiff where vdiff_uuid = %a and db_name = %a" + sqlGetVDiffIDsByKeyspaceWorkflow = "select id as id from _vt.vdiff where keyspace = %a and workflow = %a and db_name = %a" sqlGetTableRows = "select table_rows as table_rows from INFORMATION_SCHEMA.TABLES where table_schema = %a and table_name = %a" sqlGetAllTableRows = "select table_name as table_name, table_rows as table_rows from INFORMATION_SCHEMA.TABLES where table_schema = %s and table_name in (%s) order by table_name" diff --git a/go/vt/vttablet/tabletmanager/vdiff/table_differ.go b/go/vt/vttablet/tabletmanager/vdiff/table_differ.go index f63fced008d..2411288f50c 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/table_differ.go +++ b/go/vt/vttablet/tabletmanager/vdiff/table_differ.go @@ -398,15 +398,14 @@ func (td *tableDiffer) restartTargetVReplicationStreams(ctx context.Context) err func (td *tableDiffer) streamOneShard(ctx context.Context, participant *shardStreamer, query string, lastPK *querypb.QueryResult, gtidch chan string) { log.Infof("streamOneShard Start on %s using query: %s", participant.tablet.Alias.String(), query) td.wgShardStreamers.Add(1) + resultch := participant.result defer func() { - log.Infof("streamOneShard End on %s", participant.tablet.Alias.String()) - select { - case <-ctx.Done(): - default: - close(participant.result) - close(gtidch) - } + log.Info("streamOneShard End on " + participant.tablet.Alias.String()) + + close(resultch) + close(gtidch) + td.wgShardStreamers.Done() }() @@ -455,7 +454,7 @@ func (td *tableDiffer) streamOneShard(ctx context.Context, participant *shardStr result.Fields = nil } select { - case participant.result <- result: + case resultch <- result: case <-ctx.Done(): return vterrors.Wrap(ctx.Err(), "VStreamRows") case <-td.wd.ct.done: @@ -529,8 +528,13 @@ func (td *tableDiffer) diff(ctx context.Context, coreOpts *tabletmanagerdatapb.V } dr.TableName = td.table.Name - sourceExecutor := newPrimitiveExecutor(ctx, td.sourcePrimitive, "source") - targetExecutor := newPrimitiveExecutor(ctx, td.targetPrimitive, "target") + // Scope executor goroutines to this single diff attempt, rather + // than surviving until the controller context is canceled. + execCtx, cancelExec := context.WithCancel(ctx) + defer cancelExec() + + sourceExecutor := newPrimitiveExecutor(execCtx, td.sourcePrimitive, "source") + targetExecutor := newPrimitiveExecutor(execCtx, td.targetPrimitive, "target") var sourceRow, lastProcessedRow, targetRow []sqltypes.Value advanceSource := true advanceTarget := true diff --git a/go/vt/vttablet/tabletmanager/vdiff/workflow_differ.go b/go/vt/vttablet/tabletmanager/vdiff/workflow_differ.go index ea52a972d1c..a58e6ec1387 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/workflow_differ.go +++ b/go/vt/vttablet/tabletmanager/vdiff/workflow_differ.go @@ -82,7 +82,7 @@ func (wd *workflowDiffer) reconcileExtraRows(dr *DiffReport, maxExtraRowsToCompa } func (wd *workflowDiffer) reconcileReferenceTables(dr *DiffReport) error { - if dr.MismatchedRows == 0 { + if dr.MismatchedRows == 0 && dr.MatchingRows > 0 { // Get the VSchema on the target and source keyspaces. We can then use this // for handling additional edge cases, such as adjusting results for reference // tables when the shard count is different between the source and target as diff --git a/go/vt/vttablet/tabletmanager/vdiff/workflow_differ_test.go b/go/vt/vttablet/tabletmanager/vdiff/workflow_differ_test.go index dbd45f6a4d3..6ece3dc83f6 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/workflow_differ_test.go +++ b/go/vt/vttablet/tabletmanager/vdiff/workflow_differ_test.go @@ -29,11 +29,13 @@ import ( "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/binlog/binlogplayer" "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/vtgate/engine" "vitess.io/vitess/go/vt/vtgate/engine/opcode" binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" + vschemapb "vitess.io/vitess/go/vt/proto/vschema" ) func max(a, b int64) int64 { @@ -56,7 +58,7 @@ func TestReconcileExtraRows(t *testing.T) { fmt.Sprintf("1|%s|%s|%s|%s|%s|%s|%s|", UUID, vdiffenv.workflow, tstenv.KeyspaceName, tstenv.ShardName, vdiffDBName, PendingState, optionsJS), ) - vdiffenv.dbClient.ExpectRequest("select * from _vt.vdiff where id = 1", noResults, nil) + vdiffenv.dbClient.ExpectRequest("select * from _vt.vdiff where id = 1 and db_name = "+encodeString(vdiffDBName), noResults, nil) ct := vdenv.newController(t, controllerQR) wd, err := newWorkflowDiffer(ct, vdiffenv.opts, collations.MySQL8()) require.NoError(t, err) @@ -302,6 +304,118 @@ func TestReconcileExtraRows(t *testing.T) { }) } +func TestReconcileReferenceTables(t *testing.T) { + ctx := t.Context() + vdenv := newTestVDiffEnv(t) + defer vdenv.close() + UUID := uuid.New() + controllerQR := sqltypes.MakeTestResult(sqltypes.MakeTestFields( + vdiffTestCols, + vdiffTestColTypes, + ), + fmt.Sprintf("1|%s|%s|%s|%s|%s|%s|%s|", UUID, vdiffenv.workflow, tstenv.KeyspaceName, tstenv.ShardName, vdiffDBName, PendingState, optionsJS), + ) + + vdiffenv.dbClient.ExpectRequest("select * from _vt.vdiff where id = 1 and db_name = "+encodeString(vdiffDBName), noResults, nil) + ct := vdenv.newController(t, controllerQR) + ct.sourceKeyspace = tstenv.KeyspaceName + wd, err := newWorkflowDiffer(ct, vdiffenv.opts, collations.MySQL8()) + require.NoError(t, err) + + // Create VSchema for the source keyspace with a reference table. + err = tstenv.TopoServ.EnsureVSchema(ctx, tstenv.KeyspaceName) + require.NoError(t, err) + sourceVS := &vschemapb.Keyspace{ + Tables: map[string]*vschemapb.Table{ + "ref_table": { + Type: "reference", + }, + }, + } + err = tstenv.TopoServ.SaveVSchema(ctx, &topo.KeyspaceVSchemaInfo{ + Name: tstenv.KeyspaceName, + Keyspace: sourceVS, + }) + require.NoError(t, err) + + t.Run("division by zero with zero matching rows - source side", func(t *testing.T) { + dr := &DiffReport{ + TableName: "ref_table", + ProcessedRows: 10, + MatchingRows: 0, + MismatchedRows: 0, // Must be 0 to enter reconciliation logic + ExtraRowsSource: 10, + ExtraRowsSourceDiffs: []*RowDiff{{Row: map[string]string{"id": "1"}}}, + ExtraRowsTarget: 0, + } + + err := wd.reconcileReferenceTables(dr) + require.NoError(t, err) + + // Values should remain unchanged since MatchingRows is 0. + require.Equal(t, int64(10), dr.ExtraRowsSource) + require.Equal(t, int64(0), dr.ExtraRowsTarget) + }) + + t.Run("division by zero with zero matching rows - target side", func(t *testing.T) { + dr := &DiffReport{ + TableName: "ref_table", + ProcessedRows: 10, + MatchingRows: 0, + MismatchedRows: 0, // Must be 0 to enter reconciliation logic + ExtraRowsSource: 0, + ExtraRowsTarget: 10, + ExtraRowsTargetDiffs: []*RowDiff{{Row: map[string]string{"id": "1"}}}, + } + + err := wd.reconcileReferenceTables(dr) + require.NoError(t, err) + + // Values should remain unchanged since MatchingRows is 0. + require.Equal(t, int64(0), dr.ExtraRowsSource) + require.Equal(t, int64(10), dr.ExtraRowsTarget) + }) + + t.Run("reference table with positive matching rows - works correctly", func(t *testing.T) { + dr := &DiffReport{ + TableName: "ref_table", + ProcessedRows: 15, + MatchingRows: 5, + MismatchedRows: 0, + ExtraRowsSource: 10, // 10 % 5 = 0, so it's a multiple. + ExtraRowsSourceDiffs: []*RowDiff{{Row: map[string]string{"id": "1"}}}, + ExtraRowsTarget: 0, + } + + err := wd.reconcileReferenceTables(dr) + require.NoError(t, err) + + // ExtraRowsSource should be cleared since it's a multiple of MatchingRows. + require.Equal(t, int64(0), dr.ExtraRowsSource) + require.Equal(t, 0, len(dr.ExtraRowsSourceDiffs)) + }) + + t.Run("mismatched rows - reconciliation skipped entirely", func(t *testing.T) { + // With mismatched rows, reconciliation is skipped, so no VSchema access. + dr := &DiffReport{ + TableName: "ref_table", + ProcessedRows: 10, + MatchingRows: 0, + MismatchedRows: 5, // Non-zero means early return, no VSchema access + ExtraRowsSource: 10, + ExtraRowsSourceDiffs: []*RowDiff{{Row: map[string]string{"id": "1"}}}, + ExtraRowsTarget: 0, + } + + err := wd.reconcileReferenceTables(dr) + require.NoError(t, err) + + // Values should remain unchanged. + require.Equal(t, int64(10), dr.ExtraRowsSource) + require.Equal(t, int64(0), dr.ExtraRowsTarget) + }) +} + func TestBuildPlanSuccess(t *testing.T) { vdenv := newTestVDiffEnv(t) defer vdenv.close() @@ -313,7 +427,7 @@ func TestBuildPlanSuccess(t *testing.T) { fmt.Sprintf("1|%s|%s|%s|%s|%s|%s|%s|", UUID, vdiffenv.workflow, tstenv.KeyspaceName, tstenv.ShardName, vdiffDBName, PendingState, optionsJS), ) - vdiffenv.dbClient.ExpectRequest("select * from _vt.vdiff where id = 1", noResults, nil) + vdiffenv.dbClient.ExpectRequest("select * from _vt.vdiff where id = 1 and db_name = "+encodeString(vdiffDBName), noResults, nil) ct := vdenv.newController(t, controllerQR) ct.sources = map[string]*migrationSource{ tstenv.ShardName: { @@ -961,7 +1075,7 @@ func TestBuildPlanFailure(t *testing.T) { ), fmt.Sprintf("1|%s|%s|%s|%s|%s|%s|%s|", UUID, vdiffenv.workflow, tstenv.KeyspaceName, tstenv.ShardName, vdiffDBName, PendingState, optionsJS), ) - vdiffenv.dbClient.ExpectRequest("select * from _vt.vdiff where id = 1", noResults, nil) + vdiffenv.dbClient.ExpectRequest("select * from _vt.vdiff where id = 1 and db_name = "+encodeString(vdiffDBName), noResults, nil) ct := vdenv.newController(t, controllerQR) testcases := []struct { input *binlogdatapb.Rule diff --git a/go/vt/vttablet/tabletmanager/vreplication/framework_test.go b/go/vt/vttablet/tabletmanager/vreplication/framework_test.go index 9f2647a8770..2a17768b2ad 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/framework_test.go +++ b/go/vt/vttablet/tabletmanager/vreplication/framework_test.go @@ -71,6 +71,7 @@ var ( vrepldb = "vrepl" globalDBQueries = make(chan string, 1000) lastMultiExecQuery = "" + lastMultiExecQueryMu sync.Mutex testForeignKeyQueries = false testSetForeignKeyQueries = false doNotLogDBQueries = false @@ -521,10 +522,18 @@ func (dbc *realDBClient) ExecuteFetchMulti(query string, maxrows int) ([]*sqltyp } results = append(results, qr) } + lastMultiExecQueryMu.Lock() lastMultiExecQuery = query + lastMultiExecQueryMu.Unlock() return results, nil } +func getLastMultiExecQuery() string { + lastMultiExecQueryMu.Lock() + defer lastMultiExecQueryMu.Unlock() + return lastMultiExecQuery +} + func (dbc *realDBClient) SupportsCapability(capability capabilities.FlavorCapability) (bool, error) { return dbc.conn.SupportsCapability(capability) } diff --git a/go/vt/vttablet/tabletmanager/vreplication/journal_test.go b/go/vt/vttablet/tabletmanager/vreplication/journal_test.go index 862f22ab564..b22b6f18fca 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/journal_test.go +++ b/go/vt/vttablet/tabletmanager/vreplication/journal_test.go @@ -74,7 +74,7 @@ func TestJournalOneToOne(t *testing.T) { fmt.Sprintf("delete from _vt.vreplication where id=%d", firstID), "commit", "/update _vt.vreplication set message='Picked source tablet.*", - "/update _vt.vreplication set state='Running', message='' where id.*", + "/update _vt.vreplication set state='Running', message=left\\('', 1000\\) where id.*", )) // Delete all vreplication streams. There should be only one, but we don't know its id. @@ -139,8 +139,8 @@ func TestJournalOneToMany(t *testing.T) { "commit", "/update _vt.vreplication set message='Picked source tablet.*", "/update _vt.vreplication set message='Picked source tablet.*", - "/update _vt.vreplication set state='Running', message='' where id.*", - "/update _vt.vreplication set state='Running', message='' where id.*", + "/update _vt.vreplication set state='Running', message=left\\('', 1000\\) where id.*", + "/update _vt.vreplication set state='Running', message=left\\('', 1000\\) where id.*", )) // Delete all vreplication streams. There should be only one, but we don't know its id. @@ -198,7 +198,7 @@ func TestJournalTablePresent(t *testing.T) { fmt.Sprintf("delete from _vt.vreplication where id=%d", firstID), "commit", "/update _vt.vreplication set message='Picked source tablet.*", - "/update _vt.vreplication set state='Running', message='' where id.*", + "/update _vt.vreplication set state='Running', message=left\\('', 1000\\) where id.*", )) // Delete all vreplication streams. There should be only one, but we don't know its id. @@ -307,7 +307,7 @@ func TestJournalTableMixed(t *testing.T) { defer execStatements(t, []string{"delete from _vt.resharding_journal"}) expectDBClientQueries(t, qh.Expect( - "/update _vt.vreplication set state='Stopped', message='unable to handle journal event: tables were partially matched' where id", + "/update _vt.vreplication set state='Stopped', message=left\\('unable to handle journal event: tables were partially matched', 1000\\) where id", )) // Delete all vreplication streams. There should be only one, but we don't know its id. diff --git a/go/vt/vttablet/tabletmanager/vreplication/replicator_plan_test.go b/go/vt/vttablet/tabletmanager/vreplication/replicator_plan_test.go index 09ace916f11..cdee6483ecc 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/replicator_plan_test.go +++ b/go/vt/vttablet/tabletmanager/vreplication/replicator_plan_test.go @@ -640,7 +640,7 @@ func TestBuildPlayerPlan(t *testing.T) { Filter: "select c1, * from t1", }}, }, - err: "failed to build table replication plan for t1 table: invalid expression: * in query: select c1, * from t1", + err: "failed to build table replication plan for t1 table: syntax error at position 13 in query: select c1, * from t1", }, { // no distinct in func input: &binlogdatapb.Filter{ diff --git a/go/vt/vttablet/tabletmanager/vreplication/vplayer_flaky_test.go b/go/vt/vttablet/tabletmanager/vreplication/vplayer_flaky_test.go index 07d5229ef34..7eb892c4151 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/vplayer_flaky_test.go +++ b/go/vt/vttablet/tabletmanager/vreplication/vplayer_flaky_test.go @@ -2086,7 +2086,7 @@ func TestPlayerDDL(t *testing.T) { expectDBClientQueries(t, qh.Expect( "alter table t1 add column val2 varchar(128)", "/update _vt.vreplication set message='error applying event: Duplicate", - "/update _vt.vreplication set state='Error', message='terminal error: error applying event: Duplicate", + "/update _vt.vreplication set state='Error', message=left\\('terminal error: error applying event: Duplicate", )) cancel() @@ -3634,7 +3634,6 @@ func TestPlayerBatchMode(t *testing.T) { require.LessOrEqual(t, len(stmt), maxBatchSize, "expected output statement is longer than the max batch size (%d): %s", maxBatchSize, stmt) } expectNontxQueries(t, output, recvTimeout) - time.Sleep(1 * time.Second) if tcase.table != "" { expectData(t, tcase.table, tcase.data) } @@ -3646,15 +3645,35 @@ func TestPlayerBatchMode(t *testing.T) { expectedBulkInserts += tcase.expectedBulkInserts expectedTrxBatchCommits++ // Should only ever be 1 per test case expectedTrxBatchExecs += tcase.expectedNonCommitBatches - if tcase.expectedInLastBatch != "" { // We expect the trx to be split - require.Regexpf(t, regexp.MustCompile(fmt.Sprintf(trxLastBatchExpectRE, regexp.QuoteMeta(tcase.expectedInLastBatch))), lastMultiExecQuery, "Unexpected batch statement: %s", lastMultiExecQuery) + + // Poll until the batch query and stats counters are updated. + // These are set asynchronously on the vplayer goroutine after + // the commit completes, so we poll rather than using a fixed sleep. + var batchRE *regexp.Regexp + if tcase.expectedInLastBatch != "" { + batchRE = regexp.MustCompile(fmt.Sprintf(trxLastBatchExpectRE, regexp.QuoteMeta(tcase.expectedInLastBatch))) } else { - require.Regexpf(t, regexp.MustCompile(fmt.Sprintf(trxFullBatchExpectRE, regexp.QuoteMeta(strings.Join(tcase.output, ";")))), lastMultiExecQuery, "Unexpected batch statement: %s", lastMultiExecQuery) + batchRE = regexp.MustCompile(fmt.Sprintf(trxFullBatchExpectRE, regexp.QuoteMeta(strings.Join(tcase.output, ";")))) } - require.Equal(t, expectedBulkInserts, stats.BulkQueryCount.Counts()["insert"], "expected %d bulk inserts but got %d", expectedBulkInserts, stats.BulkQueryCount.Counts()["insert"]) - require.Equal(t, expectedBulkDeletes, stats.BulkQueryCount.Counts()["delete"], "expected %d bulk deletes but got %d", expectedBulkDeletes, stats.BulkQueryCount.Counts()["delete"]) - require.Equal(t, expectedTrxBatchExecs, stats.TrxQueryBatchCount.Counts()["without_commit"], "expected %d trx batch execs but got %d", expectedTrxBatchExecs, stats.TrxQueryBatchCount.Counts()["without_commit"]) - require.Equal(t, expectedTrxBatchCommits, stats.TrxQueryBatchCount.Counts()["with_commit"], "expected %d trx batch commits but got %d", expectedTrxBatchCommits, stats.TrxQueryBatchCount.Counts()["with_commit"]) + require.Eventually(t, func() bool { + got := getLastMultiExecQuery() + if !batchRE.MatchString(got) { + return false + } + if stats.BulkQueryCount.Counts()["insert"] != expectedBulkInserts { + return false + } + if stats.BulkQueryCount.Counts()["delete"] != expectedBulkDeletes { + return false + } + if stats.TrxQueryBatchCount.Counts()["without_commit"] != expectedTrxBatchExecs { + return false + } + if stats.TrxQueryBatchCount.Counts()["with_commit"] != expectedTrxBatchCommits { + return false + } + return true + }, 10*time.Second, 100*time.Millisecond, "batch query or stats mismatch after timeout; lastMultiExecQuery: %s", getLastMultiExecQuery()) }) } } diff --git a/go/vt/vttablet/tabletmanager/vreplication/vreplicator.go b/go/vt/vttablet/tabletmanager/vreplication/vreplicator.go index 39e705bd301..83bca9604e3 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/vreplicator.go +++ b/go/vt/vttablet/tabletmanager/vreplication/vreplicator.go @@ -508,7 +508,7 @@ func (vr *vreplicator) setState(state binlogdatapb.VReplicationWorkflowState, me }) } vr.stats.State.Store(state.String()) - query := fmt.Sprintf("update _vt.vreplication set state=%v, message=%v where id=%v", encodeString(state.String()), encodeString(binlogplayer.MessageTruncate(message)), vr.id) + query := fmt.Sprintf("update _vt.vreplication set state=%v, message=left(%v, 1000) where id=%v", encodeString(state.String()), encodeString(binlogplayer.MessageTruncate(message)), vr.id) // If we're batching a transaction, then include the state update // in the current transaction batch. if vr.dbClient.InTransaction && vr.dbClient.maxBatchSize > 0 { diff --git a/go/vt/vttablet/tabletserver/tabletserver_test.go b/go/vt/vttablet/tabletserver/tabletserver_test.go index 23a65deafd1..11f28deb0f3 100644 --- a/go/vt/vttablet/tabletserver/tabletserver_test.go +++ b/go/vt/vttablet/tabletserver/tabletserver_test.go @@ -221,7 +221,9 @@ func TestTabletServerRedoLogIsKeptBetweenRestarts(t *testing.T) { db.AddQuery(tpc.readAllRedo, &sqltypes.Result{}) turnOnTxEngine() - assert.Empty(t, tsv.te.preparedPool.conns, "tsv.te.preparedPool.conns") + require.EventuallyWithT(t, func(c *assert.CollectT) { + require.Empty(c, tsv.te.preparedPool.conns, "tsv.te.preparedPool.conns") + }, 5*time.Second, 10*time.Millisecond, "prepared transactions should be empty initially") turnOffTxEngine() db.AddQuery(tpc.readAllRedo, &sqltypes.Result{ @@ -241,14 +243,18 @@ func TestTabletServerRedoLogIsKeptBetweenRestarts(t *testing.T) { }}, }) turnOnTxEngine() - assert.EqualValues(t, 1, len(tsv.te.preparedPool.conns), "len(tsv.te.preparedPool.conns)") + require.EventuallyWithT(t, func(c *assert.CollectT) { + require.EqualValues(c, 1, len(tsv.te.preparedPool.conns), "len(tsv.te.preparedPool.conns)") + }, 5*time.Second, 10*time.Millisecond, "prepared transactions should be loaded from redo log") got := tsv.te.preparedPool.conns["dtid0"].TxProperties().Queries want := []tx.Query{{ Sql: "update test_table set `name` = 2 where pk = 1 limit 10001", Tables: []string{"test_table"}}} utils.MustMatch(t, want, got, "Prepared queries") turnOffTxEngine() - assert.Empty(t, tsv.te.preparedPool.conns, "tsv.te.preparedPool.conns") + require.EventuallyWithT(t, func(c *assert.CollectT) { + require.Empty(c, tsv.te.preparedPool.conns, "tsv.te.preparedPool.conns") + }, 5*time.Second, 10*time.Millisecond, "prepared transactions should be cleared when transaction engine is turned off") tsv.te.txPool.scp.lastID.Store(1) // Ensure we continue past errors. @@ -281,7 +287,9 @@ func TestTabletServerRedoLogIsKeptBetweenRestarts(t *testing.T) { }}, }) turnOnTxEngine() - assert.EqualValues(t, 1, len(tsv.te.preparedPool.conns), "len(tsv.te.preparedPool.conns)") + require.EventuallyWithT(t, func(c *assert.CollectT) { + require.EqualValues(c, 1, len(tsv.te.preparedPool.conns), "len(tsv.te.preparedPool.conns)") + }, 5*time.Second, 10*time.Millisecond, "only valid prepared transactions should be loaded from redo log") got = tsv.te.preparedPool.conns["a:b:10"].TxProperties().Queries want = []tx.Query{{ Sql: "update test_table set `name` = 2 where pk = 1 limit 10001", @@ -293,9 +301,13 @@ func TestTabletServerRedoLogIsKeptBetweenRestarts(t *testing.T) { } utils.MustMatch(t, tsv.te.preparedPool.reserved, wantFailed, fmt.Sprintf("Failed dtids: %v, want %v", tsv.te.preparedPool.reserved, wantFailed)) // Verify last id got adjusted. - assert.EqualValues(t, 20, tsv.te.txPool.scp.lastID.Load(), "tsv.te.txPool.lastID.Get()") + require.EventuallyWithT(t, func(c *assert.CollectT) { + require.EqualValues(c, 20, tsv.te.txPool.scp.lastID.Load(), "tsv.te.txPool.lastID.Get()") + }, 5*time.Second, 10*time.Millisecond, "lastID should be adjusted to the max id in redo log") turnOffTxEngine() - assert.Empty(t, tsv.te.preparedPool.conns, "tsv.te.preparedPool.conns") + require.EventuallyWithT(t, func(c *assert.CollectT) { + require.Empty(c, tsv.te.preparedPool.conns, "tsv.te.preparedPool.conns") + }, 5*time.Second, 10*time.Millisecond, "prepared transactions should be cleared when transaction engine is turned off") } func TestTabletServerCreateTransaction(t *testing.T) { diff --git a/go/vt/vttablet/tabletserver/throttle/base/self_metric_mysqld.go b/go/vt/vttablet/tabletserver/throttle/base/self_metric_mysqld.go index 321837d86b4..e0faa6cd6d5 100644 --- a/go/vt/vttablet/tabletserver/throttle/base/self_metric_mysqld.go +++ b/go/vt/vttablet/tabletserver/throttle/base/self_metric_mysqld.go @@ -92,6 +92,9 @@ func getMysqlHostMetric(ctx context.Context, params *SelfMetricReadParams, mysql if resp == nil { return metric.WithError(ErrNoResultYet) } + if resp.HostMetrics == nil || resp.HostMetrics.Metrics == nil { + return metric.WithError(ErrNoSuchMetric) + } mysqlMetric := resp.HostMetrics.Metrics[mysqlHostMetricName] if mysqlMetric == nil { return metric.WithError(ErrNoSuchMetric) diff --git a/go/vt/vttablet/tabletserver/vstreamer/planbuilder_test.go b/go/vt/vttablet/tabletserver/vstreamer/planbuilder_test.go index 8f4cac52408..a9de7f05725 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/planbuilder_test.go +++ b/go/vt/vttablet/tabletserver/vstreamer/planbuilder_test.go @@ -730,7 +730,7 @@ func TestPlanBuilder(t *testing.T) { // analyzeExpr tests. inTable: t1, inRule: &binlogdatapb.Rule{Match: "t1", Filter: "select id, * from t1"}, - outErr: `unsupported: *`, + outErr: `syntax error at position 13`, }, { inTable: t1, inRule: &binlogdatapb.Rule{Match: "t1", Filter: "select none from t1"}, diff --git a/go/vt/vttablet/tabletserver/vstreamer/snapshot_conn.go b/go/vt/vttablet/tabletserver/vstreamer/snapshot_conn.go index ee141ce9859..45fd2d5af8d 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/snapshot_conn.go +++ b/go/vt/vttablet/tabletserver/vstreamer/snapshot_conn.go @@ -36,6 +36,9 @@ import ( vttablet "vitess.io/vitess/go/vt/vttablet/common" ) +// snapshotLockWaitTimeout is the lock_wait_timeout to use when attempting to start a snapshot. +var snapshotLockWaitTimeout = 30 * time.Second + // snapshotConn is wrapper on mysql.Conn capable of // reading a table along with a GTID snapshot. type snapshotConn struct { @@ -109,6 +112,12 @@ func (conn *snapshotConn) startSnapshot(ctx context.Context, table string) (gtid tableName := sqlparser.String(sqlparser.NewIdentifierCS(table)) + // Avoid waiting indefinitely when table metadata locks are held by another transaction. + lockWaitTimeoutSeconds := int(snapshotLockWaitTimeout.Seconds()) + if _, err := lockConn.ExecuteFetch(fmt.Sprintf("set session lock_wait_timeout = %d", lockWaitTimeoutSeconds), 1, false); err != nil { + return "", vterrors.Wrapf(err, "startSnapshot: failed to set session lock_wait_timeout = %d for table %s", lockWaitTimeoutSeconds, tableName) + } + if _, err := lockConn.ExecuteFetch(fmt.Sprintf("lock tables %s read", tableName), 1, false); err != nil { log.Warningf("Error locking table %s to read: %v", tableName, err) return "", err diff --git a/go/vt/vttablet/tabletserver/vstreamer/snapshot_conn_test.go b/go/vt/vttablet/tabletserver/vstreamer/snapshot_conn_test.go index cc0899bc14b..0b5eaf82500 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/snapshot_conn_test.go +++ b/go/vt/vttablet/tabletserver/vstreamer/snapshot_conn_test.go @@ -18,7 +18,9 @@ package vstreamer import ( "context" + "fmt" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -59,3 +61,49 @@ func TestStartSnapshot(t *testing.T) { require.NoError(t, err) assert.Equal(t, wantqr, qr) } + +// TestStartSnapshotLock validates startSnapshot does not hang indefinitely when waiting on a metadata lock. +func TestStartSnapshotLock(t *testing.T) { + if testing.Short() { + t.Skip() + } + + const tableName = "t1_lock_wait_timeout" + const shortLockWaitTimeout = time.Second + + // Seed one row so the table can be locked and queried. + execStatements(t, []string{ + fmt.Sprintf("create table %s(id int, val varbinary(128), primary key(id))", tableName), + fmt.Sprintf("insert into %s values (1, 'aaa')", tableName), + }) + t.Cleanup(func() { execStatements(t, []string{"drop table " + tableName}) }) + + // Shorten the configured snapshot lock wait timeout for this test only. + originalLockWaitTimeout := snapshotLockWaitTimeout + snapshotLockWaitTimeout = shortLockWaitTimeout + t.Cleanup(func() { snapshotLockWaitTimeout = originalLockWaitTimeout }) + + ctx := t.Context() + + // Open a second connection that will hold the metadata lock. + lockHolderConn, err := mysqlConnect(ctx, env.TabletEnv.Config().DB.AppWithDB()) + require.NoError(t, err) + t.Cleanup(func() { lockHolderConn.Close() }) + + _, err = lockHolderConn.ExecuteFetch("begin", 1, false) + require.NoError(t, err) + + _, err = lockHolderConn.ExecuteFetch(fmt.Sprintf("update %s set val = 'blocked' where id = 1", tableName), 1, false) + require.NoError(t, err) + + conn, err := snapshotConnect(ctx, env.TabletEnv.Config().DB.AppWithDB()) + require.NoError(t, err) + t.Cleanup(func() { conn.Close() }) + + // Attempt to start the snapshot while the metadata lock is still held. + _, err = conn.startSnapshot(ctx, tableName) + + // Confirm we fail with the expected lock wait timeout error. + require.Error(t, err) + require.ErrorContains(t, err, "Lock wait timeout exceeded") +} diff --git a/go/vt/vttablet/tmclient/rpc_client_api.go b/go/vt/vttablet/tmclient/rpc_client_api.go index 7ce4c7f0bf4..32f788bea1a 100644 --- a/go/vt/vttablet/tmclient/rpc_client_api.go +++ b/go/vt/vttablet/tmclient/rpc_client_api.go @@ -248,7 +248,7 @@ type TabletManagerClient interface { // DemotePrimary tells the soon-to-be-former primary it's going to change, // and it should go read-only and return its current position. - DemotePrimary(ctx context.Context, tablet *topodatapb.Tablet) (*replicationdatapb.PrimaryStatus, error) + DemotePrimary(ctx context.Context, tablet *topodatapb.Tablet, force bool) (*replicationdatapb.PrimaryStatus, error) // UndoDemotePrimary reverts all changes made by DemotePrimary // To be used if we are unable to promote the chosen new primary diff --git a/go/vt/vttablet/tmrpctest/test_tm_rpc.go b/go/vt/vttablet/tmrpctest/test_tm_rpc.go index 0ec380882cc..a6f6133431c 100644 --- a/go/vt/vttablet/tmrpctest/test_tm_rpc.go +++ b/go/vt/vttablet/tmrpctest/test_tm_rpc.go @@ -26,6 +26,7 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" @@ -580,6 +581,13 @@ func tmRPCTestExecuteHook(ctx context.Context, t *testing.T, client tmclient.Tab compareError(t, "ExecuteHook", err, hr, testExecuteHookHookResult) } +func tmRPCTestExecuteHookInvalidName(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { + for _, name := range []string{"", "../etc/passwd", "/bin/ls"} { + _, err := client.ExecuteHook(ctx, tablet, &hook.Hook{Name: name}) + assert.ErrorContains(t, err, "hook name must be a basename") + } +} + func tmRPCTestExecuteHookPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { _, err := client.ExecuteHook(ctx, tablet, testExecuteHookHook) expectHandleRPCPanic(t, "ExecuteHook", true /*verbose*/, err) @@ -1236,7 +1244,7 @@ func tmRPCTestInitReplicaPanic(ctx context.Context, t *testing.T, client tmclien expectHandleRPCPanic(t, "InitReplica", true /*verbose*/, err) } -func (fra *fakeRPCTM) DemotePrimary(ctx context.Context) (*replicationdatapb.PrimaryStatus, error) { +func (fra *fakeRPCTM) DemotePrimary(ctx context.Context, force bool) (*replicationdatapb.PrimaryStatus, error) { if fra.panics { panic(fmt.Errorf("test-triggered panic")) } @@ -1244,12 +1252,12 @@ func (fra *fakeRPCTM) DemotePrimary(ctx context.Context) (*replicationdatapb.Pri } func tmRPCTestDemotePrimary(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { - PrimaryStatus, err := client.DemotePrimary(ctx, tablet) + PrimaryStatus, err := client.DemotePrimary(ctx, tablet, false) compareError(t, "DemotePrimary", err, PrimaryStatus.Position, testPrimaryStatus.Position) } func tmRPCTestDemotePrimaryPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { - _, err := client.DemotePrimary(ctx, tablet) + _, err := client.DemotePrimary(ctx, tablet, false) expectHandleRPCPanic(t, "DemotePrimary", true /*verbose*/, err) } @@ -1554,6 +1562,7 @@ func Run(t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.T tmRPCTestChangeType(ctx, t, client, tablet) tmRPCTestSleep(ctx, t, client, tablet) tmRPCTestExecuteHook(ctx, t, client, tablet) + tmRPCTestExecuteHookInvalidName(ctx, t, client, tablet) tmRPCTestRefreshState(ctx, t, client, tablet) tmRPCTestRunHealthCheck(ctx, t, client, tablet) tmRPCTestReloadSchema(ctx, t, client, tablet) diff --git a/go/vt/wrangler/testlib/planned_reparent_shard_test.go b/go/vt/wrangler/testlib/planned_reparent_shard_test.go index f160ddfa32b..585078b1a34 100644 --- a/go/vt/wrangler/testlib/planned_reparent_shard_test.go +++ b/go/vt/wrangler/testlib/planned_reparent_shard_test.go @@ -23,6 +23,7 @@ import ( "time" "vitess.io/vitess/go/mysql/replication" + "vitess.io/vitess/go/mysql/sqlerror" "vitess.io/vitess/go/vt/mysqlctl" "vitess.io/vitess/go/vt/vtctl/reparentutil/policy" "vitess.io/vitess/go/vt/vtenv" @@ -263,8 +264,10 @@ func TestPlannedReparentShardNoError(t *testing.T) { defer goodReplica2.StopActionLoop(t) // run PlannedReparentShard - err := vp.Run([]string{"PlannedReparentShard", "--wait_replicas_timeout", "10s", "--keyspace_shard", newPrimary.Tablet.Keyspace + "/" + newPrimary.Tablet.Shard, "--new_primary", - topoproto.TabletAliasString(newPrimary.Tablet.Alias)}) + err := vp.Run([]string{ + "PlannedReparentShard", "--wait_replicas_timeout", "10s", "--keyspace_shard", newPrimary.Tablet.Keyspace + "/" + newPrimary.Tablet.Shard, "--new_primary", + topoproto.TabletAliasString(newPrimary.Tablet.Alias), + }) require.NoError(t, err) // check what was run @@ -596,79 +599,90 @@ func TestPlannedReparentShardWaitForPositionTimeout(t *testing.T) { } func TestPlannedReparentShardRelayLogError(t *testing.T) { - delay := discovery.GetTabletPickerRetryDelay() - defer func() { - discovery.SetTabletPickerRetryDelay(delay) - }() - discovery.SetTabletPickerRetryDelay(5 * time.Millisecond) - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - ts := memorytopo.NewServer(ctx, "cell1") - wr := wrangler.New(vtenv.NewTestEnv(), logutil.NewConsoleLogger(), ts, tmclient.NewTabletManagerClient()) - vp := NewVtctlPipe(ctx, t, ts) - defer vp.Close() - - // Create a primary, a couple good replicas - primary := NewFakeTablet(t, wr, "cell1", 0, topodatapb.TabletType_PRIMARY, nil) - goodReplica1 := NewFakeTablet(t, wr, "cell1", 2, topodatapb.TabletType_REPLICA, nil) - - // old primary - primary.FakeMysqlDaemon.ReadOnly = false - primary.FakeMysqlDaemon.Replicating = false - primary.FakeMysqlDaemon.ReplicationStatusError = mysql.ErrNotReplica - primary.FakeMysqlDaemon.SetPrimaryPositionLocked(replication.Position{ - GTIDSet: replication.MariadbGTIDSet{ - 7: replication.MariadbGTID{ - Domain: 7, - Server: 123, - Sequence: 990, - }, + relayErrors := []struct { + name string + err error + }{ + { + name: "relay log info", + err: sqlerror.NewSQLError(sqlerror.ERReplicaRelayLogInfoInitRepository, sqlerror.SSUnknownSQLState, "Replica failed to initialize relay log info structure from the repository"), + }, + { + name: "master info", + err: sqlerror.NewSQLError(sqlerror.ERMasterInfo, sqlerror.SSUnknownSQLState, "Could not initialize master info structure; more error messages can be found in the MySQL error log"), + }, + { + name: "connection metadata", + err: sqlerror.NewSQLError(sqlerror.ERReplicaConnectionMetadataInitRepository, sqlerror.SSUnknownSQLState, "Replica failed to initialize connection metadata structure from the repository"), }, - }) - primary.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ - "SUBINSERT INTO _vt.reparent_journal (time_created_ns, action_name, primary_alias, replication_position) VALUES", } - primary.StartActionLoop(t, wr) - defer primary.StopActionLoop(t) - primary.TM.QueryServiceControl.(*tabletservermock.Controller).SetQueryServiceEnabledForTests(true) - // goodReplica1 is replicating - goodReplica1.FakeMysqlDaemon.ReadOnly = true - goodReplica1.FakeMysqlDaemon.Replicating = true - goodReplica1.FakeMysqlDaemon.SetReplicationSourceInputs = append(goodReplica1.FakeMysqlDaemon.SetReplicationSourceInputs, topoproto.MysqlAddr(primary.Tablet)) - goodReplica1.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ - // These 3 statements come from tablet startup - "STOP REPLICA", - "FAKE SET SOURCE", - "START REPLICA", - // simulate error that will trigger a call to RestartReplication - "STOP REPLICA", - "RESET REPLICA", - "START REPLICA", - "START REPLICA", + for _, relayError := range relayErrors { + t.Run(relayError.name, func(t *testing.T) { + delay := discovery.GetTabletPickerRetryDelay() + defer func() { + discovery.SetTabletPickerRetryDelay(delay) + }() + discovery.SetTabletPickerRetryDelay(5 * time.Millisecond) + + ctx := t.Context() + ts := memorytopo.NewServer(ctx, "cell1") + wr := wrangler.New(vtenv.NewTestEnv(), logutil.NewConsoleLogger(), ts, tmclient.NewTabletManagerClient()) + vp := NewVtctlPipe(ctx, t, ts) + defer vp.Close() + + // Create a primary, a couple good replicas + primary := NewFakeTablet(t, wr, "cell1", 0, topodatapb.TabletType_PRIMARY, nil) + goodReplica1 := NewFakeTablet(t, wr, "cell1", 2, topodatapb.TabletType_REPLICA, nil) + + // old primary + primary.FakeMysqlDaemon.ReadOnly = false + primary.FakeMysqlDaemon.Replicating = false + primary.FakeMysqlDaemon.ReplicationStatusError = mysql.ErrNotReplica + primary.FakeMysqlDaemon.SetPrimaryPositionLocked(replication.Position{ + GTIDSet: replication.MariadbGTIDSet{ + 7: replication.MariadbGTID{ + Domain: 7, + Server: 123, + Sequence: 990, + }, + }, + }) + primary.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ + "SUBINSERT INTO _vt.reparent_journal (time_created_ns, action_name, primary_alias, replication_position) VALUES", + } + primary.StartActionLoop(t, wr) + defer primary.StopActionLoop(t) + primary.TM.QueryServiceControl.(*tabletservermock.Controller).SetQueryServiceEnabledForTests(true) + + // goodReplica1 is replicating + goodReplica1.FakeMysqlDaemon.ReadOnly = true + goodReplica1.FakeMysqlDaemon.Replicating = true + goodReplica1.FakeMysqlDaemon.SetReplicationSourceInputs = append(goodReplica1.FakeMysqlDaemon.SetReplicationSourceInputs, topoproto.MysqlAddr(primary.Tablet)) + goodReplica1.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ + // These 3 statements come from tablet startup + "STOP REPLICA", + "FAKE SET SOURCE", + "START REPLICA", + } + goodReplica1.StartActionLoop(t, wr) + goodReplica1.FakeMysqlDaemon.StopReplicationError = relayError.err + defer goodReplica1.StopActionLoop(t) + + // run PlannedReparentShard + err := vp.Run([]string{ + "PlannedReparentShard", "--wait_replicas_timeout", "10s", "--keyspace_shard", primary.Tablet.Keyspace + "/" + primary.Tablet.Shard, "--new_primary", + topoproto.TabletAliasString(primary.Tablet.Alias), + }) + require.ErrorContains(t, err, "failed to SetReplicationSource") + require.ErrorContains(t, err, relayError.err.Error()) + // check what was run + err = primary.FakeMysqlDaemon.CheckSuperQueryList() + require.NoError(t, err) + err = goodReplica1.FakeMysqlDaemon.CheckSuperQueryList() + require.NoError(t, err) + }) } - goodReplica1.StartActionLoop(t, wr) - goodReplica1.FakeMysqlDaemon.StopReplicationError = errors.New("Replica failed to initialize relay log info structure from the repository") - defer goodReplica1.StopActionLoop(t) - - // run PlannedReparentShard - err := vp.Run([]string{"PlannedReparentShard", "--wait_replicas_timeout", "10s", "--keyspace_shard", primary.Tablet.Keyspace + "/" + primary.Tablet.Shard, "--new_primary", - topoproto.TabletAliasString(primary.Tablet.Alias)}) - require.NoError(t, err) - // check what was run - err = primary.FakeMysqlDaemon.CheckSuperQueryList() - require.NoError(t, err) - err = goodReplica1.FakeMysqlDaemon.CheckSuperQueryList() - require.NoError(t, err) - - assert.False(t, primary.FakeMysqlDaemon.ReadOnly, "primary.FakeMysqlDaemon.ReadOnly set") - assert.True(t, goodReplica1.FakeMysqlDaemon.ReadOnly, "goodReplica1.FakeMysqlDaemon.ReadOnly not set") - assert.True(t, primary.TM.QueryServiceControl.IsServing(), "primary...QueryServiceControl not serving") - - // verify the old primary was told to start replicating (and not - // the replica that wasn't replicating in the first place) - assert.True(t, goodReplica1.FakeMysqlDaemon.Replicating, "goodReplica1.FakeMysqlDaemon.Replicating not set") } // TestPlannedReparentShardRelayLogErrorStartReplication is similar to @@ -676,86 +690,109 @@ func TestPlannedReparentShardRelayLogError(t *testing.T) { // is not replicating to start with (IO_Thread is not running) and we // simulate an error from the attempt to start replication func TestPlannedReparentShardRelayLogErrorStartReplication(t *testing.T) { - delay := discovery.GetTabletPickerRetryDelay() - defer func() { - discovery.SetTabletPickerRetryDelay(delay) - }() - discovery.SetTabletPickerRetryDelay(5 * time.Millisecond) - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - ts := memorytopo.NewServer(ctx, "cell1") - wr := wrangler.New(vtenv.NewTestEnv(), logutil.NewConsoleLogger(), ts, tmclient.NewTabletManagerClient()) - vp := NewVtctlPipe(ctx, t, ts) - defer vp.Close() - - // Create a primary, a couple good replicas - primary := NewFakeTablet(t, wr, "cell1", 0, topodatapb.TabletType_PRIMARY, nil) - goodReplica1 := NewFakeTablet(t, wr, "cell1", 2, topodatapb.TabletType_REPLICA, nil) - reparenttestutil.SetKeyspaceDurability(context.Background(), t, ts, "test_keyspace", policy.DurabilitySemiSync) - - // old primary - primary.FakeMysqlDaemon.ReadOnly = false - primary.FakeMysqlDaemon.Replicating = false - primary.FakeMysqlDaemon.ReplicationStatusError = mysql.ErrNotReplica - primary.FakeMysqlDaemon.SetPrimaryPositionLocked(replication.Position{ - GTIDSet: replication.MariadbGTIDSet{ - 7: replication.MariadbGTID{ - Domain: 7, - Server: 123, - Sequence: 990, - }, + relayErrors := []struct { + name string + err error + }{ + { + name: "relay log info", + err: sqlerror.NewSQLError(sqlerror.ERReplicaRelayLogInfoInitRepository, sqlerror.SSUnknownSQLState, "Replica failed to initialize relay log info structure from the repository"), + }, + { + name: "master info", + err: sqlerror.NewSQLError(sqlerror.ERMasterInfo, sqlerror.SSUnknownSQLState, "Could not initialize master info structure; more error messages can be found in the MySQL error log"), + }, + { + name: "connection metadata", + err: sqlerror.NewSQLError(sqlerror.ERReplicaConnectionMetadataInitRepository, sqlerror.SSUnknownSQLState, "Replica failed to initialize connection metadata structure from the repository"), }, - }) - primary.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ - "SUBINSERT INTO _vt.reparent_journal (time_created_ns, action_name, primary_alias, replication_position) VALUES", } - primary.StartActionLoop(t, wr) - defer primary.StopActionLoop(t) - primary.TM.QueryServiceControl.(*tabletservermock.Controller).SetQueryServiceEnabledForTests(true) - // goodReplica1 is not replicating - goodReplica1.FakeMysqlDaemon.ReadOnly = true - goodReplica1.FakeMysqlDaemon.Replicating = true - goodReplica1.FakeMysqlDaemon.IOThreadRunning = false - goodReplica1.FakeMysqlDaemon.SetReplicationSourceInputs = append(goodReplica1.FakeMysqlDaemon.SetReplicationSourceInputs, topoproto.MysqlAddr(primary.Tablet)) - goodReplica1.FakeMysqlDaemon.CurrentSourceHost = primary.Tablet.MysqlHostname - goodReplica1.FakeMysqlDaemon.CurrentSourcePort = primary.Tablet.MysqlPort - goodReplica1.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ - // simulate error that will trigger a call to RestartReplication - // These 3 statements come from tablet startup - "STOP REPLICA", - "FAKE SET SOURCE", - "START REPLICA", - // In SetReplicationSource, we find that the source host and port was already set correctly, - // So we try to stop and start replication. The first STOP REPLICA comes from there - "STOP REPLICA", - // During the START REPLICA call, we find a relay log error, so we try to restart replication. - "STOP REPLICA", - "RESET REPLICA", - "START REPLICA", + for _, relayError := range relayErrors { + t.Run(relayError.name, func(t *testing.T) { + delay := discovery.GetTabletPickerRetryDelay() + defer func() { + discovery.SetTabletPickerRetryDelay(delay) + }() + discovery.SetTabletPickerRetryDelay(5 * time.Millisecond) + + ctx := t.Context() + ts := memorytopo.NewServer(ctx, "cell1") + wr := wrangler.New(vtenv.NewTestEnv(), logutil.NewConsoleLogger(), ts, tmclient.NewTabletManagerClient()) + vp := NewVtctlPipe(ctx, t, ts) + defer vp.Close() + + // Create a primary, a couple good replicas + primary := NewFakeTablet(t, wr, "cell1", 0, topodatapb.TabletType_PRIMARY, nil) + goodReplica1 := NewFakeTablet(t, wr, "cell1", 2, topodatapb.TabletType_REPLICA, nil) + reparenttestutil.SetKeyspaceDurability(t.Context(), t, ts, "test_keyspace", policy.DurabilitySemiSync) + + // old primary + primary.FakeMysqlDaemon.ReadOnly = false + primary.FakeMysqlDaemon.Replicating = false + primary.FakeMysqlDaemon.ReplicationStatusError = mysql.ErrNotReplica + primary.FakeMysqlDaemon.SetPrimaryPositionLocked(replication.Position{ + GTIDSet: replication.MariadbGTIDSet{ + 7: replication.MariadbGTID{ + Domain: 7, + Server: 123, + Sequence: 990, + }, + }, + }) + primary.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ + "SUBINSERT INTO _vt.reparent_journal (time_created_ns, action_name, primary_alias, replication_position) VALUES", + } + primary.StartActionLoop(t, wr) + defer primary.StopActionLoop(t) + primary.TM.QueryServiceControl.(*tabletservermock.Controller).SetQueryServiceEnabledForTests(true) + + // goodReplica1 is not replicating + goodReplica1.FakeMysqlDaemon.ReadOnly = true + goodReplica1.FakeMysqlDaemon.Replicating = true + goodReplica1.FakeMysqlDaemon.IOThreadRunning = false + goodReplica1.FakeMysqlDaemon.SetReplicationSourceInputs = append(goodReplica1.FakeMysqlDaemon.SetReplicationSourceInputs, topoproto.MysqlAddr(primary.Tablet)) + goodReplica1.FakeMysqlDaemon.CurrentSourceHost = primary.Tablet.MysqlHostname + goodReplica1.FakeMysqlDaemon.CurrentSourcePort = primary.Tablet.MysqlPort + goodReplica1.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ + // simulate error that will trigger a call to RestartReplication + // These 3 statements come from tablet startup + "STOP REPLICA", + "FAKE SET SOURCE", + "START REPLICA", + // In SetReplicationSource, we find that the source host and port was already set correctly, + // So we try to stop and start replication. The first STOP REPLICA comes from there + "STOP REPLICA", + // During the START REPLICA call, we find a relay log error, so we try to restart replication. + "STOP REPLICA", + "RESET REPLICA", + "START REPLICA", + } + goodReplica1.StartActionLoop(t, wr) + goodReplica1.FakeMysqlDaemon.StartReplicationError = relayError.err + defer goodReplica1.StopActionLoop(t) + + // run PlannedReparentShard + err := vp.Run([]string{ + "PlannedReparentShard", "--wait_replicas_timeout", "10s", "--keyspace_shard", primary.Tablet.Keyspace + "/" + primary.Tablet.Shard, "--new_primary", + topoproto.TabletAliasString(primary.Tablet.Alias), + }) + require.NoError(t, err) + // check what was run + err = primary.FakeMysqlDaemon.CheckSuperQueryList() + require.NoError(t, err) + err = goodReplica1.FakeMysqlDaemon.CheckSuperQueryList() + require.NoError(t, err) + + assert.False(t, primary.FakeMysqlDaemon.ReadOnly, "primary.FakeMysqlDaemon.ReadOnly set") + assert.True(t, goodReplica1.FakeMysqlDaemon.ReadOnly, "goodReplica1.FakeMysqlDaemon.ReadOnly not set") + assert.True(t, primary.TM.QueryServiceControl.IsServing(), "primary...QueryServiceControl not serving") + + // verify the old primary was told to start replicating (and not + // the replica that wasn't replicating in the first place) + assert.True(t, goodReplica1.FakeMysqlDaemon.Replicating, "goodReplica1.FakeMysqlDaemon.Replicating not set") + }) } - goodReplica1.StartActionLoop(t, wr) - goodReplica1.FakeMysqlDaemon.StartReplicationError = errors.New("Replica failed to initialize relay log info structure from the repository") - defer goodReplica1.StopActionLoop(t) - - // run PlannedReparentShard - err := vp.Run([]string{"PlannedReparentShard", "--wait_replicas_timeout", "10s", "--keyspace_shard", primary.Tablet.Keyspace + "/" + primary.Tablet.Shard, "--new_primary", - topoproto.TabletAliasString(primary.Tablet.Alias)}) - require.NoError(t, err) - // check what was run - err = primary.FakeMysqlDaemon.CheckSuperQueryList() - require.NoError(t, err) - err = goodReplica1.FakeMysqlDaemon.CheckSuperQueryList() - require.NoError(t, err) - - assert.False(t, primary.FakeMysqlDaemon.ReadOnly, "primary.FakeMysqlDaemon.ReadOnly set") - assert.True(t, goodReplica1.FakeMysqlDaemon.ReadOnly, "goodReplica1.FakeMysqlDaemon.ReadOnly not set") - assert.True(t, primary.TM.QueryServiceControl.IsServing(), "primary...QueryServiceControl not serving") - - // verify the old primary was told to start replicating (and not - // the replica that wasn't replicating in the first place) - assert.True(t, goodReplica1.FakeMysqlDaemon.Replicating, "goodReplica1.FakeMysqlDaemon.Replicating not set") } // TestPlannedReparentShardPromoteReplicaFail simulates a failure of the PromoteReplica call diff --git a/go/vt/wrangler/testlib/reparent_utils_test.go b/go/vt/wrangler/testlib/reparent_utils_test.go index 7012822a017..c8686e73796 100644 --- a/go/vt/wrangler/testlib/reparent_utils_test.go +++ b/go/vt/wrangler/testlib/reparent_utils_test.go @@ -18,13 +18,13 @@ package testlib import ( "context" - "errors" "testing" "time" "github.com/stretchr/testify/require" "vitess.io/vitess/go/mysql/replication" + "vitess.io/vitess/go/mysql/sqlerror" "vitess.io/vitess/go/vt/discovery" "vitess.io/vitess/go/vt/logutil" "vitess.io/vitess/go/vt/topo" @@ -215,41 +215,58 @@ func TestSetReplicationSource(t *testing.T) { primary.StartActionLoop(t, wr) defer primary.StopActionLoop(t) - // test when we receive a relay log error while starting replication - t.Run("Relay log error", func(t *testing.T) { - replica := NewFakeTablet(t, wr, "cell1", 2, topodatapb.TabletType_REPLICA, nil) - // replica loop - // We have to set the settings as replicating. Otherwise, - // the replication manager intervenes and tries to fix replication, - // which ends up making this test unpredictable. - replica.FakeMysqlDaemon.Replicating = true - replica.FakeMysqlDaemon.IOThreadRunning = true - replica.FakeMysqlDaemon.SetReplicationSourceInputs = append(replica.FakeMysqlDaemon.SetReplicationSourceInputs, topoproto.MysqlAddr(primary.Tablet)) - replica.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ - // These 3 statements come from tablet startup - "STOP REPLICA", - "FAKE SET SOURCE", - "START REPLICA", - // We stop and reset the replication parameters because of relay log issues. - "STOP REPLICA", - "STOP REPLICA", - "RESET REPLICA", - "START REPLICA", - } - replica.StartActionLoop(t, wr) - defer replica.StopActionLoop(t) - - // Set the correct error message that indicates we have received a relay log error. - replica.FakeMysqlDaemon.StartReplicationError = errors.New("ERROR 1201 (HY000): Could not initialize master info structure; more error messages can be found in the MySQL error log") - // run ReparentTablet - err = wr.SetReplicationSource(ctx, replica.Tablet) - require.NoError(t, err, "SetReplicationSource failed") + relayErrors := []struct { + name string + err error + uid uint32 + }{ + { + name: "master info relay error", + err: sqlerror.NewSQLError(sqlerror.ERMasterInfo, sqlerror.SSUnknownSQLState, "Could not initialize master info structure; more error messages can be found in the MySQL error log"), + uid: 2, + }, + { + name: "applier metadata relay error", + err: sqlerror.NewSQLError(sqlerror.ERReplicaApplierMetadataInitRepository, sqlerror.SSUnknownSQLState, "Replica failed to initialize applier metadata structure from the repository"), + uid: 5, + }, + } - // check what was run - err = replica.FakeMysqlDaemon.CheckSuperQueryList() - require.NoError(t, err, "CheckSuperQueryList failed") - checkSemiSyncEnabled(t, false, true, replica) - }) + for _, relayError := range relayErrors { + t.Run(relayError.name, func(t *testing.T) { + replica := NewFakeTablet(t, wr, "cell1", relayError.uid, topodatapb.TabletType_REPLICA, nil) + // replica loop + // We have to set the settings as replicating. Otherwise, + // the replication manager intervenes and tries to fix replication, + // which ends up making this test unpredictable. + replica.FakeMysqlDaemon.Replicating = true + replica.FakeMysqlDaemon.IOThreadRunning = true + replica.FakeMysqlDaemon.SetReplicationSourceInputs = append(replica.FakeMysqlDaemon.SetReplicationSourceInputs, topoproto.MysqlAddr(primary.Tablet)) + replica.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ + // These 3 statements come from tablet startup + "STOP REPLICA", + "FAKE SET SOURCE", + "START REPLICA", + // We stop and reset the replication parameters because of relay log issues. + "STOP REPLICA", + "STOP REPLICA", + "RESET REPLICA", + "START REPLICA", + } + replica.StartActionLoop(t, wr) + defer replica.StopActionLoop(t) + + // Set the correct error message that indicates we have received a relay log error. + replica.FakeMysqlDaemon.StartReplicationError = relayError.err + err := wr.SetReplicationSource(ctx, replica.Tablet) + require.NoError(t, err, "SetReplicationSource failed") + + // check what was run + err = replica.FakeMysqlDaemon.CheckSuperQueryList() + require.NoError(t, err, "CheckSuperQueryList failed") + checkSemiSyncEnabled(t, false, true, replica) + }) + } t.Run("Errant GTIDs on the replica", func(t *testing.T) { replica := NewFakeTablet(t, wr, "cell1", 4, topodatapb.TabletType_REPLICA, nil) diff --git a/go/vt/zkctl/zkctl_local.go b/go/vt/zkctl/zkctl_local.go index dfb11e28cd6..d6f44c37b08 100644 --- a/go/vt/zkctl/zkctl_local.go +++ b/go/vt/zkctl/zkctl_local.go @@ -18,9 +18,10 @@ package zkctl import ( "fmt" + "log" + "time" "vitess.io/vitess/go/netutil" - "vitess.io/vitess/go/vt/log" ) // StartLocalZk is a helper method to create a local ZK process. Used @@ -34,10 +35,19 @@ func StartLocalZk(id, port int) (*Zkd, string) { zkConfig := MakeZkConfigFromString(zkCfg, uint32(id)) zkd := NewZkd(zkConfig) - // Init & start zk. - if err := zkd.Init(); err != nil { - log.Exitf("zkd.Init(%d, %d) failed: %v", id, port, err) + // Init & start ZK. + retryTimer := time.NewTimer(10 * time.Minute) + defer retryTimer.Stop() + var err error + for { + if err = zkd.Init(); err == nil || err.Error() == "zk already inited" { + return zkd, fmt.Sprintf("%v:%v", hostname, port+2) + } + select { + case <-retryTimer.C: + log.Fatalf("zkd.Init(%d, %d) failed: %v", id, port, err) + default: + time.Sleep(1 * time.Second) + } } - - return zkd, fmt.Sprintf("%v:%v", hostname, port+2) } diff --git a/go/vt/zkctl/zkctl_test.go b/go/vt/zkctl/zkctl_test.go index a0c03a58df2..54417387401 100644 --- a/go/vt/zkctl/zkctl_test.go +++ b/go/vt/zkctl/zkctl_test.go @@ -18,7 +18,10 @@ package zkctl import ( "fmt" + "math/rand/v2" + "os" "testing" + "time" "github.com/stretchr/testify/require" ) @@ -28,16 +31,20 @@ import ( // so some manual cleanup may be required. func TestLifeCycle(t *testing.T) { - if testing.Short() { - t.Skip("skipping integration test in short mode.") + if testing.Short() || os.Getenv("CI") == "true" { + t.Skip("skipping integration test in short mode and in CI (it's too flaky).") } - config := "255@voltron:2888:3888:2181" - myID := 255 + leaderPort := 2888 + rand.IntN(100) + electionPort := 3888 + rand.IntN(100) + clientPort := 2181 + rand.IntN(100) + adminPort := 8081 + rand.IntN(100) + myID := 200 + rand.IntN(100) + config := fmt.Sprintf("%d@voltron:%d:%d:%d", myID, leaderPort, electionPort, clientPort) zkConf := MakeZkConfigFromString(config, uint32(myID)) tpcKeepAliveCfg := "tcpKeepAlive=true" - adminServerCfg := "admin.serverPort=8081" + adminServerCfg := fmt.Sprintf("admin.serverPort=%d", adminPort) zkConf.Extra = []string{tpcKeepAliveCfg, adminServerCfg} zkObservedConf, err := MakeZooCfg([]string{zkConf.ConfigFile()}, zkConf, "header") @@ -45,16 +52,56 @@ func TestLifeCycle(t *testing.T) { require.Contains(t, zkObservedConf, fmt.Sprintf("\n%s\n", tpcKeepAliveCfg), "Expected tpcKeepAliveCfg in zkObservedConf") require.Contains(t, zkObservedConf, fmt.Sprintf("\n%s\n", adminServerCfg), "Expected adminServerCfg in zkObservedConf") + retryTimer := time.NewTimer(10 * time.Minute) + defer retryTimer.Stop() + zkd := NewZkd(zkConf) - err = zkd.Init() - require.NoError(t, err) - err = zkd.Shutdown() - require.NoError(t, err) + for { + if err = zkd.Init(); err == nil { + break + } + select { + case <-retryTimer.C: + require.FailNow(t, "timeout waiting for Zkd.Init() to succeed: ", err) + default: + time.Sleep(1 * time.Second) + } + } - err = zkd.Start() - require.NoError(t, err) + for { + if err = zkd.Shutdown(); err == nil { + break + } + select { + case <-retryTimer.C: + require.FailNow(t, "timeout waiting for Zkd.Shutdown() to succeed: ", err) + default: + time.Sleep(1 * time.Second) + } + } - err = zkd.Teardown() - require.NoError(t, err) + for { + if err = zkd.Start(); err == nil { + break + } + select { + case <-retryTimer.C: + require.FailNow(t, "timeout waiting for Zkd.Start() to succeed: ", err) + default: + time.Sleep(1 * time.Second) + } + } + + for { + if err = zkd.Teardown(); err == nil { + break + } + select { + case <-retryTimer.C: + require.FailNow(t, "timeout waiting for Zkd.Teardown() to succeed: ", err) + default: + time.Sleep(1 * time.Second) + } + } } diff --git a/java/client/pom.xml b/java/client/pom.xml index 1c356ea6330..ef8a897dc8d 100644 --- a/java/client/pom.xml +++ b/java/client/pom.xml @@ -5,7 +5,7 @@ io.vitess vitess-parent - 22.0.3-SNAPSHOT + 22.0.5-SNAPSHOT vitess-client Vitess Java Client diff --git a/java/example/pom.xml b/java/example/pom.xml index 927192a593e..7815f342ba8 100644 --- a/java/example/pom.xml +++ b/java/example/pom.xml @@ -5,7 +5,7 @@ io.vitess vitess-parent - 22.0.3-SNAPSHOT + 22.0.5-SNAPSHOT vitess-example Vitess Java Client Example diff --git a/java/grpc-client/pom.xml b/java/grpc-client/pom.xml index dbb42fb51ea..9ce2b4bb6a9 100644 --- a/java/grpc-client/pom.xml +++ b/java/grpc-client/pom.xml @@ -5,7 +5,7 @@ io.vitess vitess-parent - 22.0.3-SNAPSHOT + 22.0.5-SNAPSHOT vitess-grpc-client Vitess gRPC Client diff --git a/java/jdbc/pom.xml b/java/jdbc/pom.xml index 97b89ca0c9e..01970830792 100644 --- a/java/jdbc/pom.xml +++ b/java/jdbc/pom.xml @@ -5,7 +5,7 @@ io.vitess vitess-parent - 22.0.3-SNAPSHOT + 22.0.5-SNAPSHOT vitess-jdbc Vitess JDBC Driver diff --git a/java/pom.xml b/java/pom.xml index 544d8fa7e78..2ed1dcc3d28 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -11,7 +11,7 @@ io.vitess vitess-parent - 22.0.3-SNAPSHOT + 22.0.5-SNAPSHOT pom Vitess Java Client libraries [Parent] diff --git a/proto/tabletmanagerdata.proto b/proto/tabletmanagerdata.proto index 9b300a2a939..0fe8649bb71 100644 --- a/proto/tabletmanagerdata.proto +++ b/proto/tabletmanagerdata.proto @@ -478,6 +478,7 @@ message InitReplicaResponse { } message DemotePrimaryRequest { + bool force = 1; } message DemotePrimaryResponse { diff --git a/test.go b/test.go index a61861890ae..218ac4ecb96 100755 --- a/test.go +++ b/test.go @@ -77,9 +77,8 @@ For example: // Flags var ( flavor = flag.String("flavor", "mysql80", "comma-separated bootstrap flavor(s) to run against (when using Docker mode). Available flavors: all,"+flavors) - bootstrapVersion = flag.String("bootstrap-version", "43.5", "the version identifier to use for the docker images") + bootstrapVersion = flag.String("bootstrap-version", "43.7", "the version identifier to use for the docker images") runCount = flag.Int("runs", 1, "run each test this many times") - retryMax = flag.Int("retry", 3, "max number of retries, to detect flaky tests") logPass = flag.Bool("log-pass", false, "log test output even if it passes") timeout = flag.Duration("timeout", 30*time.Minute, "timeout for each test") pull = flag.Bool("pull", true, "re-pull the bootstrap image, in case it's been updated") @@ -122,8 +121,10 @@ type Config struct { // Test is an entry from the test/config.json file. type Test struct { - File string - Args, Command []string + File string + Args []string + Command []string + Packages []string // Manual means it won't be run unless explicitly specified. Manual bool @@ -131,10 +132,6 @@ type Test struct { // Shard is used to split tests among workers. Shard string - // RetryMax is the maximum number of times a test will be retried. - // If 0, flag *retryMax is used. - RetryMax int - // Tags is a list of tags that can be used to filter tests. Tags []string @@ -174,6 +171,12 @@ func (t *Test) run(dir, dataDir string) ([]byte, error) { t.pass++ return nil, nil } + + junitOutput := fmt.Sprintf("_test/junit/report-%s-%d.xml", t.name, t.runIndex+1) + if *docker { + junitOutput = path.Join("/tmp/src", junitOutput) + } + testCmd := t.Command if len(testCmd) == 0 { if strings.Contains(fmt.Sprintf("%v", t.File), ".go") { @@ -217,9 +220,15 @@ func (t *Test) run(dir, dataDir string) ([]byte, error) { // Also try to make them use different port ranges // to mitigate failures due to zombie processes. cmd.Env = updateEnv(os.Environ(), map[string]string{ - "VTROOT": "/vt/src/vitess.io/vitess", - "VTDATAROOT": dataDir, - "VTPORTSTART": strconv.FormatInt(int64(getPortStart(100)), 10), + // Disable gRPC server GOAWAY/"too_many_pings" errors. Context: + // https://github.com/grpc/grpc/blob/master/doc/keepalive.md + "GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA": "0", + "JUNIT_OUTPUT": junitOutput, + "PACKAGES": strings.Join(t.Packages, " "), + "VTROOT": "/vt/src/vitess.io/vitess", + "VTDATAROOT": dataDir, + "VTPORTSTART": strconv.FormatInt(int64(getPortStart(100)), 10), + "TOPO": os.Getenv("TOPO"), }) // Capture test output. @@ -276,7 +285,6 @@ func loadOneConfig(fileName string) (*Config, error) { return nil, err } return config2, nil - } // Get test configs. @@ -329,10 +337,16 @@ func main() { // Make output directory. outDir := path.Join("_test", fmt.Sprintf("%v.%v", startTime.Format("20060102-150405"), os.Getpid())) - if err := os.MkdirAll(outDir, os.FileMode(0755)); err != nil { + if err := os.MkdirAll(outDir, os.FileMode(0o755)); err != nil { log.Fatalf("Can't create output directory: %v", err) } - logFile, err := os.OpenFile(path.Join(outDir, "test.log"), os.O_RDWR|os.O_CREATE, 0644) + + junitDir := path.Join("_test", "junit") + if err := os.MkdirAll(junitDir, os.FileMode(0o755)); err != nil { + log.Fatalf("Can't create junit directory: %v", err) + } + + logFile, err := os.OpenFile(path.Join(outDir, "test.log"), os.O_RDWR|os.O_CREATE, 0o644) if err != nil { log.Fatalf("Can't create log file: %v", err) } @@ -485,89 +499,63 @@ func main() { defer wg.Done() for test := range next { - tryMax := *retryMax - if test.RetryMax != 0 { - tryMax = test.RetryMax + select { + case <-stop: + test.logf("cancelled") + return + default: } - for try := 1; ; try++ { - select { - case <-stop: - test.logf("cancelled") - return - default: - } - if try > tryMax { - // Every try failed. - test.logf("retry limit exceeded") - mu.Lock() - failed++ - mu.Unlock() - break - } + test.logf("running...") - test.logf("running (try %v/%v)...", try, tryMax) + // Make a unique VTDATAROOT. + dataDir, err := os.MkdirTemp(vtDataRoot, "vt_") + if err != nil { + test.logf("Failed to create temporary subdir in VTDATAROOT: %v", vtDataRoot) + mu.Lock() + failed++ + mu.Unlock() + continue + } - // Make a unique VTDATAROOT. - dataDir, err := os.MkdirTemp(vtDataRoot, "vt_") - if err != nil { - test.logf("Failed to create temporary subdir in VTDATAROOT: %v", vtDataRoot) - mu.Lock() - failed++ - mu.Unlock() - break - } + // Run the test. + start := time.Now() + output, err := test.run(vtRoot, dataDir) + duration := time.Since(start) - // Run the test. - start := time.Now() - output, err := test.run(vtRoot, dataDir) - duration := time.Since(start) - - // Save/print test output. - if err != nil || *logPass { - if *printLog && !*follow { - test.logf("%s\n", output) - } - outFile := fmt.Sprintf("%v.%v-%v.%v.log", test.flavor, test.name, test.runIndex+1, try) - outFilePath := path.Join(outDir, outFile) - test.logf("saving test output to %v", outFilePath) - if fileErr := os.WriteFile(outFilePath, output, os.FileMode(0644)); fileErr != nil { - test.logf("WriteFile error: %v", fileErr) - } + // Save/print test output. + if err != nil || *logPass { + if *printLog && !*follow { + test.logf("%s\n", output) } - - // Clean up the unique VTDATAROOT. - if !*keepData { - if err := os.RemoveAll(dataDir); err != nil { - test.logf("WARNING: can't remove temporary VTDATAROOT: %v", err) - } + outFile := fmt.Sprintf("%v.%v-%v.log", test.flavor, test.name, test.runIndex+1) + outFilePath := path.Join(outDir, outFile) + test.logf("saving test output to %v", outFilePath) + if fileErr := os.WriteFile(outFilePath, output, os.FileMode(0o644)); fileErr != nil { + test.logf("WriteFile error: %v", fileErr) } + } - if err != nil { - // This try failed. - test.logf("FAILED (try %v/%v) in %v: %v", try, tryMax, round(duration), err) - mu.Lock() - testFailed(test.name) - mu.Unlock() - continue + // Clean up the unique VTDATAROOT. + if !*keepData { + if err := os.RemoveAll(dataDir); err != nil { + test.logf("WARNING: can't remove temporary VTDATAROOT: %v", err) } + } + if err != nil { + test.logf("FAILED in %v: %v", round(duration), err) mu.Lock() - testPassed(test.name, duration) - - if try == 1 { - // Passed on the first try. - test.logf("PASSED in %v", round(duration)) - passed++ - } else { - // Passed, but not on the first try. - test.logf("FLAKY (1/%v passed in %v)", try, round(duration)) - flaky++ - testFlaked(test.name, try) - } + testFailed(test.name) mu.Unlock() - break + continue } + + mu.Lock() + testPassed(test.name, duration) + test.logf("PASSED in %v", round(duration)) + passed++ + mu.Unlock() } }() } @@ -734,7 +722,7 @@ func updateTestStats(name string, update func(*TestStats)) { log.Printf("Can't encode stats file: %v", err) return } - if err := os.WriteFile(statsFileName, data, 0644); err != nil { + if err := os.WriteFile(statsFileName, data, 0o644); err != nil { log.Printf("Can't write stats file: %v", err) } } diff --git a/test/README.md b/test/README.md index 6579245ef45..1f4ca8e5306 100644 --- a/test/README.md +++ b/test/README.md @@ -4,17 +4,23 @@ This document has a short outline of how tests are run in CI, how to add new tes ### Adding a new test -Unit tests are run by the unit test runner, one per platform, currently mysql57, mysql80. +Unit tests are run by the unit test runner, one per platform, currently mysql57, mysql80, and mysql84. The workflow first installs the required database server before calling `make unit_test`. To add a new end-to-end (e2e) test (also called _cluster end to end_ tests): -* Add a new object to test/config.json -* If you are creating a new test _shard_: - * update `clusterList` in `ci_workflow_gen.go` - * `make generate_ci_workflows` -* If you are adding a new database platform, update the `templates\unit_test.tpl` to add - the platform specific packages and update `unitTestDatabases` +* Add a new object to test/config.json with the appropriate `Shard` value +* Add any required dependencies to the test's `Needs` array in config.json +* The cluster_endtoend.yml workflow will automatically pick up the new shard + +Available `Needs` values: +* `xtrabackup` - Install Percona Server and XtraBackup +* `minio` - Install Minio S3 server +* `consul` - Run `make tools` for Consul/ZooKeeper +* `larger-runner` - Use 16-core runner +* `memory-check` - Verify 15GB+ RAM +* `limit-resources` - Apply MySQL resource limits +* `binlog-compression` - Enable binlog transaction compression ### Vitess test runner The `.github/workflows` directory contains one yaml file per workflow. e2e tests are run using the `test.go` script @@ -26,19 +32,19 @@ Each test is of the form: ```javascript "vtgate": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate"], + "Packages": ["vitess.io/vitess/go/test/endtoend/vtgate"], + "Args": [], "Command": [], "Manual": false, - "Shard": 17, - "RetryMax": 0, + "Shard": "vtgate_queries", + "Needs": ["larger-runner"], "Tags": [] }, ``` -The important parameters here are Args which define the arguments to `go test` and the Shard which says -which Test VM should run this test. All tests which have a common Shard value are run in the same test vm. +The important parameters here are Packages which define the Go packages to test, Args for any `go test` flags, the Shard which says +which group of tests to run together, and Needs which specifies CI dependencies. ### Known Issue * Each VM does not seem to be able to create a lot of vttablets. For this reason we have had to split a few VReplication e2e tests across Shards. We need to identify and if possible fix this limitation so that we can reduce the number of test Shards - diff --git a/test/ci_workflow_gen.go b/test/ci_workflow_gen.go deleted file mode 100644 index 8c350033fd6..00000000000 --- a/test/ci_workflow_gen.go +++ /dev/null @@ -1,414 +0,0 @@ -/* -Copyright 2021 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -import ( - "bytes" - "fmt" - "log" - "os" - "path" - "strings" - "text/template" -) - -type mysqlVersion string - -const ( - mysql57 mysqlVersion = "mysql57" - mysql80 mysqlVersion = "mysql80" - mysql84 mysqlVersion = "mysql84" - - defaultMySQLVersion = mysql80 -) - -type mysqlVersions []mysqlVersion - -var ( - defaultMySQLVersions = []mysqlVersion{defaultMySQLVersion} -) - -var ( - unitTestDatabases = []mysqlVersion{mysql57, mysql80, mysql84} -) - -const ( - oracleCloudRunner = "oracle-16cpu-64gb-x86-64" - githubRunner = "ubuntu-latest-xl" - cores16RunnerName = githubRunner - defaultRunnerName = "ubuntu-24.04" -) - -// To support a private git repository, set goPrivate to a repo in -// github.com/org/repo format. This assumes a GitHub PAT token is -// set as a repo secret named GH_ACCESS_TOKEN. The GitHub PAT must -// have read access to your vitess fork/repo. -const goPrivate = "" - -const ( - workflowConfigDir = "../.github/workflows" - - unitTestTemplate = "templates/unit_test.tpl" - - // An empty string will cause the default non platform specific template - // to be used. - clusterTestTemplate = "templates/cluster_endtoend_test%s.tpl" - - clusterVitessTesterTemplate = "templates/cluster_vitess_tester.tpl" - - clusterTestDockerTemplate = "templates/cluster_endtoend_test_docker.tpl" -) - -var ( - // Clusters 10, 25 are executed on docker, using the docker_test_cluster 10, 25 workflows. - // Hence, they are not listed in the list below. - clusterList = []string{ - "vtctlbackup_sharded_clustertest_heavy", - "12", - "13", - "ers_prs_newfeatures_heavy", - "15", - "vtgate_general_heavy", - "vtbackup", - "18", - "xb_backup", - "backup_pitr", - "backup_pitr_xtrabackup", - "backup_pitr_mysqlshell", - "21", - "mysql_server_vault", - "vstream", - "onlineddl_vrepl", - "onlineddl_vrepl_stress", - "onlineddl_vrepl_stress_suite", - "onlineddl_vrepl_suite", - "onlineddl_revert", - "onlineddl_scheduler", - "tabletmanager_throttler_topo", - "tabletmanager_tablegc", - "tabletmanager_consul", - "vtgate_concurrentdml", - "vtgate_godriver", - "vtgate_gen4", - "vtgate_readafterwrite", - "vtgate_reservedconn", - "vtgate_schema", - "vtgate_tablet_healthcheck_cache", - "vtgate_topo", - "vtgate_topo_consul", - "vtgate_topo_etcd", - "vtgate_transaction", - "vtgate_unsharded", - "vtgate_vindex_heavy", - "vtgate_vschema", - "vtgate_queries", - "vtgate_plantests", - "vtgate_schema_tracker", - "vtgate_foreignkey_stress", - "vtorc", - "xb_recovery", - "mysql80", - "vreplication_across_db_versions", - "vreplication_mariadb_to_mysql", - "vreplication_basic", - "vreplication_cellalias", - "vreplication_copy_parallel", - "vreplication_v2", - "vreplication_partial_movetables_and_materialize", - "vreplication_foreign_key_stress", - "vreplication_migrate", - "vreplication_vtctldclient_movetables_tz", - "vreplication_vdiff2", - "vreplication_multi_tenant", - "schemadiff_vrepl", - "topo_connection_cache", - "vtgate_partial_keyspace", - "vttablet_prscomplex", - } - - buildTag = map[string]string{ - "vtgate_transaction": "debug2PC", - } - - vitessTesterMap = map[string]string{ - "vtgate": "./go/test/endtoend/vtgate/vitess_tester", - } - - clusterDockerList = []string{} - clustersRequiringXtraBackup = []string{ - "xb_backup", - "xb_recovery", - "backup_pitr_xtrabackup", - } - clustersRequiringMakeTools = []string{ - "18", - "mysql_server_vault", - "vtgate_topo_consul", - "tabletmanager_consul", - } - clustersRequiringMemoryCheck = []string{ - "vtorc", - } - clusterRequiring16CoresMachines = []string{ - "onlineddl_vrepl", - "onlineddl_vrepl_stress", - "onlineddl_vrepl_stress_suite", - "onlineddl_vrepl_suite", - "vreplication_basic", - "vreplication_migrate", - "vreplication_vtctldclient_vdiff2_movetables_tz", - "vtgate_transaction", - } - clusterRequiringMinio = []string{ - "21", - } -) - -type unitTest struct { - Name, RunsOn, Platform, FileName, GoPrivate, Evalengine string -} - -type clusterTest struct { - Name, Shard, Platform string - FileName string - BuildTag string - RunsOn string - GoPrivate string - MemoryCheck bool - MakeTools, InstallXtraBackup bool - Docker bool - LimitResourceUsage bool - EnableBinlogTransactionCompression bool - EnablePartialJSON bool - PartialKeyspace bool - NeedsMinio bool -} - -type vitessTesterTest struct { - FileName string - Name string - RunsOn string - GoPrivate string - Path string -} - -// clusterMySQLVersions return list of mysql versions (one or more) that this cluster needs to test against -func clusterMySQLVersions() mysqlVersions { - switch { - // Add any specific clusters, or groups of clusters, here, - // that require allMySQLVersions to be tested against. - // At this time this list is clean because Vitess stopped - // supporting MySQL 5.7. At some point, we will need to - // support post 8.0 versions of MySQL, and this list will - // inevitably grow. - default: - return defaultMySQLVersions - } -} - -func mergeBlankLines(buf *bytes.Buffer) string { - var out []string - in := strings.Split(buf.String(), "\n") - lastWasBlank := false - for _, line := range in { - if strings.TrimSpace(line) == "" { - if lastWasBlank { - continue - } - lastWasBlank = true - } else { - lastWasBlank = false - } - - out = append(out, line) - } - return strings.Join(out, "\n") -} - -func main() { - generateUnitTestWorkflows() - generateVitessTesterWorkflows(vitessTesterMap, clusterVitessTesterTemplate) - generateClusterWorkflows(clusterList, clusterTestTemplate) - generateClusterWorkflows(clusterDockerList, clusterTestDockerTemplate) -} - -func canonnizeList(list []string) []string { - var output []string - for _, item := range list { - if item := strings.TrimSpace(item); item != "" { - output = append(output, item) - } - } - return output -} - -func generateVitessTesterWorkflows(mp map[string]string, tpl string) { - for test, testPath := range mp { - tt := &vitessTesterTest{ - Name: fmt.Sprintf("Vitess Tester (%v)", test), - RunsOn: defaultRunnerName, - GoPrivate: goPrivate, - Path: testPath, - } - - templateFileName := tpl - tt.FileName = fmt.Sprintf("vitess_tester_%s.yml", test) - workflowPath := fmt.Sprintf("%s/%s", workflowConfigDir, tt.FileName) - err := writeFileFromTemplate(templateFileName, workflowPath, tt) - if err != nil { - log.Print(err) - } - } -} - -func generateClusterWorkflows(list []string, tpl string) { - clusters := canonnizeList(list) - for _, cluster := range clusters { - for _, mysqlVersion := range clusterMySQLVersions() { - test := &clusterTest{ - Name: fmt.Sprintf("Cluster (%s)", cluster), - Shard: cluster, - BuildTag: buildTag[cluster], - RunsOn: defaultRunnerName, - GoPrivate: goPrivate, - } - cores16Clusters := canonnizeList(clusterRequiring16CoresMachines) - for _, cores16Cluster := range cores16Clusters { - if cores16Cluster == cluster { - test.RunsOn = cores16RunnerName - break - } - } - makeToolClusters := canonnizeList(clustersRequiringMakeTools) - for _, makeToolCluster := range makeToolClusters { - if makeToolCluster == cluster { - test.MakeTools = true - break - } - } - memoryCheckClusters := canonnizeList(clustersRequiringMemoryCheck) - for _, memCheckCluster := range memoryCheckClusters { - if memCheckCluster == cluster { - test.MemoryCheck = true - break - } - } - xtraBackupClusters := canonnizeList(clustersRequiringXtraBackup) - for _, xtraBackupCluster := range xtraBackupClusters { - if xtraBackupCluster == cluster { - test.InstallXtraBackup = true - break - } - } - minioClusters := canonnizeList(clusterRequiringMinio) - for _, minioCluster := range minioClusters { - if minioCluster == cluster { - test.NeedsMinio = true - break - } - } - if mysqlVersion == mysql57 { - test.Platform = string(mysql57) - } - if strings.HasPrefix(cluster, "vreplication") || strings.HasSuffix(cluster, "heavy") { - test.LimitResourceUsage = true - } - if strings.Contains(cluster, "vrepl") { - test.EnableBinlogTransactionCompression = true - test.EnablePartialJSON = true - } - mysqlVersionIndicator := "" - if mysqlVersion != defaultMySQLVersion && len(clusterMySQLVersions()) > 1 { - mysqlVersionIndicator = "_" + string(mysqlVersion) - test.Name = test.Name + " " + string(mysqlVersion) - } - if strings.Contains(test.Shard, "partial_keyspace") { - test.PartialKeyspace = true - } - - workflowPath := fmt.Sprintf("%s/cluster_endtoend_%s%s.yml", workflowConfigDir, cluster, mysqlVersionIndicator) - templateFileName := tpl - if test.Platform != "" { - templateFileName = fmt.Sprintf(tpl, "_"+test.Platform) - } else if strings.Contains(templateFileName, "%s") { - templateFileName = fmt.Sprintf(tpl, "") - } - test.FileName = fmt.Sprintf("cluster_endtoend_%s%s.yml", cluster, mysqlVersionIndicator) - err := writeFileFromTemplate(templateFileName, workflowPath, test) - if err != nil { - log.Print(err) - } - } - } -} - -func generateUnitTestWorkflows() { - for _, platform := range unitTestDatabases { - for _, evalengine := range []string{"1", "0"} { - test := &unitTest{ - Name: fmt.Sprintf("Unit Test (%s%s)", evalengineToString(evalengine), platform), - RunsOn: defaultRunnerName, - Platform: string(platform), - GoPrivate: goPrivate, - Evalengine: evalengine, - } - test.FileName = fmt.Sprintf("unit_test_%s%s.yml", evalengineToString(evalengine), platform) - path := fmt.Sprintf("%s/%s", workflowConfigDir, test.FileName) - err := writeFileFromTemplate(unitTestTemplate, path, test) - if err != nil { - log.Print(err) - } - } - } -} - -func evalengineToString(evalengine string) string { - if evalengine == "1" { - return "evalengine_" - } - return "" -} - -func writeFileFromTemplate(templateFile, filePath string, test any) error { - tpl := template.New(path.Base(templateFile)) - tpl.Funcs(template.FuncMap{ - "contains": strings.Contains, - }) - tpl, err := tpl.ParseFiles(templateFile) - if err != nil { - return fmt.Errorf("Error: %s\n", err) - } - - buf := &bytes.Buffer{} - err = tpl.Execute(buf, test) - if err != nil { - return fmt.Errorf("Error: %s\n", err) - } - - f, err := os.Create(filePath) - if err != nil { - return fmt.Errorf("Error creating file: %s\n", err) - } - if _, err := f.WriteString("# DO NOT MODIFY: THIS FILE IS GENERATED USING \"make generate_ci_workflows\"\n\n"); err != nil { - return err - } - if _, err := f.WriteString(mergeBlankLines(buf)); err != nil { - return err - } - fmt.Printf("Generated %s\n", filePath) - return nil -} diff --git a/test/config.json b/test/config.json index f4d9894f163..0635dc4bd6c 100644 --- a/test/config.json +++ b/test/config.json @@ -1,1485 +1,2442 @@ { - "Tests": { - "java": { - "File": "", - "Args": [], - "Command": [ - "make", - "java_test" - ], - "Manual": false, - "Shard": "java", - "RetryMax": 1, - "Tags": [] - }, - "client_test": { - "File": "", - "Args": [], - "Command": [ - "test/client_test.sh" - ], - "Manual": false, - "Shard": "java", - "RetryMax": 1, - "Tags": [] - }, - "e2e": { - "File": "", - "Args": [], - "Command": [ - "tools/e2e_test_runner.sh" - ], - "Manual": false, - "Shard": "", - "RetryMax": 1, - "Tags": [] - }, - "e2e_race": { - "File": "", - "Args": [], - "Command": [ - "make", - "e2e_test_race" - ], - "Manual": false, - "Shard": "", - "RetryMax": 1, - "Tags": [] - }, - "unit": { - "File": "", - "Args": [], - "Command": [ - "tools/unit_test_runner.sh" - ], - "Manual": false, - "Shard": "", - "RetryMax": 1, - "Tags": [] - }, - "unit_race": { - "File": "", - "Args": [], - "Command": [ - "make", - "unit_test_race" - ], - "Manual": false, - "Shard": "5", - "RetryMax": 1, - "Tags": [] - }, - "local_example": { - "File": "", - "Args": [], - "Command": [ - "test/local_example.sh" - ], - "Manual": false, - "Shard": "", - "RetryMax": 1, - "Tags": [] - }, - "region_example": { - "File": "", - "Args": [], - "Command": [ - "test/region_example.sh" - ], - "Manual": false, - "Shard": "", - "RetryMax": 1, - "Tags": [] - }, - "backup_pitr": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/backup/pitr", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "backup_pitr", - "RetryMax": 1, - "Tags": [] - }, - "backup_pitr_xtrabackup": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/backup/pitr_xtrabackup", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "backup_pitr_xtrabackup", - "RetryMax": 1, - "Tags": [] - }, - "backup_pitr_mysqlshell": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/backup/pitr_mysqlshell", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "backup_pitr_mysqlshell", - "RetryMax": 1, - "Tags": [] - }, - "backup": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/backup/vtctlbackup", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "vtctlbackup_sharded_clustertest_heavy", - "RetryMax": 1, - "Tags": [] - }, - "backup_mysqlctld": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/backup/mysqlctld", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "21", - "RetryMax": 1, - "Tags": [] - }, - "backup_s3": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/backup/s3", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "21", - "RetryMax": 1, - "Tags": [] - }, - "backup_only": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/backup/vtbackup", "-timeout", "20m"], - "Command": [], - "Manual": false, - "Shard": "vtbackup", - "RetryMax": 1, - "Tags": ["upgrade_downgrade_backups"] - }, - "backup_xtrabackup": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/backup/xtrabackup", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "xb_backup", - "RetryMax": 2, - "Tags": [] - }, - "backup_xtrabackup_xbstream": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/backup/xtrabackupstream", "-run", "XtrabackupStream", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "xb_backup", - "RetryMax": 1, - "Tags": [] - }, - "backup_xtrabackup_xbstream_lz4": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/backup/xtrabackupstream", "-run", "XtrabackupStreamWithlz4Compression", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "xb_backup", - "RetryMax": 1, - "Tags": [] - }, - "cellalias": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/cellalias"], - "Command": [], - "Manual": false, - "Shard": "13", - "RetryMax": 3, - "Tags": [] - }, - "prepare_statement": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/preparestmt"], - "Command": [], - "Manual": false, - "Shard": "12", - "RetryMax": 1, - "Tags": ["upgrade_downgrade_query_serving_queries"] - }, - "mysql_server": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/mysqlserver"], - "Command": [], - "Manual": false, - "Shard": "mysql_server_vault", - "RetryMax": 1, - "Tags": [] - }, - "messaging": { - "File": "messaging_test.go", - "Args": ["vitess.io/vitess/go/test/endtoend/messaging"], - "Command": [], - "Manual": false, - "Shard": "12", - "RetryMax": 3, - "Tags": [] - }, - "clustertest": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/clustertest"], - "Command": [], - "Manual": false, - "Shard": "vtctlbackup_sharded_clustertest_heavy", - "RetryMax": 1, - "Tags": [] - }, - "encrypted_replication": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/encryption/encryptedreplication"], - "Command": [], - "Manual": false, - "Shard": "12", - "RetryMax": 1, - "Tags": [] - }, - "encrypted_transport": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/encryption/encryptedtransport"], - "Command": [], - "Manual": false, - "Shard": "12", - "RetryMax": 1, - "Tags": [] - }, - "keyspace": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/keyspace"], - "Command": [], - "Manual": false, - "Shard": "12", - "RetryMax": 1, - "Tags": [ - "site_test" - ] - }, - "mysqlctl": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/mysqlctl"], - "Command": [], - "Manual": false, - "Shard": "12", - "RetryMax": 1, - "Tags": [ - "site_test" - ] - }, - "mysqlctld": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/mysqlctld"], - "Command": [], - "Manual": false, - "Shard": "12", - "RetryMax": 1, - "Tags": [ - "site_test" - ] - }, - "onlineddl_vrepl": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/onlineddl/vrepl", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "onlineddl_vrepl", - "RetryMax": 2, - "Tags": [] - }, - "onlineddl_vrepl_stress": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/onlineddl/vrepl_stress", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "onlineddl_vrepl_stress", - "RetryMax": 1, - "Tags": [] - }, - "onlineddl_vrepl_suite": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/onlineddl/vrepl_suite", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "onlineddl_vrepl_suite", - "RetryMax": 1, - "Tags": [] - }, - "onlineddl_vrepl_stress_suite": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/onlineddl/vrepl_stress_suite", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "onlineddl_vrepl_stress_suite", - "RetryMax": 1, - "Tags": [] - }, - "onlineddl_revert": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/onlineddl/revert", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "onlineddl_revert", - "RetryMax": 1, - "Tags": [] - }, - "onlineddl_scheduler": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/onlineddl/scheduler", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "onlineddl_scheduler", - "RetryMax": 1, - "Tags": [] - }, - "onlineddl_flow": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/onlineddl/flow", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "onlineddl_flow", - "RetryMax": 1, - "Tags": ["upgrade_downgrade_onlineddl_flow"] - }, - "schemadiff_vrepl": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/schemadiff/vrepl", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "schemadiff_vrepl", - "RetryMax": 1, - "Tags": [] - }, - "recovery": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/recovery/unshardedrecovery"], - "Command": [], - "Manual": false, - "Shard": "vtctlbackup_sharded_clustertest_heavy", - "RetryMax": 1, - "Tags": [] - }, - "emergencyreparent": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/reparent/emergencyreparent", "-timeout", "20m"], - "Command": [], - "Manual": false, - "Shard": "ers_prs_newfeatures_heavy", - "RetryMax": 1, - "Tags": ["upgrade_downgrade_reparent"] - }, - "plannedreparent": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/reparent/plannedreparent", "-timeout", "20m"], - "Command": [], - "Manual": false, - "Shard": "ers_prs_newfeatures_heavy", - "RetryMax": 1, - "Tags": ["upgrade_downgrade_reparent"] - }, - "newfeatures": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/reparent/newfeaturetest"], - "Command": [], - "Manual": false, - "Shard": "ers_prs_newfeatures_heavy", - "RetryMax": 1, - "Tags": [""] - }, - "sharded": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/sharded", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "vtctlbackup_sharded_clustertest_heavy", - "RetryMax": 1, - "Tags": [] - }, - "tabletgateway_buffer_reparent": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/tabletgateway/buffer/reparent"], - "Command": [], - "Manual": false, - "Shard": "13", - "RetryMax": 1, - "Tags": [] - }, - "tabletgateway_buffer_reshard": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/tabletgateway/buffer/reshard"], - "Command": [], - "Manual": false, - "Shard": "13", - "RetryMax": 1, - "Tags": [] - }, - "tabletgateway": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/tabletgateway"], - "Command": [], - "Manual": false, - "Shard": "15", - "RetryMax": 1, - "Tags": [] - }, - "tabletmanager": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/tabletmanager"], - "Command": [], - "Manual": false, - "Shard": "18", - "RetryMax": 1, - "Tags": [ - "site_test" - ] - }, - "tabletmanager_replication_manager": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/tabletmanager/replication_manager"], - "Command": [], - "Manual": false, - "Shard": "18", - "RetryMax": 1, - "Tags": [] - }, - "tabletmanager_consul": { - "File": "unused.go", - "Args": [ - "vitess.io/vitess/go/test/endtoend/tabletmanager","--topo-flavor=consul" - ], - "Command": [], - "Manual": false, - "Shard": "tabletmanager_consul", - "RetryMax": 1, - "Tags": [ - "site_test" - ] - }, - "tabletmanager_throttler_topo": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/tabletmanager/throttler_topo"], - "Command": [], - "Manual": false, - "Shard": "tabletmanager_throttler_topo", - "RetryMax": 1, - "Tags": [ - "site_test" - ] - }, - "tabletmanager_tablegc": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/tabletmanager/tablegc"], - "Command": [], - "Manual": false, - "Shard": "tabletmanager_tablegc", - "RetryMax": 2, - "Tags": [ - "site_test" - ] - }, - "tabletmanager_zk2": { - "File": "unused.go", - "Args": [ - "vitess.io/vitess/go/test/endtoend/tabletmanager","--topo-flavor=zk2" - ], - "Command": [], - "Manual": false, - "Shard": "docker_cluster", - "RetryMax": 1, - "Tags": [ - "site_test" - ] - }, - "upgrade": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/versionupgrade", "-keep-data", "-force-vtdataroot", "/tmp/vtdataroot/vtroot_10901", "-force-port-start", "vtctlbackup_sharded_clustertest_heavy900", "-force-base-tablet-uid", "vtctlbackup_sharded_clustertest_heavy90"], - "Command": [], - "Manual": false, - "Shard": "28", - "RetryMax": 1, - "Tags": [] - }, - "vtgate": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate"], - "Command": [], - "Manual": false, - "Shard": "vtgate_general_heavy", - "RetryMax": 2, - "Tags": [] - }, - "vtgate_connectiondrain": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/connectiondrain"], - "Command": [], - "Manual": false, - "Shard": "vtgate_general_heavy", - "RetryMax": 2, - "Tags": [] - }, - "vtgate_queries_derived": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/derived"], - "Command": [], - "Manual": false, - "Shard": "vtgate_queries", - "RetryMax": 1, - "Tags": ["upgrade_downgrade_query_serving_queries"] - }, - "vtgate_queries_aggregation": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/aggregation"], - "Command": [], - "Manual": false, - "Shard": "vtgate_queries", - "RetryMax": 2, - "Tags": ["upgrade_downgrade_query_serving_queries"] - }, - "vtgate_queries_foundrows": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/foundrows"], - "Command": [], - "Manual": false, - "Shard": "vtgate_queries", - "RetryMax": 2, - "Tags": ["upgrade_downgrade_query_serving_queries"] - }, - "vtgate_queries_informationschema": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/informationschema"], - "Command": [], - "Manual": false, - "Shard": "vtgate_queries", - "RetryMax": 2, - "Tags": ["upgrade_downgrade_query_serving_queries"] - }, - "vtgate_queries_misc": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/misc"], - "Command": [], - "Manual": false, - "Shard": "vtgate_queries", - "RetryMax": 1, - "Tags": ["upgrade_downgrade_query_serving_queries"] - }, - "vtgate_queries_multi_query": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/multi_query"], - "Command": [], - "Manual": false, - "Shard": "vtgate_queries", - "RetryMax": 1, - "Tags": ["upgrade_downgrade_query_serving_queries"] - }, - "vtgate_queries_timeout": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/timeout"], - "Command": [], - "Manual": false, - "Shard": "vtgate_queries", - "RetryMax": 1, - "Tags": ["upgrade_downgrade_query_serving_queries"] - }, - "vtgate_queries_normalize": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/normalize"], - "Command": [], - "Manual": false, - "Shard": "vtgate_queries", - "RetryMax": 2, - "Tags": ["upgrade_downgrade_query_serving_queries"] - }, - "vtgate_queries_no_scatter": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/no_scatter"], - "Command": [], - "Manual": false, - "Shard": "vtgate_queries", - "RetryMax": 1, - "Tags": ["upgrade_downgrade_query_serving_queries"] - }, - "vtgate_queries_orderby": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/orderby", "-timeout", "20m"], - "Command": [], - "Manual": false, - "Shard": "vtgate_queries", - "RetryMax": 2, - "Tags": ["upgrade_downgrade_query_serving_queries"] - }, - "vtgate_queries_tpch": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/tpch", "-timeout", "20m"], - "Command": [], - "Manual": false, - "Shard": "vtgate_queries", - "RetryMax": 2, - "Tags": ["upgrade_downgrade_query_serving_queries_2"] - }, - "vtgate_queries_subquery": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/subquery", "-timeout", "20m"], - "Command": [], - "Manual": false, - "Shard": "vtgate_queries", - "RetryMax": 2, - "Tags": ["upgrade_downgrade_query_serving_queries_2"] - }, - "vtgate_queries_union": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/union", "-timeout", "20m"], - "Command": [], - "Manual": false, - "Shard": "vtgate_queries", - "RetryMax": 2, - "Tags": ["upgrade_downgrade_query_serving_queries_2"] - }, - "vtgate_queries_insert": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/dml"], - "Command": [], - "Manual": false, - "Shard": "vtgate_queries", - "RetryMax": 2, - "Tags": ["upgrade_downgrade_query_serving_queries_2"] - }, - "vtgate_queries_vexplain": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/vexplain"], - "Command": [], - "Manual": false, - "Shard": "vtgate_queries", - "RetryMax": 2, - "Tags": ["upgrade_downgrade_query_serving_queries_2"] - }, - "vtgate_queries_reference": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/reference"], - "Command": [], - "Manual": false, - "Shard": "vtgate_queries", - "RetryMax": 1, - "Tags": ["upgrade_downgrade_query_serving_queries_2"] - }, - "vtgate_queries_random": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/random"], - "Command": [], - "Manual": false, - "Shard": "vtgate_queries", - "RetryMax": 1, - "Tags": ["upgrade_downgrade_query_serving_queries_2"] - }, - "vtgate_kill": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/kill"], - "Command": [], - "Manual": false, - "Shard": "vtgate_queries", - "RetryMax": 1, - "Tags": ["upgrade_downgrade_query_serving_queries_2"] - }, - "vtgate_concurrentdml": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/concurrentdml"], - "Command": [], - "Manual": false, - "Shard": "vtgate_concurrentdml", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_schema": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/schema", "-timeout", "20m"], - "Command": [], - "Manual": false, - "Shard": "vtgate_schema", - "RetryMax": 1, - "Tags": ["upgrade_downgrade_query_serving_schema"] - }, - "vtgate_schematracker_loadkeyspace": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/schematracker/loadkeyspace"], - "Command": [], - "Manual": false, - "Shard": "vtgate_schema_tracker", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_schematracker_restarttablet": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/schematracker/restarttablet"], - "Command": [], - "Manual": false, - "Shard": "vtgate_schema_tracker", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_schematracker_sharded": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/schematracker/sharded", "-timeout", "20m"], - "Command": [], - "Manual": false, - "Shard": "vtgate_schema_tracker", - "RetryMax": 1, - "Tags": ["upgrade_downgrade_query_serving_schema"] - }, - "vtgate_schematracker_sharded_prs": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/schematracker/sharded_prs", "-timeout", "20m"], - "Command": [], - "Manual": false, - "Shard": "vtgate_schema_tracker", - "RetryMax": 1, - "Tags": ["upgrade_downgrade_query_serving_schema"] - }, - "vtgate_schematracker_unsharded": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/schematracker/unsharded", "-timeout", "20m"], - "Command": [], - "Manual": false, - "Shard": "vtgate_schema_tracker", - "RetryMax": 1, - "Tags": ["upgrade_downgrade_query_serving_schema"] - }, - "vtgate_schematracker_viewsdisabled": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/schematracker/viewsdisabled", "-timeout", "20m"], - "Command": [], - "Manual": false, - "Shard": "vtgate_schema_tracker", - "RetryMax": 1, - "Tags": ["upgrade_downgrade_query_serving_schema"] - }, - "vtgate_mysql80": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/mysql80"], - "Command": [], - "Manual": false, - "Shard": "mysql80", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_sequence": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/sequence"], - "Command": [], - "Manual": false, - "Shard": "vtgate_general_heavy", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_setstatement": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/reservedconn"], - "Command": [], - "Manual": false, - "Shard": "vtgate_reservedconn", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_reserved_conn1": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/reservedconn/reconnect1"], - "Command": [], - "Manual": false, - "Shard": "vtgate_reservedconn", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_reserved_conn2": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/reservedconn/reconnect2"], - "Command": [], - "Manual": false, - "Shard": "vtgate_reservedconn", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_reserved_conn3": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/reservedconn/reconnect3"], - "Command": [], - "Manual": false, - "Shard": "vtgate_reservedconn", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_reserved_conn4": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/reservedconn/reconnect4"], - "Command": [], - "Manual": false, - "Shard": "vtgate_reservedconn", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_tablet_healthcheck_cache": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/tablet_healthcheck_cache", "-timeout", "45m"], - "Command": [], - "Manual": false, - "Shard": "vtgate_tablet_healthcheck_cache", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_transaction": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/transaction"], - "Command": [], - "Manual": false, - "Shard": "vtgate_transaction", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_transaction_restart": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/transaction/restart"], - "Command": [], - "Manual": false, - "Shard": "vtgate_transaction", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_transaction_rollback": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/transaction/rollback"], - "Command": [], - "Manual": false, - "Shard": "vtgate_transaction", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_transaction_single": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/transaction/single"], - "Command": [], - "Manual": false, - "Shard": "vtgate_transaction", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_transaction_twopc": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/transaction/twopc"], - "Command": [], - "Manual": false, - "Shard": "vtgate_transaction", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_transaction_twopc_metric": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/transaction/twopc/metric"], - "Command": [], - "Manual": false, - "Shard": "vtgate_transaction", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_transaction_twopc_stress": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/transaction/twopc/stress"], - "Command": [], - "Manual": false, - "Shard": "vtgate_transaction", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_transaction_twopc_fuzz": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/transaction/twopc/fuzz"], - "Command": [], - "Manual": false, - "Shard": "vtgate_transaction", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_transaction_partial_exec": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/partialfailure"], - "Command": [], - "Manual": false, - "Shard": "vtgate_transaction", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_plantests": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/plan_tests"], - "Command": [], - "Manual": false, - "Shard": "vtgate_plantests", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_unsharded": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/unsharded"], - "Command": [], - "Manual": false, - "Shard": "vtgate_unsharded", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_vschema": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/vschema", "-timeout", "20m"], - "Command": [], - "Manual": false, - "Shard": "vtgate_vschema", - "RetryMax": 1, - "Tags": ["upgrade_downgrade_query_serving_schema"] - }, - "vtgate_readafterwrite": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/readafterwrite"], - "Command": [], - "Manual": false, - "Shard": "vtgate_readafterwrite", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_dbddlplugin": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/createdb_plugin"], - "Command": [], - "Manual": false, - "Shard": "vtgate_general_heavy", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_foreignkey": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/foreignkey"], - "Command": [], - "Manual": false, - "Shard": "vtgate_foreignkey_stress", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_foreignkey_routing": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/foreignkey/routing"], - "Command": [], - "Manual": false, - "Shard": "vtgate_foreignkey_stress", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_foreignkey_stress": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/foreignkey/stress", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "vtgate_foreignkey_stress", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_gen4": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/gen4"], - "Command": [], - "Manual": false, - "Shard": "vtgate_gen4", - "RetryMax": 2, - "Tags": [] - }, - "vtgate_godriver": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/godriver"], - "Command": [], - "Manual": false, - "Shard": "vtgate_godriver", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_watchkeyspace": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/keyspace_watches"], - "Command": [], - "Manual": false, - "Shard": "vtgate_topo", - "RetryMax": 1, - "Tags": [] - }, - "vtgate_grpc_api": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/grpc_api"], - "Command": [], - "Manual": false, - "Shard": "vtgate_general_heavy", - "RetryMax": 1, - "Tags": [] - }, - "topo_zk2": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/topotest/zk2", "--topo-flavor=zk2"], - "Command": [], - "Manual": false, - "Shard": "docker_cluster", - "RetryMax": 1, - "Tags": [] - }, - "topo_consul": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/topotest/consul", "--topo-flavor=consul"], - "Command": [], - "Manual": false, - "Shard": "vtgate_topo_consul", - "RetryMax": 1, - "Tags": [] - }, - "topo_etcd2": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/topotest/etcd2"], - "Command": [], - "Manual": false, - "Shard": "vtgate_topo_etcd", - "RetryMax": 1, - "Tags": [] - }, - "errs_as_warns": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/errors_as_warnings"], - "Command": [], - "Manual": false, - "Shard": "vtgate_general_heavy", - "RetryMax": 1, - "Tags": [] - }, - "consolidator": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/consolidator"], - "Command": [], - "Manual": false, - "Shard": "vtgate_general_heavy", - "RetryMax": 1, - "Tags": [] - }, - "prefixfanout": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/prefixfanout"], - "Command": [], - "Manual": false, - "Shard": "vtgate_vindex_heavy", - "RetryMax": 1, - "Tags": [] - }, - "vindex_bindvars": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/vindex_bindvars"], - "Command": [], - "Manual": false, - "Shard": "vtgate_vindex_heavy", - "RetryMax": 2, - "Tags": [] - }, - "vindex_secondary": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/sec_vind"], - "Command": [], - "Manual": false, - "Shard": "vtgate_vindex_heavy", - "RetryMax": 2, - "Tags": [] - }, - "vttest_sample": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtcombo"], - "Command": [], - "Manual": false, - "Shard": "docker_cluster", - "RetryMax": 1, - "Tags": [] - }, - "xb_recovery": { - "File": "recovery_test.go", - "Args": ["vitess.io/vitess/go/test/endtoend/recovery/xtrabackup"], - "Command": [], - "Manual": false, - "Shard": "xb_recovery", - "RetryMax": 1, - "Tags": [] - }, - "vreplication_materialize": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "Materialize"], - "Command": [], - "Manual": false, - "Shard": "vreplication_partial_movetables_and_materialize", - "RetryMax": 0, - "Tags": [] - }, - "vreplication_vtctldclient_materialize": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestMaterializeVtctldClient"], - "Command": [], - "Manual": false, - "Shard": "vreplication_partial_movetables_and_materialize", - "RetryMax": 0, - "Tags": [] - }, - "vreplication_cellalias": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "CellAlias"], - "Command": [], - "Manual": false, - "Shard": "vreplication_cellalias", - "RetryMax": 0, - "Tags": [] - }, - "vreplication_movetables_ignore_source_keyspace": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestMoveTablesIgnoreSourceKeyspace"], - "Command": [], - "Manual": false, - "Shard": "vreplication_cellalias", - "RetryMax": 0, - "Tags": [] - }, - "vreplication_multi_tenant": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication","-run", "MultiTenant"], - "Command": [], - "Manual": false, - "Shard": "vreplication_multi_tenant", - "RetryMax": 0, - "Tags": [] - }, - "vreplication_partial_movetables_basic": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "PartialMoveTablesBasic"], - "Command": [], - "Manual": false, - "Shard": "vreplication_partial_movetables_and_materialize", - "RetryMax": 0, - "Tags": [] - }, - "vdiff_multiple_movetables_test.go": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestMultipleConcurrentVDiffs"], - "Command": [], - "Manual": false, - "Shard": "vreplication_partial_movetables_and_materialize", - "RetryMax": 0, - "Tags": [] - }, - "vreplication_movetables_buffering": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestMoveTablesBuffering"], - "Command": [], - "Manual": false, - "Shard": "vreplication_cellalias", - "RetryMax": 0, - "Tags": [] - }, - "vreplication_onlineddl_vdiff": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestOnlineDDLVDiff"], - "Command": [], - "Manual": false, - "Shard": "vreplication_cellalias", - "RetryMax": 2, - "Tags": [] - }, - "vreplication_vschema_load": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestVSchemaChangesUnderLoad"], - "Command": [], - "Manual": false, - "Shard": "vreplication_cellalias", - "RetryMax": 2, - "Tags": [] - }, - "sidecardb": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestSidecarDB"], - "Command": [], - "Manual": false, - "Shard": "schemadiff_vrepl", - "RetryMax": 2, - "Tags": [] - }, - "vreplication_basic": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestBasicVreplicationWorkflow", "-timeout", "20m"], - "Command": [], - "Manual": false, - "Shard": "vreplication_basic", - "RetryMax": 1, - "Tags": [] - }, - "vreplication_copy_parallel": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestVreplicationCopyParallel", "-timeout", "20m"], - "Command": [], - "Manual": false, - "Shard": "vreplication_copy_parallel", - "RetryMax": 1, - "Tags": [] - }, - "vreplication_partial_movetables_sequences": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestPartialMoveTablesWithSequences"], - "Command": [], - "Manual": false, - "Shard": "vreplication_partial_movetables_and_materialize", - "RetryMax": 1, - "Tags": [] - }, - "vreplication_sequence_reset_on_switch_traffic": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestSequenceResetOnSwitchTraffic"], - "Command": [], - "Manual": false, - "Shard": "vreplication_partial_movetables_and_materialize", - "RetryMax": 1, - "Tags": [] - }, - "vstream_flush_binlog": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestVStreamFlushBinlog"], - "Command": [], - "Manual": false, - "Shard": "vreplication_basic", - "RetryMax": 1, - "Tags": [] - }, - "multi_vstreams_keyspace_reshard": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestMultiVStreamsKeyspaceReshard", "-timeout", "15m"], - "Command": [], - "Manual": false, - "Shard": "vstream", - "RetryMax": 1, - "Tags": [] - }, - "vstream_failover": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "VStreamFailover"], - "Command": [], - "Manual": false, - "Shard": "vstream", - "RetryMax": 3, - "Tags": [] - }, - "vstream_stoponreshard_true": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "VStreamStopOnReshardTrue"], - "Command": [], - "Manual": false, - "Shard": "vstream", - "RetryMax": 1, - "Tags": [] - }, - "vstream_stoponreshard_false": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "VStreamStopOnReshardFalse"], - "Command": [], - "Manual": false, - "Shard": "vstream", - "RetryMax": 1, - "Tags": [] - }, - "vstream_with_keyspaces_to_watch": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "VStreamWithKeyspacesToWatch"], - "Command": [], - "Manual": false, - "Shard": "vstream", - "RetryMax": 1, - "Tags": [] - }, - "vtop_example": { - "File": "", - "Args": [], - "Command": [ - "test/vtop_example.sh" - ], - "Manual": false, - "Shard": "", - "RetryMax": 1, - "Tags": [] - }, - "vtorc_primary_failure": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtorc/primaryfailure"], - "Command": [], - "Manual": false, - "Shard": "vtorc", - "RetryMax": 3, - "Tags": [] - }, - "vtorc_api": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtorc/api"], - "Command": [], - "Manual": false, - "Shard": "vtorc", - "RetryMax": 3, - "Tags": [] - }, - "vtorc_general": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtorc/general"], - "Command": [], - "Manual": false, - "Shard": "vtorc", - "RetryMax": 3, - "Tags": [] - }, - "vtorc_readtopologyinstance": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtorc/readtopologyinstance"], - "Command": [], - "Manual": false, - "Shard": "vtorc", - "RetryMax": 3, - "Tags": [] - }, - "vault": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vault"], - "Command": [], - "Manual": false, - "Shard": "mysql_server_vault", - "RetryMax": 1, - "Tags": [] - }, - "vreplication_v2": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestBasicV2Workflows", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "vreplication_v2", - "RetryMax": 1, - "Tags": [] - }, - "global_routing": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestGlobalRouting", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "vreplication_v2", - "RetryMax": 1, - "Tags": [] - }, - "vreplication_fk": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestFKWorkflow"], - "Command": [], - "Manual": false, - "Shard": "vreplication_cellalias", - "RetryMax": 1, - "Tags": [] - }, - "vreplication_foreign_key_stress": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestFKExt"], - "Command": [], - "Manual": false, - "Shard": "vreplication_foreign_key_stress", - "RetryMax": 1, - "Tags": [] - }, - "vreplication_across_db_versions": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestV2WorkflowsAcrossDBVersions", "-timeout", "20m"], - "Command": [], - "Manual": false, - "Shard": "vreplication_across_db_versions", - "RetryMax": 1, - "Tags": [] - }, - "vreplication_mariadb_to_mysql": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestMoveTablesMariaDBToMySQL", "-timeout", "20m"], - "Command": [], - "Manual": false, - "Shard": "vreplication_mariadb_to_mysql", - "RetryMax": 1, - "Tags": [] - }, - "vreplication_migrate": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestMigrate", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "vreplication_migrate", - "RetryMax": 1, - "Tags": [] - }, - "vdiff2": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestVDiff2", "-timeout", "30m"], - "Command": [], - "Manual": false, - "Shard": "vreplication_vdiff2", - "RetryMax": 1, - "Tags": [] - }, - "vreplication_vtctldclient_cli": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestVtctldclientCLI", "-timeout", "20m"], - "Command": [], - "Manual": false, - "Shard": "vreplication_vtctldclient_movetables_tz", - "RetryMax": 1, - "Tags": [] - }, - "vreplication_movetables_tz": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestMoveTablesTZ"], - "Command": [], - "Manual": false, - "Shard": "vreplication_vtctldclient_movetables_tz", - "RetryMax": 1, - "Tags": [] - }, - "loopkup_index": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vreplication", "-run", "TestLookupIndex"], - "Command": [], - "Manual": false, - "Shard": "vreplication_vtctldclient_movetables_tz", - "RetryMax": 1, - "Tags": [] - }, - "vtadmin": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtadmin"], - "Command": [], - "Manual": false, - "Shard": "15", - "RetryMax": 1, - "Tags": [] - }, - "topo_connection_cache": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/topoconncache", "-run", "TestVtctldListAllTablets"], - "Command": [], - "Manual": false, - "Shard": "topo_connection_cache", - "RetryMax": 1, - "Tags": [] - }, - "prscomplex": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/reparent/prscomplex"], - "Command": [], - "Manual": false, - "Shard": "vttablet_prscomplex", - "RetryMax": 1, - "Tags": [""] - }, - "prssettingspool": { - "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/reparent/prssettingspool"], - "Command": [], - "Manual": false, - "Shard": "vttablet_prscomplex", - "RetryMax": 1, - "Tags": [""] - } - } + "Tests": { + "java": { + "File": "", + "Packages": [], + "Args": [], + "Command": [ + "make", + "java_test" + ], + "Manual": false, + "Shard": "java", + "Tags": [], + "Needs": [] + }, + "client_test": { + "File": "", + "Packages": [], + "Args": [], + "Command": [ + "test/client_test.sh" + ], + "Manual": false, + "Shard": "java", + "Tags": [], + "Needs": [] + }, + "e2e": { + "File": "", + "Packages": [], + "Args": [], + "Command": [ + "tools/e2e_test_runner.sh" + ], + "Manual": false, + "Shard": "", + "Tags": [], + "Needs": [] + }, + "e2e_race": { + "File": "", + "Packages": [], + "Args": [], + "Command": [ + "make", + "e2e_test_race" + ], + "Manual": false, + "Shard": "", + "Tags": [], + "Needs": [] + }, + "unit": { + "File": "", + "Packages": [], + "Args": [], + "Command": [ + "tools/unit_test_runner.sh" + ], + "Manual": false, + "Shard": "", + "Tags": [], + "Needs": [] + }, + "unit_race": { + "File": "", + "Packages": [], + "Args": [], + "Command": [ + "make", + "unit_test_race" + ], + "Manual": false, + "Shard": "5", + "Tags": [], + "Needs": [] + }, + "local_example": { + "File": "", + "Packages": [], + "Args": [], + "Command": [ + "test/local_example.sh" + ], + "Manual": false, + "Shard": "", + "Tags": [], + "Needs": [] + }, + "region_example": { + "File": "", + "Packages": [], + "Args": [], + "Command": [ + "test/region_example.sh" + ], + "Manual": false, + "Shard": "", + "Tags": [], + "Needs": [] + }, + "backup_pitr": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/backup/pitr" + ], + "Args": [ + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "backup_pitr", + "Tags": [], + "Needs": [] + }, + "backup_pitr_xtrabackup": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/backup/pitr_xtrabackup" + ], + "Args": [ + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "backup_pitr_xtrabackup", + "Tags": [], + "Needs": [ + "xtrabackup" + ] + }, + "backup_pitr_mysqlshell": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/backup/pitr_mysqlshell" + ], + "Args": [ + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "backup_pitr_mysqlshell", + "Tags": [], + "Needs": [] + }, + "backup": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/backup/vtctlbackup" + ], + "Args": [ + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "vtctlbackup_sharded_clustertest_heavy", + "Tags": [], + "Needs": [ + "limit-resources" + ] + }, + "backup_mysqlctld": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/backup/mysqlctld" + ], + "Args": [ + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "21", + "Tags": [], + "Needs": [ + "minio" + ] + }, + "backup_s3": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/backup/s3" + ], + "Args": [ + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "21", + "Tags": [], + "Needs": [ + "minio" + ] + }, + "backup_only": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/backup/vtbackup" + ], + "Args": [ + "-timeout", + "20m" + ], + "Command": [], + "Manual": false, + "Shard": "vtbackup", + "Tags": [ + "upgrade_downgrade_backups" + ], + "Needs": [] + }, + "backup_xtrabackup": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/backup/xtrabackup" + ], + "Args": [ + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "xb_backup", + "Tags": [], + "Needs": [ + "xtrabackup" + ] + }, + "backup_xtrabackup_xbstream": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/backup/xtrabackupstream" + ], + "Args": [ + "-run", + "XtrabackupStream", + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "xb_backup", + "Tags": [], + "Needs": [ + "xtrabackup" + ] + }, + "backup_xtrabackup_xbstream_lz4": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/backup/xtrabackupstream" + ], + "Args": [ + "-run", + "XtrabackupStreamWithlz4Compression", + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "xb_backup", + "Tags": [], + "Needs": [ + "xtrabackup" + ] + }, + "cellalias": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/cellalias" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "13", + "Tags": [], + "Needs": [] + }, + "prepare_statement": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/preparestmt" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "12", + "Tags": [ + "upgrade_downgrade_query_serving_queries" + ], + "Needs": [] + }, + "mysql_server": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/mysqlserver" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "mysql_server_vault", + "Tags": [], + "Needs": [ + "consul" + ] + }, + "messaging": { + "File": "messaging_test.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/messaging" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "12", + "Tags": [], + "Needs": [] + }, + "clustertest": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/clustertest" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtctlbackup_sharded_clustertest_heavy", + "Tags": [], + "Needs": [ + "limit-resources" + ] + }, + "encrypted_replication": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/encryption/encryptedreplication" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "12", + "Tags": [], + "Needs": [] + }, + "encrypted_transport": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/encryption/encryptedtransport" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "12", + "Tags": [], + "Needs": [] + }, + "keyspace": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/keyspace" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "12", + "Tags": [ + "site_test" + ], + "Needs": [] + }, + "mysqlctl": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/mysqlctl" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "12", + "Tags": [ + "site_test" + ], + "Needs": [] + }, + "mysqlctld": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/mysqlctld" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "12", + "Tags": [ + "site_test" + ], + "Needs": [] + }, + "onlineddl_vrepl": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/onlineddl/vrepl" + ], + "Args": [ + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "onlineddl_vrepl", + "Tags": [], + "Needs": [ + "larger-runner", + "binlog-compression" + ] + }, + "onlineddl_vrepl_stress": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/onlineddl/vrepl_stress" + ], + "Args": [ + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "onlineddl_vrepl_stress", + "Tags": [], + "Needs": [ + "larger-runner", + "binlog-compression" + ] + }, + "onlineddl_vrepl_suite": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/onlineddl/vrepl_suite" + ], + "Args": [ + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "onlineddl_vrepl_suite", + "Tags": [], + "Needs": [ + "larger-runner", + "binlog-compression" + ] + }, + "onlineddl_vrepl_stress_suite": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/onlineddl/vrepl_stress_suite" + ], + "Args": [ + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "onlineddl_vrepl_stress_suite", + "Tags": [], + "Needs": [ + "larger-runner", + "binlog-compression" + ] + }, + "onlineddl_revert": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/onlineddl/revert" + ], + "Args": [ + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "onlineddl_revert", + "Tags": [], + "Needs": [] + }, + "onlineddl_scheduler": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/onlineddl/scheduler" + ], + "Args": [ + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "onlineddl_scheduler", + "Tags": [], + "Needs": [] + }, + "onlineddl_flow": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/onlineddl/flow" + ], + "Args": [ + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "onlineddl_flow", + "Tags": [ + "upgrade_downgrade_onlineddl_flow" + ], + "Needs": [] + }, + "schemadiff_vrepl": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/schemadiff/vrepl" + ], + "Args": [ + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "schemadiff_vrepl", + "Tags": [], + "Needs": [ + "binlog-compression" + ] + }, + "recovery": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/recovery/unshardedrecovery" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtctlbackup_sharded_clustertest_heavy", + "Tags": [], + "Needs": [ + "limit-resources" + ] + }, + "emergencyreparent": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/reparent/emergencyreparent" + ], + "Args": [ + "-timeout", + "20m" + ], + "Command": [], + "Manual": false, + "Shard": "ers_prs_newfeatures_heavy", + "Tags": [ + "upgrade_downgrade_reparent" + ], + "Needs": [ + "limit-resources" + ] + }, + "plannedreparent": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/reparent/plannedreparent" + ], + "Args": [ + "-timeout", + "20m" + ], + "Command": [], + "Manual": false, + "Shard": "ers_prs_newfeatures_heavy", + "Tags": [ + "upgrade_downgrade_reparent" + ], + "Needs": [ + "limit-resources" + ] + }, + "newfeatures": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/reparent/newfeaturetest" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "ers_prs_newfeatures_heavy", + "Tags": [ + "" + ], + "Needs": [ + "limit-resources" + ] + }, + "sharded": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/sharded" + ], + "Args": [ + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "vtctlbackup_sharded_clustertest_heavy", + "Tags": [], + "Needs": [ + "limit-resources" + ] + }, + "tabletgateway_buffer_reparent": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/tabletgateway/buffer/reparent" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "13", + "Tags": [], + "Needs": [] + }, + "tabletgateway_buffer_reshard": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/tabletgateway/buffer/reshard" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "13", + "Tags": [], + "Needs": [] + }, + "tabletgateway": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/tabletgateway" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "15", + "Tags": [], + "Needs": [] + }, + "tabletmanager": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/tabletmanager" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "18", + "Tags": [ + "site_test" + ], + "Needs": [ + "consul" + ] + }, + "tabletmanager_replication_manager": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/tabletmanager/replication_manager" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "18", + "Tags": [], + "Needs": [ + "consul" + ] + }, + "tabletmanager_consul": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/tabletmanager" + ], + "Args": [ + "--topo-flavor=consul" + ], + "Command": [], + "Manual": false, + "Shard": "tabletmanager_consul", + "Tags": [ + "site_test" + ], + "Needs": [ + "consul" + ] + }, + "tabletmanager_throttler_topo": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/tabletmanager/throttler_topo" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "tabletmanager_throttler_topo", + "Tags": [ + "site_test" + ], + "Needs": [] + }, + "tabletmanager_tablegc": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/tabletmanager/tablegc" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "tabletmanager_tablegc", + "Tags": [ + "site_test" + ], + "Needs": [] + }, + "tabletmanager_zk2": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/tabletmanager" + ], + "Args": [ + "--topo-flavor=zk2" + ], + "Command": [], + "Manual": false, + "Shard": "docker_cluster", + "Tags": [ + "site_test" + ], + "Needs": [] + }, + "upgrade": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/versionupgrade" + ], + "Args": [ + "-keep-data", + "-force-vtdataroot", + "/tmp/vtdataroot/vtroot_10901", + "-force-port-start", + "vtctlbackup_sharded_clustertest_heavy900", + "-force-base-tablet-uid", + "vtctlbackup_sharded_clustertest_heavy90" + ], + "Command": [], + "Manual": false, + "Shard": "28", + "Tags": [], + "Needs": [] + }, + "vtgate": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_general_heavy", + "Tags": [], + "Needs": [ + "limit-resources" + ] + }, + "vtgate_connectiondrain": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/connectiondrain" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_general_heavy", + "Tags": [], + "Needs": [ + "limit-resources" + ] + }, + "vtgate_queries_derived": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/derived" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_queries", + "Tags": [ + "upgrade_downgrade_query_serving_queries" + ], + "Needs": [] + }, + "vtgate_queries_aggregation": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/aggregation" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_queries", + "Tags": [ + "upgrade_downgrade_query_serving_queries" + ], + "Needs": [] + }, + "vtgate_queries_foundrows": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/foundrows" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_queries", + "Tags": [ + "upgrade_downgrade_query_serving_queries" + ], + "Needs": [] + }, + "vtgate_queries_informationschema": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/informationschema" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_queries", + "Tags": [ + "upgrade_downgrade_query_serving_queries" + ], + "Needs": [] + }, + "vtgate_queries_misc": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/misc" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_queries", + "Tags": [ + "upgrade_downgrade_query_serving_queries" + ], + "Needs": [] + }, + "vtgate_queries_multi_query": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/multi_query" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_queries", + "Tags": [ + "upgrade_downgrade_query_serving_queries" + ], + "Needs": [] + }, + "vtgate_queries_timeout": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/timeout" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_queries", + "Tags": [ + "upgrade_downgrade_query_serving_queries" + ], + "Needs": [] + }, + "vtgate_queries_normalize": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/normalize" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_queries", + "Tags": [ + "upgrade_downgrade_query_serving_queries" + ], + "Needs": [] + }, + "vtgate_queries_no_scatter": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/no_scatter" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_queries", + "Tags": [ + "upgrade_downgrade_query_serving_queries" + ], + "Needs": [] + }, + "vtgate_queries_orderby": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/orderby" + ], + "Args": [ + "-timeout", + "20m" + ], + "Command": [], + "Manual": false, + "Shard": "vtgate_queries", + "Tags": [ + "upgrade_downgrade_query_serving_queries" + ], + "Needs": [] + }, + "vtgate_queries_tpch": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/tpch" + ], + "Args": [ + "-timeout", + "20m" + ], + "Command": [], + "Manual": false, + "Shard": "vtgate_queries", + "Tags": [ + "upgrade_downgrade_query_serving_queries_2" + ], + "Needs": [] + }, + "vtgate_queries_subquery": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/subquery" + ], + "Args": [ + "-timeout", + "20m" + ], + "Command": [], + "Manual": false, + "Shard": "vtgate_queries", + "Tags": [ + "upgrade_downgrade_query_serving_queries_2" + ], + "Needs": [] + }, + "vtgate_queries_union": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/union" + ], + "Args": [ + "-timeout", + "20m" + ], + "Command": [], + "Manual": false, + "Shard": "vtgate_queries", + "Tags": [ + "upgrade_downgrade_query_serving_queries_2" + ], + "Needs": [] + }, + "vtgate_queries_insert": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/dml" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_queries", + "Tags": [ + "upgrade_downgrade_query_serving_queries_2" + ], + "Needs": [] + }, + "vtgate_queries_vexplain": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/vexplain" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_queries", + "Tags": [ + "upgrade_downgrade_query_serving_queries_2" + ], + "Needs": [] + }, + "vtgate_queries_reference": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/reference" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_queries", + "Tags": [ + "upgrade_downgrade_query_serving_queries_2" + ], + "Needs": [] + }, + "vtgate_queries_random": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/random" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_queries", + "Tags": [ + "upgrade_downgrade_query_serving_queries_2" + ], + "Needs": [] + }, + "vtgate_kill": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/kill" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_queries", + "Tags": [ + "upgrade_downgrade_query_serving_queries_2" + ], + "Needs": [] + }, + "vtgate_concurrentdml": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/concurrentdml" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_concurrentdml", + "Tags": [], + "Needs": [] + }, + "vtgate_schema": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/schema" + ], + "Args": [ + "-timeout", + "20m" + ], + "Command": [], + "Manual": false, + "Shard": "vtgate_schema", + "Tags": [ + "upgrade_downgrade_query_serving_schema" + ], + "Needs": [] + }, + "vtgate_schematracker_loadkeyspace": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/schematracker/loadkeyspace" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_schema_tracker", + "Tags": [], + "Needs": [] + }, + "vtgate_schematracker_restarttablet": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/schematracker/restarttablet" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_schema_tracker", + "Tags": [], + "Needs": [] + }, + "vtgate_schematracker_sharded": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/schematracker/sharded" + ], + "Args": [ + "-timeout", + "20m" + ], + "Command": [], + "Manual": false, + "Shard": "vtgate_schema_tracker", + "Tags": [ + "upgrade_downgrade_query_serving_schema" + ], + "Needs": [] + }, + "vtgate_schematracker_sharded_prs": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/schematracker/sharded_prs" + ], + "Args": [ + "-timeout", + "20m" + ], + "Command": [], + "Manual": false, + "Shard": "vtgate_schema_tracker", + "Tags": [ + "upgrade_downgrade_query_serving_schema" + ], + "Needs": [] + }, + "vtgate_schematracker_unsharded": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/schematracker/unsharded" + ], + "Args": [ + "-timeout", + "20m" + ], + "Command": [], + "Manual": false, + "Shard": "vtgate_schema_tracker", + "Tags": [ + "upgrade_downgrade_query_serving_schema" + ], + "Needs": [] + }, + "vtgate_schematracker_viewsdisabled": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/schematracker/viewsdisabled" + ], + "Args": [ + "-timeout", + "20m" + ], + "Command": [], + "Manual": false, + "Shard": "vtgate_schema_tracker", + "Tags": [ + "upgrade_downgrade_query_serving_schema" + ], + "Needs": [] + }, + "vtgate_sequence": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/sequence" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_general_heavy", + "Tags": [], + "Needs": [ + "limit-resources" + ] + }, + "vtgate_setstatement": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/reservedconn" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_reservedconn", + "Tags": [], + "Needs": [] + }, + "vtgate_reserved_conn1": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/reservedconn/reconnect1" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_reservedconn", + "Tags": [], + "Needs": [] + }, + "vtgate_reserved_conn2": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/reservedconn/reconnect2" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_reservedconn", + "Tags": [], + "Needs": [] + }, + "vtgate_reserved_conn3": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/reservedconn/reconnect3" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_reservedconn", + "Tags": [], + "Needs": [] + }, + "vtgate_reserved_conn4": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/reservedconn/reconnect4" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_reservedconn", + "Tags": [], + "Needs": [] + }, + "vtgate_tablet_healthcheck_cache": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/tablet_healthcheck_cache" + ], + "Args": [ + "-timeout", + "45m" + ], + "Command": [], + "Manual": false, + "Shard": "vtgate_tablet_healthcheck_cache", + "Tags": [], + "Needs": [] + }, + "vtgate_transaction": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/transaction" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_transaction", + "Tags": [], + "Needs": [ + "larger-runner" + ], + "BuildTag": "debug2PC" + }, + "vtgate_transaction_restart": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/transaction/restart" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_transaction", + "Tags": [], + "Needs": [], + "BuildTag": "debug2PC" + }, + "vtgate_transaction_rollback": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/transaction/rollback" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_transaction", + "Tags": [], + "Needs": [], + "BuildTag": "debug2PC" + }, + "vtgate_transaction_single": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/transaction/single" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_transaction", + "Tags": [], + "Needs": [], + "BuildTag": "debug2PC" + }, + "vtgate_transaction_twopc": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/transaction/twopc" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_transaction", + "Tags": [], + "Needs": [], + "BuildTag": "debug2PC" + }, + "vtgate_transaction_twopc_metric": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/transaction/twopc/metric" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_transaction", + "Tags": [], + "Needs": [], + "BuildTag": "debug2PC" + }, + "vtgate_transaction_twopc_stress": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/transaction/twopc/stress" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_transaction", + "Tags": [], + "Needs": [], + "BuildTag": "debug2PC" + }, + "vtgate_transaction_twopc_fuzz": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/transaction/twopc/fuzz" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_transaction", + "Tags": [], + "Needs": [ + "larger-runner" + ], + "BuildTag": "debug2PC" + }, + "vtgate_transaction_partial_exec": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/partialfailure" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_transaction", + "Tags": [], + "Needs": [], + "BuildTag": "debug2PC" + }, + "vtgate_plantests": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/plan_tests" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_plantests", + "Tags": [], + "Needs": [] + }, + "vtgate_unsharded": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/unsharded" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_unsharded", + "Tags": [], + "Needs": [] + }, + "vtgate_vschema": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/vschema" + ], + "Args": [ + "-timeout", + "20m" + ], + "Command": [], + "Manual": false, + "Shard": "vtgate_vschema", + "Tags": [ + "upgrade_downgrade_query_serving_schema" + ], + "Needs": [] + }, + "vtgate_readafterwrite": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/readafterwrite" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_readafterwrite", + "Tags": [], + "Needs": [] + }, + "vtgate_dbddlplugin": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/createdb_plugin" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_general_heavy", + "Tags": [], + "Needs": [ + "limit-resources" + ] + }, + "vtgate_foreignkey": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/foreignkey" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_foreignkey_stress", + "Tags": [], + "Needs": [] + }, + "vtgate_foreignkey_routing": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/foreignkey/routing" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_foreignkey_stress", + "Tags": [], + "Needs": [] + }, + "vtgate_foreignkey_stress": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/foreignkey/stress" + ], + "Args": [ + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "vtgate_foreignkey_stress", + "Tags": [], + "Needs": [] + }, + "vtgate_gen4": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/gen4" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_gen4", + "Tags": [], + "Needs": [] + }, + "vtgate_godriver": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/godriver" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_godriver", + "Tags": [], + "Needs": [] + }, + "vtgate_watchkeyspace": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/keyspace_watches" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_topo", + "Tags": [], + "Needs": [] + }, + "vtgate_grpc_api": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/grpc_api" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_general_heavy", + "Tags": [], + "Needs": [ + "limit-resources" + ] + }, + "topo_zk2": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/topotest/zk2" + ], + "Args": [ + "--topo-flavor=zk2" + ], + "Command": [], + "Manual": false, + "Shard": "docker_cluster", + "Tags": [], + "Needs": [] + }, + "topo_consul": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/topotest/consul" + ], + "Args": [ + "--topo-flavor=consul" + ], + "Command": [], + "Manual": false, + "Shard": "vtgate_topo_consul", + "Tags": [], + "Needs": [ + "consul" + ] + }, + "topo_etcd2": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/topotest/etcd2" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_topo_etcd", + "Tags": [], + "Needs": [] + }, + "errs_as_warns": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/errors_as_warnings" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_general_heavy", + "Tags": [], + "Needs": [ + "limit-resources" + ] + }, + "consolidator": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/consolidator" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_general_heavy", + "Tags": [], + "Needs": [ + "limit-resources" + ] + }, + "prefixfanout": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/prefixfanout" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_vindex_heavy", + "Tags": [], + "Needs": [ + "limit-resources" + ] + }, + "vindex_bindvars": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/vindex_bindvars" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_vindex_heavy", + "Tags": [], + "Needs": [ + "limit-resources" + ] + }, + "vindex_secondary": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/sec_vind" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtgate_vindex_heavy", + "Tags": [], + "Needs": [ + "limit-resources" + ] + }, + "vttest_sample": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtcombo" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "docker_cluster", + "Tags": [], + "Needs": [] + }, + "xb_recovery": { + "File": "recovery_test.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/recovery/xtrabackup" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "xb_recovery", + "Tags": [], + "Needs": [ + "xtrabackup" + ] + }, + "vreplication_materialize": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "Materialize" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_partial_movetables_and_materialize", + "Tags": [], + "Needs": [ + "larger-runner", + "limit-resources", + "binlog-compression" + ] + }, + "vreplication_vtctldclient_materialize": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestMaterializeVtctldClient" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_partial_movetables_and_materialize", + "Tags": [], + "Needs": [ + "larger-runner", + "limit-resources", + "binlog-compression" + ] + }, + "vreplication_cellalias": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "CellAlias" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_cellalias", + "Tags": [], + "Needs": [ + "larger-runner", + "limit-resources", + "binlog-compression" + ] + }, + "vreplication_movetables_ignore_source_keyspace": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestMoveTablesIgnoreSourceKeyspace" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_cellalias", + "Tags": [], + "Needs": [ + "larger-runner", + "limit-resources", + "binlog-compression" + ] + }, + "vreplication_multi_tenant": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "MultiTenant" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_multi_tenant", + "Tags": [], + "Needs": [ + "larger-runner", + "limit-resources", + "binlog-compression" + ] + }, + "vreplication_partial_movetables_basic": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "PartialMoveTablesBasic" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_partial_movetables_and_materialize", + "Tags": [], + "Needs": [ + "larger-runner", + "limit-resources", + "binlog-compression" + ] + }, + "vdiff_multiple_movetables_test.go": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestMultipleConcurrentVDiffs" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_partial_movetables_and_materialize", + "Tags": [], + "Needs": [ + "larger-runner", + "limit-resources", + "binlog-compression" + ] + }, + "vreplication_movetables_buffering": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestMoveTablesBuffering" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_cellalias", + "Tags": [], + "Needs": [ + "larger-runner", + "limit-resources", + "binlog-compression" + ] + }, + "vreplication_onlineddl_vdiff": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestOnlineDDLVDiff" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_cellalias", + "Tags": [], + "Needs": [ + "larger-runner", + "limit-resources", + "binlog-compression" + ] + }, + "vreplication_vschema_load": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestVSchemaChangesUnderLoad" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_cellalias", + "Tags": [], + "Needs": [ + "larger-runner", + "limit-resources", + "binlog-compression" + ] + }, + "sidecardb": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestSidecarDB" + ], + "Command": [], + "Manual": false, + "Shard": "schemadiff_vrepl", + "Tags": [], + "Needs": [ + "binlog-compression" + ] + }, + "vreplication_basic": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestBasicVreplicationWorkflow", + "-timeout", + "20m" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_basic", + "Tags": [], + "Needs": [ + "larger-runner", + "limit-resources", + "binlog-compression" + ] + }, + "vreplication_copy_parallel": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestVreplicationCopyParallel", + "-timeout", + "20m" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_copy_parallel", + "Tags": [], + "Needs": [ + "larger-runner", + "limit-resources", + "binlog-compression" + ] + }, + "vreplication_partial_movetables_sequences": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestPartialMoveTablesWithSequences" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_partial_movetables_and_materialize", + "Tags": [], + "Needs": [ + "larger-runner", + "limit-resources", + "binlog-compression" + ] + }, + "vreplication_sequence_reset_on_switch_traffic": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestSequenceResetOnSwitchTraffic" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_partial_movetables_and_materialize", + "Tags": [], + "Needs": [ + "larger-runner", + "limit-resources", + "binlog-compression" + ] + }, + "vstream_flush_binlog": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestVStreamFlushBinlog" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_basic", + "Tags": [], + "Needs": [ + "larger-runner", + "limit-resources", + "binlog-compression" + ] + }, + "multi_vstreams_keyspace_reshard": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestMultiVStreamsKeyspaceReshard", + "-timeout", + "15m" + ], + "Command": [], + "Manual": false, + "Shard": "vstream", + "Tags": [], + "Needs": [] + }, + "vstream_failover": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "VStreamFailover" + ], + "Command": [], + "Manual": false, + "Shard": "vstream", + "Tags": [], + "Needs": [] + }, + "vstream_stoponreshard_true": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "VStreamStopOnReshardTrue" + ], + "Command": [], + "Manual": false, + "Shard": "vstream", + "Tags": [], + "Needs": [] + }, + "vstream_stoponreshard_false": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "VStreamStopOnReshardFalse" + ], + "Command": [], + "Manual": false, + "Shard": "vstream", + "Tags": [], + "Needs": [] + }, + "vstream_with_keyspaces_to_watch": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "VStreamWithKeyspacesToWatch" + ], + "Command": [], + "Manual": false, + "Shard": "vstream", + "Tags": [], + "Needs": [] + }, + "vtop_example": { + "File": "", + "Packages": [], + "Args": [], + "Command": [ + "test/vtop_example.sh" + ], + "Manual": false, + "Shard": "", + "Tags": [], + "Needs": [] + }, + "vtorc_primary_failure": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtorc/primaryfailure" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtorc", + "Tags": [], + "Needs": [ + "larger-runner", + "memory-check" + ] + }, + "vtorc_api": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtorc/api" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtorc", + "Tags": [], + "Needs": [ + "memory-check" + ] + }, + "vtorc_general": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtorc/general" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtorc", + "Tags": [], + "Needs": [ + "memory-check" + ] + }, + "vtorc_readtopologyinstance": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtorc/readtopologyinstance" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vtorc", + "Tags": [], + "Needs": [ + "memory-check" + ] + }, + "vault": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vault" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "mysql_server_vault", + "Tags": [], + "Needs": [ + "consul" + ] + }, + "vreplication_v2": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestBasicV2Workflows", + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_v2", + "Tags": [], + "Needs": [ + "larger-runner", + "limit-resources", + "binlog-compression" + ] + }, + "global_routing": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestGlobalRouting", + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_v2", + "Tags": [], + "Needs": [ + "limit-resources", + "binlog-compression" + ] + }, + "vreplication_fk": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestFKWorkflow" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_cellalias", + "Tags": [], + "Needs": [ + "larger-runner", + "limit-resources", + "binlog-compression" + ] + }, + "vreplication_foreign_key_stress": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestFKExt" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_foreign_key_stress", + "Tags": [], + "Needs": [ + "larger-runner", + "limit-resources", + "binlog-compression" + ] + }, + "vreplication_across_db_versions": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestV2WorkflowsAcrossDBVersions", + "-timeout", + "20m" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_across_db_versions", + "Tags": [], + "Needs": [ + "larger-runner", + "limit-resources", + "binlog-compression" + ] + }, + "vreplication_mariadb_to_mysql": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestMoveTablesMariaDBToMySQL", + "-timeout", + "20m" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_mariadb_to_mysql", + "Tags": [], + "Needs": [ + "limit-resources", + "binlog-compression" + ] + }, + "vreplication_migrate": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestMigrate", + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_migrate", + "Tags": [], + "Needs": [ + "larger-runner", + "limit-resources", + "binlog-compression" + ] + }, + "vdiff2": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestVDiff2", + "-timeout", + "30m" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_vdiff2", + "Tags": [], + "Needs": [ + "limit-resources", + "binlog-compression" + ] + }, + "vreplication_vtctldclient_cli": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestVtctldclientCLI", + "-timeout", + "20m" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_vtctldclient_movetables_tz", + "Tags": [], + "Needs": [ + "limit-resources", + "binlog-compression" + ] + }, + "vreplication_movetables_tz": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestMoveTablesTZ" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_vtctldclient_movetables_tz", + "Tags": [], + "Needs": [ + "limit-resources", + "binlog-compression" + ] + }, + "loopkup_index": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vreplication" + ], + "Args": [ + "-run", + "TestLookupIndex" + ], + "Command": [], + "Manual": false, + "Shard": "vreplication_vtctldclient_movetables_tz", + "Tags": [], + "Needs": [ + "limit-resources", + "binlog-compression" + ] + }, + "vtadmin": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtadmin" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "15", + "Tags": [], + "Needs": [] + }, + "topo_connection_cache": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/topoconncache" + ], + "Args": [ + "-run", + "TestVtctldListAllTablets" + ], + "Command": [], + "Manual": false, + "Shard": "topo_connection_cache", + "Tags": [], + "Needs": [] + }, + "prscomplex": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/reparent/prscomplex" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vttablet_prscomplex", + "Tags": [ + "" + ], + "Needs": [] + }, + "prssettingspool": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/reparent/prssettingspool" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "vttablet_prscomplex", + "Tags": [ + "" + ], + "Needs": [] + }, + "vtgate_mysql80": { + "File": "unused.go", + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/schematracker/multi_ks" + ], + "Args": [], + "Command": [], + "Manual": false, + "Shard": "mysql80", + "RetryMax": 1, + "Tags": [], + "Needs": [] + } + } } diff --git a/test/config_partial_keyspace.json b/test/config_partial_keyspace.json index bcd445d34bc..2c3570aad76 100644 --- a/test/config_partial_keyspace.json +++ b/test/config_partial_keyspace.json @@ -2,146 +2,193 @@ "Tests": { "vtgate_partial_keyspace": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate"], + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate" + ], + "Args": [], "Command": [], "Manual": false, "Shard": "vtgate_partial_keyspace", - "RetryMax": 2, "Tags": [] }, "vtgate_sequence_partial_keyspace": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/sequence"], + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/sequence" + ], + "Args": [], "Command": [], "Manual": false, "Shard": "vtgate_partial_keyspace", - "RetryMax": 1, "Tags": [] }, "errs_as_warns_partial_keyspace": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/errors_as_warnings"], + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/errors_as_warnings" + ], + "Args": [], "Command": [], "Manual": false, "Shard": "vtgate_partial_keyspace", - "RetryMax": 1, "Tags": [] }, "vtgate_transaction_partial_keyspace": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/transaction"], + "Packages": [ + "vitess.io/vitess/go/test/endtoend/transaction" + ], + "Args": [], "Command": [], "Manual": false, "Shard": "vtgate_partial_keyspace", - "RetryMax": 1, "Tags": [] }, "vtgate_transaction_rollback_partial_keyspace": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/transaction/rollback"], + "Packages": [ + "vitess.io/vitess/go/test/endtoend/transaction/rollback" + ], + "Args": [], "Command": [], "Manual": false, "Shard": "vtgate_partial_keyspace", - "RetryMax": 1, "Tags": [] }, "vtgate_transaction_single_partial_keyspace": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/transaction/single"], + "Packages": [ + "vitess.io/vitess/go/test/endtoend/transaction/single" + ], + "Args": [], "Command": [], "Manual": false, "Shard": "vtgate_partial_keyspace", - "RetryMax": 1, "Tags": [] }, "vtgate_transaction_partial_exec_partial_keyspace": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/partialfailure"], + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/partialfailure" + ], + "Args": [], "Command": [], "Manual": false, "Shard": "vtgate_partial_keyspace", - "RetryMax": 1, "Tags": [] }, "vtgate_queries_aggregation_partial_keyspace": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/aggregation"], + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/aggregation" + ], + "Args": [], "Command": [], "Manual": false, "Shard": "vtgate_partial_keyspace", - "RetryMax": 2, "Tags": [] }, "vtgate_queries_foundrows_partial_keyspace": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/foundrows"], + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/foundrows" + ], + "Args": [], "Command": [], "Manual": false, "Shard": "vtgate_partial_keyspace", - "RetryMax": 2, "Tags": [] }, "vtgate_queries_informationschema_partial_keyspace": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/informationschema"], + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/informationschema" + ], + "Args": [], "Command": [], "Manual": false, "Shard": "vtgate_partial_keyspace", - "RetryMax": 2, "Tags": [] }, "vtgate_queries_misc_partial_keyspace": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/misc"], + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/misc" + ], + "Args": [], "Command": [], "Manual": false, "Shard": "vtgate_partial_keyspace", - "RetryMax": 1, "Tags": [] }, "vtgate_queries_normalize_partial_keyspace": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/normalize"], + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/normalize" + ], + "Args": [], "Command": [], "Manual": false, "Shard": "vtgate_partial_keyspace", - "RetryMax": 2, "Tags": [] }, "vtgate_queries_orderby_partial_keyspace": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/orderby", "-timeout", "20m"], + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/orderby" + ], + "Args": [ + "-timeout", + "20m" + ], "Command": [], "Manual": false, "Shard": "vtgate_partial_keyspace", - "RetryMax": 2, - "Tags": ["upgrade_downgrade_query_serving_queries"] + "Tags": [ + "upgrade_downgrade_query_serving_queries" + ] }, "vtgate_queries_subquery_partial_keyspace": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/subquery", "-timeout", "20m"], + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/subquery" + ], + "Args": [ + "-timeout", + "20m" + ], "Command": [], "Manual": false, "Shard": "vtgate_partial_keyspace", - "RetryMax": 2, - "Tags": ["upgrade_downgrade_query_serving_queries"] + "Tags": [ + "upgrade_downgrade_query_serving_queries" + ] }, "vtgate_queries_union_partial_keyspace": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/union", "-timeout", "20m"], + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/union" + ], + "Args": [ + "-timeout", + "20m" + ], "Command": [], "Manual": false, "Shard": "vtgate_partial_keyspace", - "RetryMax": 2, - "Tags": ["upgrade_downgrade_query_serving_queries"] + "Tags": [ + "upgrade_downgrade_query_serving_queries" + ] }, "vtgate_queries_insert_partial_keyspace": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/queries/dml"], + "Packages": [ + "vitess.io/vitess/go/test/endtoend/vtgate/queries/dml" + ], + "Args": [], "Command": [], "Manual": false, "Shard": "vtgate_partial_keyspace", - "RetryMax": 2, "Tags": [] } } diff --git a/test/templates/cluster_endtoend_test.tpl b/test/templates/cluster_endtoend_test.tpl deleted file mode 100644 index 3f6fa608b5b..00000000000 --- a/test/templates/cluster_endtoend_test.tpl +++ /dev/null @@ -1,240 +0,0 @@ -name: {{.Name}} -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{"{{"}} github.ref {{"}}"}}, '{{.Name}}') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{`{{ github.event.pull_request.head.sha }}`}}" -{{if .GoPrivate}} GOPRIVATE: "{{.GoPrivate}}"{{end}} - -jobs: - build: - timeout-minutes: 60 - name: Run endtoend tests on {{.Name}} - runs-on: {{.RunsOn}} - - steps: - - name: Skip CI - run: | - if [[ "{{"${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}"}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - {{if .MemoryCheck}} - - - name: Check Memory - run: | - totalMem=$(free -g | awk 'NR==2 {print $2}') - echo "total memory $totalMem GB" - if [[ "$totalMem" -lt 15 ]]; then - echo "Less memory than required" - exit 1 - fi - - {{end}} - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/{{.FileName}}' - {{- if or (contains .Name "onlineddl") (contains .Name "schemadiff") }} - - 'go/test/endtoend/onlineddl/vrepl_suite/testdata' - {{- end}} - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - -{{if .GoPrivate}} - - name: Setup GitHub access token - if: steps.changes.outputs.end_to_end == 'true' - run: git config --global url.https://${{`{{ secrets.GH_ACCESS_TOKEN }}`}}@github.com/.insteadOf https://github.com/ -{{end}} - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - {{if not .InstallXtraBackup}} - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - {{ end }} - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - {{if .InstallXtraBackup}} - - # Setup Percona Server for MySQL 8.0 - sudo apt-get -qq update - sudo apt-get -qq install -y lsb-release gnupg2 - wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb - sudo DEBIAN_FRONTEND="noninteractive" dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb - sudo percona-release setup ps80 - sudo apt-get -qq update - - sudo apt-get -qq install -y percona-server-server percona-server-client - - sudo service mysql stop - - sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/ - sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld - - sudo apt-get -qq install -y percona-xtrabackup-80 lz4 - - {{else}} - - sudo apt-get -qq install -y mysql-shell - - {{end}} - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - {{if .NeedsMinio }} - - name: Install Minio - run: | - wget https://dl.min.io/server/minio/release/linux-amd64/minio - chmod +x minio - mv minio /usr/local/bin - {{end}} - - {{if .MakeTools}} - - - name: Installing zookeeper and consul - if: steps.changes.outputs.end_to_end == 'true' - run: | - make tools - - {{end}} - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - {{if .LimitResourceUsage}} - # Increase our open file descriptor limit as we could hit this - ulimit -n 65536 - cat <<-EOF>>./config/mycnf/mysql8026.cnf - innodb_buffer_pool_dump_at_shutdown=OFF - innodb_buffer_pool_in_core_file=OFF - innodb_buffer_pool_load_at_startup=OFF - innodb_buffer_pool_size=64M - innodb_doublewrite=OFF - innodb_flush_log_at_trx_commit=0 - innodb_flush_method=O_DIRECT - innodb_numa_interleave=ON - innodb_adaptive_hash_index=OFF - sync_binlog=0 - sync_relay_log=0 - performance_schema=OFF - slow-query-log=OFF - EOF - {{end}} - - {{if .EnableBinlogTransactionCompression}} - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-transaction-compression=ON - EOF - {{end}} - - {{if .EnablePartialJSON}} - cat <<-EOF>>./config/mycnf/mysql8026.cnf - binlog-row-value-options=PARTIAL_JSON - EOF - {{end}} - - # Some of these tests require specific locales to be installed. - # See https://github.com/cncf/automation/commit/49f2ad7a791a62ff7d038002bbb2b1f074eed5d5 - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker={{if .Docker}}true -flavor={{.Platform}}{{else}}false{{end}} -follow -shard {{.Shard}}{{if .PartialKeyspace}} -partial-keyspace=true {{end}}{{if .BuildTag}} -build-tag={{.BuildTag}} {{end}} | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/test/templates/cluster_endtoend_test_docker.tpl b/test/templates/cluster_endtoend_test_docker.tpl deleted file mode 100644 index 6e7d8cf061f..00000000000 --- a/test/templates/cluster_endtoend_test_docker.tpl +++ /dev/null @@ -1,81 +0,0 @@ -name: {{.Name}} -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' - -permissions: read-all - -env: -{{if .GoPrivate}} GOPRIVATE: "{{.GoPrivate}}"{{end}} - -jobs: - build: - name: Run endtoend tests on {{.Name}} - runs-on: {{.RunsOn}} - - steps: - - name: Skip CI - run: | - if [[ "{{"${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}"}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/{{.FileName}}' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - -{{if .GoPrivate}} - - name: Setup GitHub access token - if: steps.changes.outputs.end_to_end == 'true' - run: git config --global url.https://${{`{{ secrets.GH_ACCESS_TOKEN }}`}}@github.com/.insteadOf https://github.com/ -{{end}} - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - run: | - sudo sysctl -w net.ipv4.ip_local_port_range="22768 65535" - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 30 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - - go run test.go -docker=true --follow -shard {{.Shard}} diff --git a/test/templates/cluster_endtoend_test_mysql57.tpl b/test/templates/cluster_endtoend_test_mysql57.tpl deleted file mode 100644 index 13a32866b3d..00000000000 --- a/test/templates/cluster_endtoend_test_mysql57.tpl +++ /dev/null @@ -1,211 +0,0 @@ -name: {{.Name}} -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{"{{"}} github.ref {{"}}"}}, '{{.Name}}') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{`{{ github.event.pull_request.head.sha }}`}}" -{{if .GoPrivate}} GOPRIVATE: "{{.GoPrivate}}"{{end}} -{{if .InstallXtraBackup}} - # This is used if we need to pin the xtrabackup version used in tests. - # If this is NOT set then the latest version available will be used. - #XTRABACKUP_VERSION: "2.4.24-1" -{{end}} - -jobs: - build: - name: Run endtoend tests on {{.Name}} - runs-on: {{.RunsOn}} - - steps: - - name: Skip CI - run: | - if [[ "{{"${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}"}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - {{if .MemoryCheck}} - - - name: Check Memory - run: | - totalMem=$(free -g | awk 'NR==2 {print $2}') - echo "total memory $totalMem GB" - if [[ "$totalMem" -lt 15 ]]; then - echo "Less memory than required" - exit 1 - fi - - {{end}} - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/onlineddl/vrepl_suite/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/{{.FileName}}' - {{- if or (contains .Name "onlineddl") (contains .Name "schemadiff") }} - - 'go/test/endtoend/onlineddl/vrepl_suite/testdata' - {{- end}} - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - -{{if .GoPrivate}} - - name: Setup GitHub access token - if: steps.changes.outputs.end_to_end == 'true' - run: git config --global url.https://${{`{{ secrets.GH_ACCESS_TOKEN }}`}}@github.com/.insteadOf https://github.com/ -{{end}} - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-5.7 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - run: | - sudo apt-get update - - sudo apt-get install -y make unzip g++ etcd-client etcd-server curl git wget - - sudo service etcd stop - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - {{if .InstallXtraBackup}} - - wget "https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb" - sudo apt-get install -y gnupg2 - sudo dpkg -i "percona-release_latest.$(lsb_release -sc)_all.deb" - sudo percona-release enable-only tools - sudo apt-get update - if [[ -n $XTRABACKUP_VERSION ]]; then - debfile="percona-xtrabackup-24_$XTRABACKUP_VERSION.$(lsb_release -sc)_amd64.deb" - wget "https://repo.percona.com/pxb-24/apt/pool/main/p/percona-xtrabackup-24/$debfile" - sudo apt install -y "./$debfile" - else - sudo apt-get install -y percona-xtrabackup-24 - fi - - {{end}} - - {{if .MakeTools}} - - - name: Installing zookeeper and consul - if: steps.changes.outputs.end_to_end == 'true' - run: | - make tools - - {{end}} - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - - set -exo pipefail - - {{if .LimitResourceUsage}} - # Increase our local ephemeral port range as we could exhaust this - sudo sysctl -w net.ipv4.ip_local_port_range="22768 61999" - # Increase our open file descriptor limit as we could hit this - ulimit -n 65536 - cat <<-EOF>>./config/mycnf/mysql57.cnf - innodb_buffer_pool_dump_at_shutdown=OFF - innodb_buffer_pool_load_at_startup=OFF - innodb_buffer_pool_size=64M - innodb_doublewrite=OFF - innodb_flush_log_at_trx_commit=0 - innodb_flush_method=O_DIRECT - innodb_numa_interleave=ON - innodb_adaptive_hash_index=OFF - sync_binlog=0 - sync_relay_log=0 - performance_schema=OFF - slow-query-log=OFF - EOF - {{end}} - - # run the tests however you normally do, then produce a JUnit XML file - go run test.go -docker={{if .Docker}}true -flavor={{.Platform}}{{else}}false{{end}} -follow -shard {{.Shard}}{{if .PartialKeyspace}} -partial-keyspace=true {{end}} | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/test/templates/cluster_vitess_tester.tpl b/test/templates/cluster_vitess_tester.tpl deleted file mode 100644 index e0f645bec13..00000000000 --- a/test/templates/cluster_vitess_tester.tpl +++ /dev/null @@ -1,162 +0,0 @@ -name: {{.Name}} -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{"{{"}} github.ref {{"}}"}}, '{{.Name}}') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{`{{ github.event.pull_request.head.sha }}`}}" -{{if .GoPrivate}} GOPRIVATE: "{{.GoPrivate}}"{{end}} - -jobs: - build: - name: Run endtoend tests on {{.Name}} - runs-on: {{.RunsOn}} - - steps: - - name: Skip CI - run: | - if [[ "{{"${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}"}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - end_to_end: - - 'test/config.json' - - 'go/**/*.go' - - 'go/vt/sidecardb/**/*.sql' - - 'go/test/endtoend/vtgate/vitess_tester/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/{{.FileName}}' - - - name: Set up Go - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - -{{if .GoPrivate}} - - name: Setup GitHub access token - if: steps.changes.outputs.end_to_end == 'true' - run: git config --global url.https://${{`{{ secrets.GH_ACCESS_TOKEN }}`}}@github.com/.insteadOf https://github.com/ -{{end}} - - - name: Set up python - if: steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.end_to_end == 'true' - uses: ./.github/actions/setup-mysql - with: - flavor: mysql-8.0 - - - name: Get dependencies - if: steps.changes.outputs.end_to_end == 'true' - run: | - sudo apt-get -qq update - - # Install everything else we need, and configure - sudo apt-get -qq install -y make unzip g++ etcd-client etcd-server curl git wget xz-utils libncurses6 - - sudo service etcd stop - - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - # install vitess tester - go install github.com/vitessio/vt/go/vt@e43009309f599378504905d4b804460f47822ac5 - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run cluster endtoend test - if: steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 45 - run: | - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - source build.env - export NOVTADMINBUILD=1 - make build - - set -exo pipefail - - i=1 - for dir in {{.Path}}/*/; do - # We go over all the directories in the given path. - # If there is a vschema file there, we use it, otherwise we let vt tester autogenerate it. - if [ -f $dir/vschema.json ]; then - vt tester --xunit --vschema "$dir"vschema.json $dir/*.test - else - vt tester --sharded --xunit $dir/*.test - fi - # Number the reports by changing their file names. - mv report.xml report"$i".xml - i=$((i+1)) - done - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - run: | - # print test output - cat report*.xml - - - name: Test Summary - if: steps.changes.outputs.end_to_end == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report*.xml" - show: "fail" diff --git a/test/templates/dockerfile.tpl b/test/templates/dockerfile.tpl deleted file mode 100644 index 3f0afe39e1b..00000000000 --- a/test/templates/dockerfile.tpl +++ /dev/null @@ -1,48 +0,0 @@ -ARG bootstrap_version=43.5 -ARG image="vitess/bootstrap:${bootstrap_version}-{{.Platform}}" - -FROM "${image}" - -USER root - -# Re-copy sources from working tree -RUN rm -rf /vt/src/vitess.io/vitess/* -COPY . /vt/src/vitess.io/vitess - -{{if .InstallXtraBackup}} -# install XtraBackup -RUN wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb -RUN apt-get update -RUN apt-get install -y gnupg2 -RUN dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb -RUN percona-release enable-only tools -RUN apt-get update -RUN apt-get install -y percona-xtrabackup-24 -{{end}} - -# Set the working directory -WORKDIR /vt/src/vitess.io/vitess - -# Fix permissions -RUN chown -R vitess:vitess /vt - -USER vitess - -# Set environment variables -ENV VTROOT /vt/src/vitess.io/vitess -# Set the vtdataroot such that it uses the volume mount -ENV VTDATAROOT /vt/vtdataroot - -# create the vtdataroot directory -RUN mkdir -p $VTDATAROOT - -# install goimports -RUN go install golang.org/x/tools/cmd/goimports@latest - -{{if .MakeTools}} -# make tools -RUN make tools -{{end}} - -# sleep for 50 minutes -CMD sleep 3000 diff --git a/test/templates/unit_test.tpl b/test/templates/unit_test.tpl deleted file mode 100644 index 2b2de08416e..00000000000 --- a/test/templates/unit_test.tpl +++ /dev/null @@ -1,161 +0,0 @@ -name: {{.Name}} -on: - push: - branches: - - "main" - - "release-[0-9]+.[0-9]" - tags: '**' - pull_request: - branches: '**' -concurrency: - group: format('{0}-{1}', ${{"{{"}} github.ref {{"}}"}}, '{{.Name}}') - cancel-in-progress: true - -permissions: read-all - -env: - LAUNCHABLE_ORGANIZATION: "vitess" - LAUNCHABLE_WORKSPACE: "vitess-app" - GITHUB_PR_HEAD_SHA: "${{`{{ github.event.pull_request.head.sha }}`}}" -{{if .GoPrivate}} GOPRIVATE: "{{.GoPrivate}}"{{end}} - -jobs: - test: - name: {{.Name}} - runs-on: {{.RunsOn}} - - steps: - - name: Skip CI - run: | - if [[ "{{"${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}"}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: 'false' - - - name: Check for changes in relevant files - uses: dorny/paths-filter@ebc4d7e9ebcb0b1eb21480bb8f43113e996ac77a # v3.0.1 - id: changes - with: - token: '' - filters: | - unit_tests: - - 'test/config.json' - - 'go/**' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/{{.FileName}}' - - - name: Set up Go - if: steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - with: - go-version-file: go.mod - -{{if .GoPrivate}} - - name: Setup GitHub access token - if: steps.changes.outputs.unit_tests == 'true' - run: git config --global url.https://${{`{{ secrets.GH_ACCESS_TOKEN }}`}}@github.com/.insteadOf https://github.com/ -{{end}} - - - name: Set up python - if: steps.changes.outputs.unit_tests == 'true' - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 - - - name: Tune the OS - if: steps.changes.outputs.unit_tests == 'true' - uses: ./.github/actions/tune-os - - - name: Setup MySQL - if: steps.changes.outputs.unit_tests == 'true' - uses: ./.github/actions/setup-mysql - with: - {{ if (eq .Platform "mysql57") -}} - flavor: mysql-5.7 - {{ end }} - {{- if (eq .Platform "mysql80") -}} - flavor: mysql-8.0 - {{ end }} - {{- if (eq .Platform "mysql84") -}} - flavor: mysql-8.4 - {{ end }} - - - name: Get dependencies - if: steps.changes.outputs.unit_tests == 'true' - run: | - export DEBIAN_FRONTEND="noninteractive" - sudo apt-get install -y make unzip g++ curl git wget ant openjdk-11-jdk - - mkdir -p dist bin - curl --max-time 10 --retry 3 --retry-max-time 45 -s -L https://github.com/coreos/etcd/releases/download/v3.5.25/etcd-v3.5.25-linux-amd64.tar.gz | tar -zxC dist - mv dist/etcd-v3.5.25-linux-amd64/{etcd,etcdctl} bin/ - - go mod download - go install golang.org/x/tools/cmd/goimports@latest - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - - name: Run make tools - if: steps.changes.outputs.unit_tests == 'true' - run: | - make tools - - - name: Setup launchable dependencies - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.unit_tests == 'true' && github.base_ref == 'main' - run: | - # Get Launchable CLI installed. If you can, make it a part of the builder image to speed things up - pip3 install --user launchable~=1.0 > /dev/null - - # verify that launchable setup is all correct. - launchable verify || true - - # Tell Launchable about the build you are producing and testing - launchable record build --name "$GITHUB_RUN_ID" --no-commit-collection --source . - - - name: Run test - if: steps.changes.outputs.unit_tests == 'true' - timeout-minutes: 30 - run: | - set -exo pipefail - # We set the VTDATAROOT to the /tmp folder to reduce the file path of mysql.sock file - # which musn't be more than 107 characters long. - export VTDATAROOT="/tmp/" - - export NOVTADMINBUILD=1 - export VTEVALENGINETEST="{{.Evalengine}}" - # We sometimes need to alter the behavior based on the platform we're - # testing, e.g. MySQL 5.7 vs 8.0. - export CI_DB_PLATFORM="{{.Platform}}" - - make unit_test | tee -a output.txt | go-junit-report -set-exit-code > report.xml - - - name: Record test results in launchable if PR is not a draft - if: github.event_name == 'pull_request' && github.event.pull_request.draft == 'false' && steps.changes.outputs.unit_tests == 'true' && github.base_ref == 'main' && !cancelled() - run: | - # send recorded tests to launchable - launchable record tests --build "$GITHUB_RUN_ID" go-test . || true - - - name: Print test output - if: steps.changes.outputs.unit_tests == 'true' && !cancelled() - run: | - # print test output - cat output.txt - - - name: Test Summary - if: steps.changes.outputs.unit_tests == 'true' && !cancelled() - uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4 - with: - paths: "report.xml" - show: "fail" diff --git a/tools/check_go_versions.sh b/tools/check_go_versions.sh index 846a10322f1..5c32a3b5cb4 100755 --- a/tools/check_go_versions.sh +++ b/tools/check_go_versions.sh @@ -10,13 +10,13 @@ set -e # go.mod GO_MOD_VERSION="$(awk '/^go [0-9].[0-9]+/{print $(NF-0)}' go.mod)" if [ -z "${GO_MOD_VERSION}" ]; then - echo "cannot find go version in go.mod" - exit 1 + echo "cannot find go version in go.mod" + exit 1 fi # docker/bootstrap/Dockerfile.common -BOOTSTRAP_GO_VERSION="$(awk -F ':' '/golang:/{print $(NF-0)}' docker/bootstrap/Dockerfile.common | cut -d- -f1)" -if [[ ! "${BOOTSTRAP_GO_VERSION}" =~ "${GO_MOD_VERSION}" ]]; then - echo "expected golang docker version in docker/bootstrap/Dockerfile.common to be equal to go.mod: '${TPL_GO_VERSION}' != '${GO_MOD_VERSION}'" - exit 1 +BOOTSTRAP_GO_VERSION="$(sed -n 's/.*golang:\([0-9]*\.[0-9]*\.[0-9]*\).*/\1/p' docker/bootstrap/Dockerfile.common)" +if [[ "${BOOTSTRAP_GO_VERSION}" != "${GO_MOD_VERSION}" ]]; then + echo "expected golang docker version in docker/bootstrap/Dockerfile.common to be equal to go.mod: '${BOOTSTRAP_GO_VERSION}' != '${GO_MOD_VERSION}'" + exit 1 fi diff --git a/tools/e2e_go_test.sh b/tools/e2e_go_test.sh index bc4964ffb12..c519b5589df 100755 --- a/tools/e2e_go_test.sh +++ b/tools/e2e_go_test.sh @@ -1,4 +1,25 @@ #!/bin/bash + source build.env -echo "running tests for " "$@" -go test -v "$@" -alsologtostderr -count=1 \ No newline at end of file + +echo "running tests for $PACKAGES" + +if [[ -z "$PACKAGES" ]]; then + echo "ERROR: PACKAGES is empty" + exit 1 +fi + +GOTESTSUM_ARGS=( + --format github-actions + --rerun-fails=3 + --rerun-fails-max-failures=10 + --rerun-fails-run-root-test + --format-hide-empty-pkg + --hide-summary=skipped +) + +if [[ -n "$JUNIT_OUTPUT" ]]; then + GOTESTSUM_ARGS+=("--junitfile" "$JUNIT_OUTPUT") +fi + +go tool gotestsum "${GOTESTSUM_ARGS[@]}" --packages "$PACKAGES" -- -v -count=1 "$@" -args -alsologtostderr diff --git a/tools/e2e_test_runner.sh b/tools/e2e_test_runner.sh index 1fc5c2cb558..8d97a89bbb4 100755 --- a/tools/e2e_test_runner.sh +++ b/tools/e2e_test_runner.sh @@ -33,7 +33,7 @@ source build.env if [[ -z $VT_GO_PARALLEL && -n $VT_GO_PARALLEL_VALUE ]]; then - VT_GO_PARALLEL="-p $VT_GO_PARALLEL_VALUE" + VT_GO_PARALLEL="-p $VT_GO_PARALLEL_VALUE" fi # All Go packages with test files. @@ -41,29 +41,29 @@ fi packages_with_tests=$(go list -f '{{if len .TestGoFiles}}{{.ImportPath}} {{join .TestGoFiles " "}}{{end}}{{if len .XTestGoFiles}}{{.ImportPath}} {{join .XTestGoFiles " "}}{{end}}' ./go/.../endtoend/... | sort) # Flaky tests have the suffix "_flaky_test.go". -all_except_flaky_and_cluster_tests=$(echo "$packages_with_tests" | grep -vE ".+ .+_flaky_test\.go" | grep -vE "go/test/endtoend" | cut -d" " -f1) +all_except_flaky_and_cluster_tests=$(echo "$packages_with_tests" | grep -vE ".+ .+_flaky_test\.go" | grep -vE "go/test/endtoend" | cut -d" " -f1) flaky_tests=$(echo "$packages_with_tests" | grep -E ".+ .+_flaky_test\.go" | grep -vE "go/test/endtoend" | cut -d" " -f1) # Run non-flaky tests. echo "$all_except_flaky_and_cluster_tests" | xargs go test -count=1 $VT_GO_PARALLEL if [ $? -ne 0 ]; then - echo "ERROR: Go unit tests failed. See above for errors." - echo - echo "This should NOT happen. Did you introduce a flaky unit test?" - echo "If so, please rename it to the suffix _flaky_test.go." - exit 1 + echo "ERROR: Go unit tests failed. See above for errors." + echo + echo "This should NOT happen. Did you introduce a flaky unit test?" + echo "If so, please rename it to the suffix _flaky_test.go." + exit 1 fi # Run flaky tests sequentially. Retry when necessary. for pkg in $flaky_tests; do - max_attempts=3 - attempt=1 - # Set a timeout because some tests may deadlock when they flake. - until go test -timeout 30s $VT_GO_PARALLEL $pkg; do - echo "FAILED (try $attempt/$max_attempts) in $pkg (return code $?). See above for errors." - if [ $((++attempt)) -gt $max_attempts ]; then - echo "ERROR: Flaky Go unit tests in package $pkg failed too often (after $max_attempts retries). Please reduce the flakiness." - exit 1 - fi - done + max_attempts=3 + attempt=1 + # Set a timeout because some tests may deadlock when they flake. + until go test -timeout 30s $VT_GO_PARALLEL $pkg; do + echo "FAILED (try $attempt/$max_attempts) in $pkg (return code $?). See above for errors." + if [ $((++attempt)) -gt $max_attempts ]; then + echo "ERROR: Flaky Go unit tests in package $pkg failed too often (after $max_attempts retries). Please reduce the flakiness." + exit 1 + fi + done done diff --git a/tools/run_codecov.sh b/tools/run_codecov.sh new file mode 100755 index 00000000000..c95a9157a7b --- /dev/null +++ b/tools/run_codecov.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# Run go test with coverage for one or more Go package directories. +# Usage: run_codecov.sh [dir ...] +# Example: run_codecov.sh go/vt/topo go/vt/vtctl +# +# With no arguments, runs coverage on all packages under go/. + +set -euo pipefail + +DIRS=("${@:-go}") + +COVERPKG=$(printf 'vitess.io/vitess/%s/...,' "${DIRS[@]}"); COVERPKG="${COVERPKG%,}" + +go test -count=1 \ + -covermode=atomic \ + -coverpkg="$COVERPKG" \ + -coverprofile=coverage.out \ + $(printf './%s/... ' "${DIRS[@]}") diff --git a/tools/unit_test_race.sh b/tools/unit_test_race.sh deleted file mode 100755 index 86fbcbcf995..00000000000 --- a/tools/unit_test_race.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -source build.env - -if [[ -z $VT_GO_PARALLEL && -n $VT_GO_PARALLEL_VALUE ]]; then - VT_GO_PARALLEL="-p $VT_GO_PARALLEL_VALUE" -fi - -# All Go packages with test files. -# Output per line: * - -packages_with_tests=$(go list -f '{{if len .TestGoFiles}}{{.ImportPath}} {{join .TestGoFiles " "}}{{end}}{{if len .XTestGoFiles}}{{.ImportPath}} {{join .XTestGoFiles " "}}{{end}}' ./go/... | sort) -if [[ "$VTEVALENGINETEST" == "1" ]]; then - packages_with_tests=$(echo "$packages_with_tests" | grep "evalengine") -fi - -if [[ "$VTEVALENGINETEST" == "0" ]]; then - packages_with_tests=$(echo "$packages_with_tests" | grep -v "evalengine") -fi - -# Flaky tests have the suffix "_flaky_test.go". -# Exclude endtoend tests -all_except_flaky_tests=$(echo "$packages_with_tests" | grep -vE ".+ .+_flaky_test\.go" | cut -d" " -f1 | grep -v "endtoend") -flaky_tests=$(echo "$packages_with_tests" | grep -E ".+ .+_flaky_test\.go" | cut -d" " -f1) - -# Run non-flaky tests. -echo "$all_except_flaky_tests" | xargs go test $VT_GO_PARALLEL -v -race -count=1 -if [ $? -ne 0 ]; then - echo "ERROR: Go unit tests failed. See above for errors." - echo - echo "This should NOT happen. Did you introduce a flaky unit test?" - echo "If so, please rename it to the suffix _flaky_test.go." - exit 1 -fi - -echo '# Flaky tests (3 attempts permitted)' - -# Run flaky tests sequentially. Retry when necessary. -for pkg in $flaky_tests; do - max_attempts=3 - attempt=1 - # Set a timeout because some tests may deadlock when they flake. - until go test -timeout 5m $VT_GO_PARALLEL $pkg -v -race -count=1; do - echo "FAILED (try $attempt/$max_attempts) in $pkg (return code $?). See above for errors." - if [ $((++attempt)) -gt $max_attempts ]; then - echo "ERROR: Flaky Go unit tests in package $pkg failed too often (after $max_attempts retries). Please reduce the flakiness." - exit 1 - fi - done -done - diff --git a/tools/unit_test_runner.sh b/tools/unit_test_runner.sh index efcd03aec0c..ba24e8332c8 100755 --- a/tools/unit_test_runner.sh +++ b/tools/unit_test_runner.sh @@ -1,30 +1,21 @@ #!/bin/bash # Copyright 2019 The Vitess Authors. -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -# Custom Go unit test runner which runs all unit tests in parallel except for -# known flaky unit tests. -# Flaky unit tests are run sequentially in the second phase and retried up to -# three times. - -# Why are there flaky unit tests? -# -# Some of the Go unit tests are inherently flaky e.g. because they use the -# real timer implementation and might fail when things take longer as usual. -# In particular, this happens when the system is under load and threads do not -# get scheduled as fast as usual. Then, the expected timings do not match. +# Custom Go unit test runner which runs all unit tests using gotestsum. Failed tests are +# automatically retried up to 3 times to handle flaky tests. # Set VT_GO_PARALLEL variable in the same way as the Makefile does. # We repeat this here because this script is called directly by test.go @@ -33,62 +24,55 @@ source build.env if [[ -z $VT_GO_PARALLEL && -n $VT_GO_PARALLEL_VALUE ]]; then - VT_GO_PARALLEL="-p $VT_GO_PARALLEL_VALUE" + VT_GO_PARALLEL="-p $VT_GO_PARALLEL_VALUE" +fi + +# Enable race detector if RACE=1 +RACE_FLAG="" +if [[ "$RACE" == "1" ]]; then + RACE_FLAG="-race" +fi + +# Enable race detector if RACE=1 +RACE_FLAG="" +if [[ "$RACE" == "1" ]]; then + RACE_FLAG="-race" fi # Mac makes long temp directories for os.TempDir(). MySQL can't connect to # sockets in those directories. Tell Golang to use /tmp/vttest_XXXXXX instead. kernel="$(uname -s)" case "$kernel" in - darwin|Darwin) - TMPDIR=${TMPDIR:-} - if [ -z "$TMPDIR" ]; then - TMPDIR="$(mktemp -d /tmp/vttest_XXXXXX)" - export TMPDIR - fi - echo "Using temporary directory for tests: $TMPDIR" - ;; +darwin | Darwin) + TMPDIR=${TMPDIR:-} + if [ -z "$TMPDIR" ]; then + TMPDIR="$(mktemp -d /tmp/vttest_XXXXXX)" + export TMPDIR + fi + echo "Using temporary directory for tests: $TMPDIR" + ;; esac -# All Go packages with test files. -# Output per line: * -packages_with_tests=$(go list -f '{{if len .TestGoFiles}}{{.ImportPath}} {{join .TestGoFiles " "}}{{end}}{{if len .XTestGoFiles}}{{.ImportPath}} {{join .XTestGoFiles " "}}{{end}}' ./go/... | sort) +# All Go packages with test files, excluding endtoend tests. +packages_with_tests=$(go list ./go/... | grep -v endtoend) if [[ "$VTEVALENGINETEST" == "1" ]]; then - packages_with_tests=$(echo "$packages_with_tests" | grep "evalengine") + packages_with_tests=$(echo "$packages_with_tests" | grep "evalengine") fi if [[ "$VTEVALENGINETEST" == "0" ]]; then - packages_with_tests=$(echo "$packages_with_tests" | grep -v "evalengine") + packages_with_tests=$(echo "$packages_with_tests" | grep -v "evalengine") fi -# Flaky tests have the suffix "_flaky_test.go". -# Exclude endtoend tests -all_except_flaky_tests=$(echo "$packages_with_tests" | grep -vE ".+ .+_flaky_test\.go" | cut -d" " -f1 | grep -v "endtoend") -flaky_tests=$(echo "$packages_with_tests" | grep -E ".+ .+_flaky_test\.go" | cut -d" " -f1) - -# Run non-flaky tests. -echo "$all_except_flaky_tests" | xargs go test $VT_GO_PARALLEL -v -count=1 -if [ $? -ne 0 ]; then - echo "ERROR: Go unit tests failed. See above for errors." - echo - echo "This should NOT happen. Did you introduce a flaky unit test?" - echo "If so, please rename it to the suffix _flaky_test.go." - exit 1 +# Build gotestsum args. Failed tests are retried up to 3 times, but if more than 10 tests fail +# initially we skip retries to avoid wasting time on a real widespread failure. +GOTESTSUM_ARGS="--format pkgname-and-test-fails --rerun-fails=3 --rerun-fails-max-failures=10 --rerun-fails-run-root-test --format-hide-empty-pkg --hide-summary=skipped" +if [[ -n "${JUNIT_OUTPUT:-}" ]]; then + GOTESTSUM_ARGS="$GOTESTSUM_ARGS --junitfile $JUNIT_OUTPUT" +fi +if [[ -n "${JSON_OUTPUT:-}" ]]; then + GOTESTSUM_ARGS="$GOTESTSUM_ARGS --jsonfile $JSON_OUTPUT" fi -echo '# Flaky tests (3 attempts permitted)' - -# Run flaky tests sequentially. Retry when necessary. -for pkg in $flaky_tests; do - max_attempts=3 - attempt=1 - # Set a timeout because some tests may deadlock when they flake. - until go test -timeout 5m $VT_GO_PARALLEL $pkg -v -count=1; do - echo "FAILED (try $attempt/$max_attempts) in $pkg (return code $?). See above for errors." - if [ $((++attempt)) -gt $max_attempts ]; then - echo "ERROR: Flaky Go unit tests in package $pkg failed too often (after $max_attempts retries). Please reduce the flakiness." - exit 1 - fi - done -done +# shellcheck disable=SC2086 +go tool gotestsum $GOTESTSUM_ARGS --packages="$packages_with_tests" -- $VT_GO_PARALLEL $RACE_FLAG -count=1 diff --git a/web/vtadmin/src/proto/vtadmin.d.ts b/web/vtadmin/src/proto/vtadmin.d.ts index 49da5095c26..9428c5d46eb 100644 --- a/web/vtadmin/src/proto/vtadmin.d.ts +++ b/web/vtadmin/src/proto/vtadmin.d.ts @@ -29791,6 +29791,9 @@ export namespace tabletmanagerdata { /** Properties of a DemotePrimaryRequest. */ interface IDemotePrimaryRequest { + + /** DemotePrimaryRequest force */ + force?: (boolean|null); } /** Represents a DemotePrimaryRequest. */ @@ -29802,6 +29805,9 @@ export namespace tabletmanagerdata { */ constructor(properties?: tabletmanagerdata.IDemotePrimaryRequest); + /** DemotePrimaryRequest force. */ + public force: boolean; + /** * Creates a new DemotePrimaryRequest instance using the specified properties. * @param [properties] Properties to set diff --git a/web/vtadmin/src/proto/vtadmin.js b/web/vtadmin/src/proto/vtadmin.js index 1c6897eb2f5..3f3ea08ba34 100644 --- a/web/vtadmin/src/proto/vtadmin.js +++ b/web/vtadmin/src/proto/vtadmin.js @@ -68087,6 +68087,7 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { * Properties of a DemotePrimaryRequest. * @memberof tabletmanagerdata * @interface IDemotePrimaryRequest + * @property {boolean|null} [force] DemotePrimaryRequest force */ /** @@ -68104,6 +68105,14 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { this[keys[i]] = properties[keys[i]]; } + /** + * DemotePrimaryRequest force. + * @member {boolean} force + * @memberof tabletmanagerdata.DemotePrimaryRequest + * @instance + */ + DemotePrimaryRequest.prototype.force = false; + /** * Creates a new DemotePrimaryRequest instance using the specified properties. * @function create @@ -68128,6 +68137,8 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { DemotePrimaryRequest.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); + if (message.force != null && Object.hasOwnProperty.call(message, "force")) + writer.uint32(/* id 1, wireType 0 =*/8).bool(message.force); return writer; }; @@ -68162,6 +68173,10 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { while (reader.pos < end) { let tag = reader.uint32(); switch (tag >>> 3) { + case 1: { + message.force = reader.bool(); + break; + } default: reader.skipType(tag & 7); break; @@ -68197,6 +68212,9 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { DemotePrimaryRequest.verify = function verify(message) { if (typeof message !== "object" || message === null) return "object expected"; + if (message.force != null && message.hasOwnProperty("force")) + if (typeof message.force !== "boolean") + return "force: boolean expected"; return null; }; @@ -68211,7 +68229,10 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { DemotePrimaryRequest.fromObject = function fromObject(object) { if (object instanceof $root.tabletmanagerdata.DemotePrimaryRequest) return object; - return new $root.tabletmanagerdata.DemotePrimaryRequest(); + let message = new $root.tabletmanagerdata.DemotePrimaryRequest(); + if (object.force != null) + message.force = Boolean(object.force); + return message; }; /** @@ -68223,8 +68244,15 @@ export const tabletmanagerdata = $root.tabletmanagerdata = (() => { * @param {$protobuf.IConversionOptions} [options] Conversion options * @returns {Object.} Plain object */ - DemotePrimaryRequest.toObject = function toObject() { - return {}; + DemotePrimaryRequest.toObject = function toObject(message, options) { + if (!options) + options = {}; + let object = {}; + if (options.defaults) + object.force = false; + if (message.force != null && message.hasOwnProperty("force")) + object.force = message.force; + return object; }; /**