diff --git a/.github/workflows/assign_milestone.yml b/.github/workflows/assign_milestone.yml index 52542ad4c90..443d28e80d6 100644 --- a/.github/workflows/assign_milestone.yml +++ b/.github/workflows/assign_milestone.yml @@ -20,7 +20,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Checkout code uses: actions/checkout@v4 diff --git a/.github/workflows/docker_build_images.yml b/.github/workflows/build_docker_images.yml similarity index 62% rename from .github/workflows/docker_build_images.yml rename to .github/workflows/build_docker_images.yml index 59885351808..da1e7c63887 100644 --- a/.github/workflows/docker_build_images.yml +++ b/.github/workflows/build_docker_images.yml @@ -1,22 +1,101 @@ -name: Docker Build Images +name: Build Docker Images on: + pull_request: push: branches: - main tags: - - 'v[2-9][0-9]*.*' # run only on tags greater or equal to v20.0.0 where this new way of building docker image was changed + - '*' concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Docker Build Images (v20+)') + group: format('{0}-{1}', ${{ github.ref }}, 'Build Docker Images') cancel-in-progress: true permissions: read-all jobs: + push: + name: Set push variable + runs-on: ubuntu-20.04 + if: github.repository == 'vitessio/vitess' + outputs: + push: ${{ steps.push.outputs.push }} + + steps: + - name: Set push variable + id: push + run: | + push='false' + if [[ "${{github.event.pull_request}}" == "" ]]; then + push='true' + fi + echo Push ${push} + echo "push=${push}" >> $GITHUB_OUTPUT + + build_and_push_vttestserver: + name: Build and push vttestserver + runs-on: gh-hosted-runners-16cores-1 + if: github.repository == 'vitessio/vitess' && needs.push.result == 'success' + needs: + - push + + strategy: + fail-fast: true + matrix: + branch: [ mysql80 ] + + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Login to Docker Hub + if: needs.push.outputs.push == 'true' + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Set Dockerfile path + run: | + echo "DOCKERFILE=./docker/vttestserver/Dockerfile.${{ matrix.branch }}" >> $GITHUB_ENV + + - name: Build and push on main + if: startsWith(github.ref, 'refs/tags/') == false + uses: docker/build-push-action@v5 + with: + context: . + file: ${{ env.DOCKERFILE }} + push: ${{ needs.push.outputs.push }} + tags: vitess/vttestserver:${{ matrix.branch }} + + ###### + # All code below only applies to new tags + ###### + - name: Get the Git tag + if: startsWith(github.ref, 'refs/tags/') + run: echo "TAG_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV + + - name: Set Docker tag name + if: startsWith(github.ref, 'refs/tags/') + run: | + echo "DOCKER_TAG=vitess/vttestserver:${TAG_NAME}-${{ matrix.branch }}" >> $GITHUB_ENV + + - name: Build and push on tags + if: startsWith(github.ref, 'refs/tags/') + uses: docker/build-push-action@v5 + with: + context: . + file: ${{ env.DOCKERFILE }} + push: true + tags: ${{ env.DOCKER_TAG }} + + build_and_push_lite: - name: Build and push vitess/lite Docker images + name: Build and push lite runs-on: gh-hosted-runners-16cores-1 - if: github.repository == 'vitessio/vitess' + if: github.repository == 'vitessio/vitess' && needs.push.result == 'success' + needs: + - push strategy: fail-fast: true @@ -28,6 +107,7 @@ jobs: uses: actions/checkout@v4 - name: Login to Docker Hub + if: needs.push.outputs.push == 'true' uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} @@ -42,12 +122,12 @@ jobs: fi - name: Build and push on main - if: github.ref == 'refs/heads/main' + if: startsWith(github.ref, 'refs/tags/') == false uses: docker/build-push-action@v5 with: context: . file: ${{ env.DOCKERFILE }} - push: true + push: ${{ needs.push.outputs.push }} tags: vitess/lite:${{ matrix.branch }} ###### @@ -76,22 +156,25 @@ jobs: tags: ${{ env.DOCKER_TAG }} build_and_push_components: - name: Build and push vitess components Docker images - needs: build_and_push_lite + name: Build and push runs-on: gh-hosted-runners-16cores-1 - if: github.repository == 'vitessio/vitess' + if: github.repository == 'vitessio/vitess' && needs.push.result == 'success' && needs.build_and_push_lite.result == 'success' + needs: + - push + - build_and_push_lite strategy: fail-fast: true matrix: debian: [ bullseye, bookworm ] - component: [ vtadmin, vtorc, vtgate, vttablet, mysqlctld, mysqlctl, vtctl, vtctlclient, vtctld, logrotate, logtail, vtbackup, vtexplain ] + component: [ vtadmin, vtorc, vtgate, vttablet, mysqlctld, mysqlctl, vtctl, vtctlclient, vtctld, vtctldclient, logrotate, logtail, vtbackup, vtexplain ] steps: - name: Check out code uses: actions/checkout@v4 - name: Login to Docker Hub + if: needs.push.outputs.push == 'true' uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} @@ -102,22 +185,22 @@ jobs: echo "DOCKER_CTX=./docker/binaries/${{ matrix.component }}" >> $GITHUB_ENV - name: Build and push on main latest tag - if: github.ref == 'refs/heads/main' && matrix.debian == 'bookworm' + if: startsWith(github.ref, 'refs/tags/') == false && matrix.debian == 'bookworm' uses: docker/build-push-action@v5 with: context: ${{ env.DOCKER_CTX }} - push: true + push: ${{ needs.push.outputs.push }} tags: vitess/${{ matrix.component }}:latest build-args: | VT_BASE_VER=latest DEBIAN_VER=${{ matrix.debian }}-slim - name: Build and push on main debian specific tag - if: github.ref == 'refs/heads/main' + if: startsWith(github.ref, 'refs/tags/') == false uses: docker/build-push-action@v5 with: context: ${{ env.DOCKER_CTX }} - push: true + push: ${{ needs.push.outputs.push }} tags: vitess/${{ matrix.component }}:latest-${{ matrix.debian }} build-args: | VT_BASE_VER=latest diff --git a/.github/workflows/check_make_vtadmin_authz_testgen.yml b/.github/workflows/check_make_vtadmin_authz_testgen.yml index 182748ef5f7..3502c973632 100644 --- a/.github/workflows/check_make_vtadmin_authz_testgen.yml +++ b/.github/workflows/check_make_vtadmin_authz_testgen.yml @@ -50,7 +50,7 @@ jobs: uses: actions/setup-go@v5 if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.vtadmin_changes == 'true' with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Tune the OS if: steps.skip-workflow.outputs.skip-workflow == 'false' && 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 f8694ae93bb..61c83168c23 100644 --- a/.github/workflows/check_make_vtadmin_web_proto.yml +++ b/.github/workflows/check_make_vtadmin_web_proto.yml @@ -52,7 +52,7 @@ jobs: uses: actions/setup-go@v5 if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.proto_changes == 'true' with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Setup Node if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.proto_changes == 'true' diff --git a/.github/workflows/cluster_endtoend_12.yml b/.github/workflows/cluster_endtoend_12.yml index 1049077d9d8..3c984f4d403 100644 --- a/.github/workflows/cluster_endtoend_12.yml +++ b/.github/workflows/cluster_endtoend_12.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_13.yml b/.github/workflows/cluster_endtoend_13.yml index f79e0c7b0fa..c1a92a8a4b7 100644 --- a/.github/workflows/cluster_endtoend_13.yml +++ b/.github/workflows/cluster_endtoend_13.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_15.yml b/.github/workflows/cluster_endtoend_15.yml index ec3b339ff40..3d2881b7676 100644 --- a/.github/workflows/cluster_endtoend_15.yml +++ b/.github/workflows/cluster_endtoend_15.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_18.yml b/.github/workflows/cluster_endtoend_18.yml index f80566e9f34..1f35fbf0431 100644 --- a/.github/workflows/cluster_endtoend_18.yml +++ b/.github/workflows/cluster_endtoend_18.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_21.yml b/.github/workflows/cluster_endtoend_21.yml index f6979a49abc..d47ad86dfd1 100644 --- a/.github/workflows/cluster_endtoend_21.yml +++ b/.github/workflows/cluster_endtoend_21.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_backup_pitr.yml b/.github/workflows/cluster_endtoend_backup_pitr.yml index 847fd84ae08..560b3029158 100644 --- a/.github/workflows/cluster_endtoend_backup_pitr.yml +++ b/.github/workflows/cluster_endtoend_backup_pitr.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_backup_pitr_xtrabackup.yml b/.github/workflows/cluster_endtoend_backup_pitr_xtrabackup.yml index a2a83812c23..1891d1a75d2 100644 --- a/.github/workflows/cluster_endtoend_backup_pitr_xtrabackup.yml +++ b/.github/workflows/cluster_endtoend_backup_pitr_xtrabackup.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' diff --git a/.github/workflows/cluster_endtoend_ers_prs_newfeatures_heavy.yml b/.github/workflows/cluster_endtoend_ers_prs_newfeatures_heavy.yml index 401185596d7..a3f41d78264 100644 --- a/.github/workflows/cluster_endtoend_ers_prs_newfeatures_heavy.yml +++ b/.github/workflows/cluster_endtoend_ers_prs_newfeatures_heavy.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_mysql80.yml b/.github/workflows/cluster_endtoend_mysql80.yml index 8cbbdfb4607..f5dc2abad55 100644 --- a/.github/workflows/cluster_endtoend_mysql80.yml +++ b/.github/workflows/cluster_endtoend_mysql80.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_mysql_server_vault.yml b/.github/workflows/cluster_endtoend_mysql_server_vault.yml index e6a75d6b70b..d41b6f014f5 100644 --- a/.github/workflows/cluster_endtoend_mysql_server_vault.yml +++ b/.github/workflows/cluster_endtoend_mysql_server_vault.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_onlineddl_revert.yml b/.github/workflows/cluster_endtoend_onlineddl_revert.yml index 76766f1bfa6..10e6c4e670f 100644 --- a/.github/workflows/cluster_endtoend_onlineddl_revert.yml +++ b/.github/workflows/cluster_endtoend_onlineddl_revert.yml @@ -74,7 +74,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -97,7 +97,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_onlineddl_scheduler.yml b/.github/workflows/cluster_endtoend_onlineddl_scheduler.yml index 0c685c4599c..4b76d62b923 100644 --- a/.github/workflows/cluster_endtoend_onlineddl_scheduler.yml +++ b/.github/workflows/cluster_endtoend_onlineddl_scheduler.yml @@ -74,7 +74,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -97,7 +97,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_onlineddl_vrepl.yml b/.github/workflows/cluster_endtoend_onlineddl_vrepl.yml index a63ad54c2c3..f2e7d2939f0 100644 --- a/.github/workflows/cluster_endtoend_onlineddl_vrepl.yml +++ b/.github/workflows/cluster_endtoend_onlineddl_vrepl.yml @@ -74,7 +74,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -97,7 +97,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_onlineddl_vrepl_stress.yml b/.github/workflows/cluster_endtoend_onlineddl_vrepl_stress.yml index 20c378695e0..7574a4bcea2 100644 --- a/.github/workflows/cluster_endtoend_onlineddl_vrepl_stress.yml +++ b/.github/workflows/cluster_endtoend_onlineddl_vrepl_stress.yml @@ -74,7 +74,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -97,7 +97,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_onlineddl_vrepl_stress_suite.yml b/.github/workflows/cluster_endtoend_onlineddl_vrepl_stress_suite.yml index 3dfcd2cc99b..c6576ed2927 100644 --- a/.github/workflows/cluster_endtoend_onlineddl_vrepl_stress_suite.yml +++ b/.github/workflows/cluster_endtoend_onlineddl_vrepl_stress_suite.yml @@ -74,7 +74,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -97,7 +97,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_onlineddl_vrepl_suite.yml b/.github/workflows/cluster_endtoend_onlineddl_vrepl_suite.yml index 92dab0a55f1..ce528f797ea 100644 --- a/.github/workflows/cluster_endtoend_onlineddl_vrepl_suite.yml +++ b/.github/workflows/cluster_endtoend_onlineddl_vrepl_suite.yml @@ -74,7 +74,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -97,7 +97,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_schemadiff_vrepl.yml b/.github/workflows/cluster_endtoend_schemadiff_vrepl.yml index be568217503..07224c415db 100644 --- a/.github/workflows/cluster_endtoend_schemadiff_vrepl.yml +++ b/.github/workflows/cluster_endtoend_schemadiff_vrepl.yml @@ -74,7 +74,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -97,7 +97,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_tabletmanager_consul.yml b/.github/workflows/cluster_endtoend_tabletmanager_consul.yml index bf6c8e8e87c..e80c8598f44 100644 --- a/.github/workflows/cluster_endtoend_tabletmanager_consul.yml +++ b/.github/workflows/cluster_endtoend_tabletmanager_consul.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_tabletmanager_tablegc.yml b/.github/workflows/cluster_endtoend_tabletmanager_tablegc.yml index 4d63b3a0cf1..14973bd1f2d 100644 --- a/.github/workflows/cluster_endtoend_tabletmanager_tablegc.yml +++ b/.github/workflows/cluster_endtoend_tabletmanager_tablegc.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_tabletmanager_throttler_topo.yml b/.github/workflows/cluster_endtoend_tabletmanager_throttler_topo.yml index 700e78ac55d..a647e443e61 100644 --- a/.github/workflows/cluster_endtoend_tabletmanager_throttler_topo.yml +++ b/.github/workflows/cluster_endtoend_tabletmanager_throttler_topo.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_topo_connection_cache.yml b/.github/workflows/cluster_endtoend_topo_connection_cache.yml index 3119d085c18..37c932621d9 100644 --- a/.github/workflows/cluster_endtoend_topo_connection_cache.yml +++ b/.github/workflows/cluster_endtoend_topo_connection_cache.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vreplication_across_db_versions.yml b/.github/workflows/cluster_endtoend_vreplication_across_db_versions.yml index 4d622675dcb..9116e1d3fc2 100644 --- a/.github/workflows/cluster_endtoend_vreplication_across_db_versions.yml +++ b/.github/workflows/cluster_endtoend_vreplication_across_db_versions.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vreplication_basic.yml b/.github/workflows/cluster_endtoend_vreplication_basic.yml index 1c0b8f922d8..7843ad05192 100644 --- a/.github/workflows/cluster_endtoend_vreplication_basic.yml +++ b/.github/workflows/cluster_endtoend_vreplication_basic.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vreplication_cellalias.yml b/.github/workflows/cluster_endtoend_vreplication_cellalias.yml index 96f30d4835a..9a179229f1e 100644 --- a/.github/workflows/cluster_endtoend_vreplication_cellalias.yml +++ b/.github/workflows/cluster_endtoend_vreplication_cellalias.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vreplication_copy_parallel.yml b/.github/workflows/cluster_endtoend_vreplication_copy_parallel.yml index aae735aa7ec..37eafd948c4 100644 --- a/.github/workflows/cluster_endtoend_vreplication_copy_parallel.yml +++ b/.github/workflows/cluster_endtoend_vreplication_copy_parallel.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vreplication_foreign_key_stress.yml b/.github/workflows/cluster_endtoend_vreplication_foreign_key_stress.yml index f0ef175a170..9fb4287e0b1 100644 --- a/.github/workflows/cluster_endtoend_vreplication_foreign_key_stress.yml +++ b/.github/workflows/cluster_endtoend_vreplication_foreign_key_stress.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vreplication_mariadb_to_mysql.yml b/.github/workflows/cluster_endtoend_vreplication_mariadb_to_mysql.yml index d2bb0a3d099..86f2fa69e30 100644 --- a/.github/workflows/cluster_endtoend_vreplication_mariadb_to_mysql.yml +++ b/.github/workflows/cluster_endtoend_vreplication_mariadb_to_mysql.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vreplication_migrate_vdiff2_convert_tz.yml b/.github/workflows/cluster_endtoend_vreplication_migrate_vdiff2_convert_tz.yml index 1f6dfb6b7ef..d7d385f1e9f 100644 --- a/.github/workflows/cluster_endtoend_vreplication_migrate_vdiff2_convert_tz.yml +++ b/.github/workflows/cluster_endtoend_vreplication_migrate_vdiff2_convert_tz.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vreplication_multi_tenant.yml b/.github/workflows/cluster_endtoend_vreplication_multi_tenant.yml index f44ddf1d27f..e4e5ee17452 100644 --- a/.github/workflows/cluster_endtoend_vreplication_multi_tenant.yml +++ b/.github/workflows/cluster_endtoend_vreplication_multi_tenant.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vreplication_partial_movetables_and_materialize.yml b/.github/workflows/cluster_endtoend_vreplication_partial_movetables_and_materialize.yml index a1074fa2553..a7b2c31b420 100644 --- a/.github/workflows/cluster_endtoend_vreplication_partial_movetables_and_materialize.yml +++ b/.github/workflows/cluster_endtoend_vreplication_partial_movetables_and_materialize.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vreplication_v2.yml b/.github/workflows/cluster_endtoend_vreplication_v2.yml index 1ee0bc3d5d0..fb1247fabfb 100644 --- a/.github/workflows/cluster_endtoend_vreplication_v2.yml +++ b/.github/workflows/cluster_endtoend_vreplication_v2.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vstream.yml b/.github/workflows/cluster_endtoend_vstream.yml index 3f1399eece4..5d13e6d3a41 100644 --- a/.github/workflows/cluster_endtoend_vstream.yml +++ b/.github/workflows/cluster_endtoend_vstream.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vtbackup.yml b/.github/workflows/cluster_endtoend_vtbackup.yml index ef96875687a..9bf411cc328 100644 --- a/.github/workflows/cluster_endtoend_vtbackup.yml +++ b/.github/workflows/cluster_endtoend_vtbackup.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vtctlbackup_sharded_clustertest_heavy.yml b/.github/workflows/cluster_endtoend_vtctlbackup_sharded_clustertest_heavy.yml index 63574ed2858..09fbfa8e451 100644 --- a/.github/workflows/cluster_endtoend_vtctlbackup_sharded_clustertest_heavy.yml +++ b/.github/workflows/cluster_endtoend_vtctlbackup_sharded_clustertest_heavy.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vtgate_concurrentdml.yml b/.github/workflows/cluster_endtoend_vtgate_concurrentdml.yml index ca050f090eb..b8cb2d77ad9 100644 --- a/.github/workflows/cluster_endtoend_vtgate_concurrentdml.yml +++ b/.github/workflows/cluster_endtoend_vtgate_concurrentdml.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vtgate_foreignkey_stress.yml b/.github/workflows/cluster_endtoend_vtgate_foreignkey_stress.yml index edcca203c4a..5ad1025debd 100644 --- a/.github/workflows/cluster_endtoend_vtgate_foreignkey_stress.yml +++ b/.github/workflows/cluster_endtoend_vtgate_foreignkey_stress.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vtgate_gen4.yml b/.github/workflows/cluster_endtoend_vtgate_gen4.yml index 8f0071a4815..43bbe666186 100644 --- a/.github/workflows/cluster_endtoend_vtgate_gen4.yml +++ b/.github/workflows/cluster_endtoend_vtgate_gen4.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vtgate_general_heavy.yml b/.github/workflows/cluster_endtoend_vtgate_general_heavy.yml index 37b318650a9..d63edf72ae7 100644 --- a/.github/workflows/cluster_endtoend_vtgate_general_heavy.yml +++ b/.github/workflows/cluster_endtoend_vtgate_general_heavy.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vtgate_godriver.yml b/.github/workflows/cluster_endtoend_vtgate_godriver.yml index 79daa318661..c7c2d0bf494 100644 --- a/.github/workflows/cluster_endtoend_vtgate_godriver.yml +++ b/.github/workflows/cluster_endtoend_vtgate_godriver.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vtgate_partial_keyspace.yml b/.github/workflows/cluster_endtoend_vtgate_partial_keyspace.yml index fc2540b5809..3510e8f2144 100644 --- a/.github/workflows/cluster_endtoend_vtgate_partial_keyspace.yml +++ b/.github/workflows/cluster_endtoend_vtgate_partial_keyspace.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vtgate_queries.yml b/.github/workflows/cluster_endtoend_vtgate_queries.yml index 8813a2ca6ac..40f20e2177e 100644 --- a/.github/workflows/cluster_endtoend_vtgate_queries.yml +++ b/.github/workflows/cluster_endtoend_vtgate_queries.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vtgate_readafterwrite.yml b/.github/workflows/cluster_endtoend_vtgate_readafterwrite.yml index e4863b23353..c913e05810a 100644 --- a/.github/workflows/cluster_endtoend_vtgate_readafterwrite.yml +++ b/.github/workflows/cluster_endtoend_vtgate_readafterwrite.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vtgate_reservedconn.yml b/.github/workflows/cluster_endtoend_vtgate_reservedconn.yml index 0296b040b3a..aa173b32ca3 100644 --- a/.github/workflows/cluster_endtoend_vtgate_reservedconn.yml +++ b/.github/workflows/cluster_endtoend_vtgate_reservedconn.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vtgate_schema.yml b/.github/workflows/cluster_endtoend_vtgate_schema.yml index 5d1c36c0e3f..5a5ab725b8a 100644 --- a/.github/workflows/cluster_endtoend_vtgate_schema.yml +++ b/.github/workflows/cluster_endtoend_vtgate_schema.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vtgate_schema_tracker.yml b/.github/workflows/cluster_endtoend_vtgate_schema_tracker.yml index 1436f891744..00244b8223a 100644 --- a/.github/workflows/cluster_endtoend_vtgate_schema_tracker.yml +++ b/.github/workflows/cluster_endtoend_vtgate_schema_tracker.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vtgate_tablet_healthcheck_cache.yml b/.github/workflows/cluster_endtoend_vtgate_tablet_healthcheck_cache.yml index f04fce0e634..ee14848cd79 100644 --- a/.github/workflows/cluster_endtoend_vtgate_tablet_healthcheck_cache.yml +++ b/.github/workflows/cluster_endtoend_vtgate_tablet_healthcheck_cache.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vtgate_topo.yml b/.github/workflows/cluster_endtoend_vtgate_topo.yml index 5954f98e1ac..9517ad965b5 100644 --- a/.github/workflows/cluster_endtoend_vtgate_topo.yml +++ b/.github/workflows/cluster_endtoend_vtgate_topo.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vtgate_topo_consul.yml b/.github/workflows/cluster_endtoend_vtgate_topo_consul.yml index a67db05bde6..6d585fb41f3 100644 --- a/.github/workflows/cluster_endtoend_vtgate_topo_consul.yml +++ b/.github/workflows/cluster_endtoend_vtgate_topo_consul.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vtgate_topo_etcd.yml b/.github/workflows/cluster_endtoend_vtgate_topo_etcd.yml index 190c934ac5f..d1ae0e96afd 100644 --- a/.github/workflows/cluster_endtoend_vtgate_topo_etcd.yml +++ b/.github/workflows/cluster_endtoend_vtgate_topo_etcd.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vtgate_transaction.yml b/.github/workflows/cluster_endtoend_vtgate_transaction.yml index a3210624126..50f6a57b551 100644 --- a/.github/workflows/cluster_endtoend_vtgate_transaction.yml +++ b/.github/workflows/cluster_endtoend_vtgate_transaction.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update @@ -136,7 +136,7 @@ jobs: set -exo pipefail # run the tests however you normally do, then produce a JUnit XML file - eatmydata -- go run test.go -docker=false -follow -shard vtgate_transaction | tee -a output.txt | go-junit-report -set-exit-code > report.xml + eatmydata -- 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: Print test output and Record test result in launchable if PR is not a draft if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() diff --git a/.github/workflows/cluster_endtoend_vtgate_unsharded.yml b/.github/workflows/cluster_endtoend_vtgate_unsharded.yml index 30dce8c0d6c..b0d8348aaab 100644 --- a/.github/workflows/cluster_endtoend_vtgate_unsharded.yml +++ b/.github/workflows/cluster_endtoend_vtgate_unsharded.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vtgate_vindex_heavy.yml b/.github/workflows/cluster_endtoend_vtgate_vindex_heavy.yml index 0a80cb59e88..330ee506517 100644 --- a/.github/workflows/cluster_endtoend_vtgate_vindex_heavy.yml +++ b/.github/workflows/cluster_endtoend_vtgate_vindex_heavy.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vtgate_vschema.yml b/.github/workflows/cluster_endtoend_vtgate_vschema.yml index dbc55e05eaf..4ddf20fa9c5 100644 --- a/.github/workflows/cluster_endtoend_vtgate_vschema.yml +++ b/.github/workflows/cluster_endtoend_vtgate_vschema.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vtorc.yml b/.github/workflows/cluster_endtoend_vtorc.yml index 04f3ac33a30..77493692395 100644 --- a/.github/workflows/cluster_endtoend_vtorc.yml +++ b/.github/workflows/cluster_endtoend_vtorc.yml @@ -82,7 +82,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -105,7 +105,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_vttablet_prscomplex.yml b/.github/workflows/cluster_endtoend_vttablet_prscomplex.yml index 451cf6013cc..58ff4074c0c 100644 --- a/.github/workflows/cluster_endtoend_vttablet_prscomplex.yml +++ b/.github/workflows/cluster_endtoend_vttablet_prscomplex.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -96,7 +96,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update diff --git a/.github/workflows/cluster_endtoend_xb_backup.yml b/.github/workflows/cluster_endtoend_xb_backup.yml index 551e98116d5..5a8acc66d8c 100644 --- a/.github/workflows/cluster_endtoend_xb_backup.yml +++ b/.github/workflows/cluster_endtoend_xb_backup.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' diff --git a/.github/workflows/cluster_endtoend_xb_recovery.yml b/.github/workflows/cluster_endtoend_xb_recovery.yml index 1648f4d8fb6..94fb11320fb 100644 --- a/.github/workflows/cluster_endtoend_xb_recovery.yml +++ b/.github/workflows/cluster_endtoend_xb_recovery.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index c277733a04a..3015309d2c2 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -32,7 +32,7 @@ jobs: if: steps.changes.outputs.changed_files == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.changes.outputs.changed_files == 'true' diff --git a/.github/workflows/codeql_analysis.yml b/.github/workflows/codeql_analysis.yml index c822cbee089..d6d5ea6335d 100644 --- a/.github/workflows/codeql_analysis.yml +++ b/.github/workflows/codeql_analysis.yml @@ -32,7 +32,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL @@ -59,7 +59,7 @@ jobs: sudo rm -rf /etc/mysql # Install mysql80 sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get update @@ -75,12 +75,6 @@ jobs: # install JUnit report formatter go install github.com/vitessio/go-junit-report@HEAD - 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 apt-get update - sudo apt-get install -y percona-xtrabackup-24 - - name: Building binaries timeout-minutes: 30 run: | diff --git a/.github/workflows/create_release.yml b/.github/workflows/create_release.yml index 33a7df3208c..cb393141ae3 100644 --- a/.github/workflows/create_release.yml +++ b/.github/workflows/create_release.yml @@ -20,7 +20,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Setup node uses: actions/setup-node@v4 diff --git a/.github/workflows/docker_build_vttestserver.yml b/.github/workflows/docker_build_vttestserver.yml deleted file mode 100644 index 1d157eef921..00000000000 --- a/.github/workflows/docker_build_vttestserver.yml +++ /dev/null @@ -1,65 +0,0 @@ -name: Docker Build vttestserver -on: - push: - branches: - - main - tags: - - '*' - -concurrency: - group: format('{0}-{1}', ${{ github.ref }}, 'Docker Build vttestserver') - cancel-in-progress: true - -permissions: read-all - -jobs: - build_and_push: - name: Build and push vitess/vttestserver Docker images - runs-on: gh-hosted-runners-16cores-1 - if: github.repository == 'vitessio/vitess' - - strategy: - fail-fast: true - matrix: - branch: [ mysql80 ] - - steps: - - name: Check out code - uses: actions/checkout@v4 - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Set Dockerfile path - run: | - echo "DOCKERFILE=./docker/vttestserver/Dockerfile.${{ matrix.branch }}" >> $GITHUB_ENV - - - name: Build and push on main - if: github.ref == 'refs/heads/main' - uses: docker/build-push-action@v5 - with: - context: . - file: ${{ env.DOCKERFILE }} - push: true - tags: vitess/vttestserver:${{ matrix.branch }} - - - name: Get the Git tag - if: startsWith(github.ref, 'refs/tags/') - run: echo "TAG_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV - - - name: Set Docker tag name - if: startsWith(github.ref, 'refs/tags/') - run: | - echo "DOCKER_TAG=vitess/vttestserver:${TAG_NAME}-${{ matrix.branch }}" >> $GITHUB_ENV - - - name: Build and push on tags - if: startsWith(github.ref, 'refs/tags/') - uses: docker/build-push-action@v5 - with: - context: . - file: ${{ env.DOCKERFILE }} - push: true - tags: ${{ env.DOCKER_TAG }} diff --git a/.github/workflows/docker_test_cluster_10.yml b/.github/workflows/docker_test_cluster_10.yml index ff3bbaf6e68..2a1c1050461 100644 --- a/.github/workflows/docker_test_cluster_10.yml +++ b/.github/workflows/docker_test_cluster_10.yml @@ -54,7 +54,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Tune the OS if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' diff --git a/.github/workflows/docker_test_cluster_25.yml b/.github/workflows/docker_test_cluster_25.yml index 9e60e3a4b50..ba73f50252b 100644 --- a/.github/workflows/docker_test_cluster_25.yml +++ b/.github/workflows/docker_test_cluster_25.yml @@ -54,7 +54,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Tune the OS if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' diff --git a/.github/workflows/e2e_race.yml b/.github/workflows/e2e_race.yml index 61e7349790d..7819ab3ae90 100644 --- a/.github/workflows/e2e_race.yml +++ b/.github/workflows/e2e_race.yml @@ -52,7 +52,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Tune the OS if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -65,7 +65,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get update diff --git a/.github/workflows/endtoend.yml b/.github/workflows/endtoend.yml index ef390dae4eb..783d3305fc8 100644 --- a/.github/workflows/endtoend.yml +++ b/.github/workflows/endtoend.yml @@ -52,7 +52,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Tune the OS if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' diff --git a/.github/workflows/local_example.yml b/.github/workflows/local_example.yml index 20c8e0ab1d3..851db91df22 100644 --- a/.github/workflows/local_example.yml +++ b/.github/workflows/local_example.yml @@ -57,13 +57,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.examples == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 - - - uses: actions/setup-node@v4 - if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.examples == 'true' - with: - # node-version should match package.json - node-version: '20.12.2' + go-version: 1.22.5 - name: Tune the OS if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.examples == 'true' @@ -77,7 +71,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get update diff --git a/.github/workflows/region_example.yml b/.github/workflows/region_example.yml index f73e8769c9a..b10abe415d7 100644 --- a/.github/workflows/region_example.yml +++ b/.github/workflows/region_example.yml @@ -57,13 +57,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.examples == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 - - - uses: actions/setup-node@v4 - if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.examples == 'true' - with: - # node-version should match package.json - node-version: '20.12.2' + go-version: 1.22.5 - name: Tune the OS if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.examples == 'true' @@ -77,7 +71,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get update diff --git a/.github/workflows/static_checks_etc.yml b/.github/workflows/static_checks_etc.yml index 65e29b67ba6..75fb01e487e 100644 --- a/.github/workflows/static_checks_etc.yml +++ b/.github/workflows/static_checks_etc.yml @@ -91,6 +91,16 @@ jobs: - 'bootstrap.sh' - 'misc/git/hooks/asthelpers' - '.github/workflows/static_checks_etc.yml' + astfmt: + - 'go/tools/astfmtgen/**' + - 'go/vt/sqlparser/**' + - 'Makefile' + - 'build.env' + - 'go.sum' + - 'go.mod' + - 'tools/**' + - 'bootstrap.sh' + - '.github/workflows/static_checks_etc.yml' end_to_end: - 'docker/**' - 'test.go' @@ -113,7 +123,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && (steps.changes.outputs.go_files == 'true' || steps.changes.outputs.parser_changes == 'true' || steps.changes.outputs.proto_changes == 'true') uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Tune the OS if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.go_files == 'true' @@ -168,6 +178,11 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && (steps.changes.outputs.visitor == 'true' || steps.changes.outputs.go_files == 'true') run: | misc/git/hooks/asthelpers || exit 1 + + - name: check_ast_format_fast + if: steps.skip-workflow.outputs.skip-workflow == 'false' && (steps.changes.outputs.astfmt == 'true' || steps.changes.outputs.go_files == 'true') + run: | + ./tools/check_astfmtgen.sh || exit 1 - name: run ensure_bootstrap_version if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' diff --git a/.github/workflows/unit_race.yml b/.github/workflows/unit_race.yml index 277a29df216..3f6de3eb6f8 100644 --- a/.github/workflows/unit_race.yml +++ b/.github/workflows/unit_race.yml @@ -69,7 +69,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' diff --git a/.github/workflows/unit_race_evalengine.yml b/.github/workflows/unit_race_evalengine.yml index 02ac005a0a5..77ada6729bd 100644 --- a/.github/workflows/unit_race_evalengine.yml +++ b/.github/workflows/unit_race_evalengine.yml @@ -69,7 +69,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' diff --git a/.github/workflows/unit_test_evalengine_mysql57.yml b/.github/workflows/unit_test_evalengine_mysql57.yml index 1a979b122a3..313e076177c 100644 --- a/.github/workflows/unit_test_evalengine_mysql57.yml +++ b/.github/workflows/unit_test_evalengine_mysql57.yml @@ -71,7 +71,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' @@ -102,9 +102,8 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb - # mysql57 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb # Bionic packages are still compatible for Jammy since there's no MySQL 5.7 # packages for Jammy. echo mysql-apt-config mysql-apt-config/repo-codename select bionic | sudo debconf-set-selections @@ -112,7 +111,7 @@ jobs: sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update sudo DEBIAN_FRONTEND="noninteractive" apt-get -qq install -y mysql-client=5.7* mysql-community-server=5.7* mysql-server=5.7* libncurses5 - + sudo apt-get -qq install -y make unzip g++ curl git wget ant openjdk-11-jdk eatmydata sudo service mysql stop sudo bash -c "echo '/usr/sbin/mysqld { }' > /etc/apparmor.d/usr.sbin.mysqld" # https://bugs.launchpad.net/ubuntu/+source/mariadb-10.1/+bug/1806263 diff --git a/.github/workflows/unit_test_evalengine_mysql80.yml b/.github/workflows/unit_test_evalengine_mysql80.yml index c00217a172a..a19087f6f29 100644 --- a/.github/workflows/unit_test_evalengine_mysql80.yml +++ b/.github/workflows/unit_test_evalengine_mysql80.yml @@ -71,7 +71,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' @@ -102,14 +102,13 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb - # mysql80 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update sudo DEBIAN_FRONTEND="noninteractive" apt-get -qq install -y mysql-server mysql-client - + sudo apt-get -qq install -y make unzip g++ curl git wget ant openjdk-11-jdk eatmydata sudo service mysql stop sudo bash -c "echo '/usr/sbin/mysqld { }' > /etc/apparmor.d/usr.sbin.mysqld" # https://bugs.launchpad.net/ubuntu/+source/mariadb-10.1/+bug/1806263 diff --git a/.github/workflows/unit_test_evalengine_mysql84.yml b/.github/workflows/unit_test_evalengine_mysql84.yml new file mode 100644 index 00000000000..be066cc5bb1 --- /dev/null +++ b/.github/workflows/unit_test_evalengine_mysql84.yml @@ -0,0 +1,175 @@ +# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" + +name: Unit Test (evalengine_mysql84) +on: [push, pull_request] +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: gh-hosted-runners-4cores-1 + + 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 if workflow needs to be skipped + id: skip-workflow + run: | + skip='false' + if [[ "${{github.event.pull_request}}" == "" ]] && [[ "${{github.ref}}" != "refs/heads/main" ]] && [[ ! "${{github.ref}}" =~ ^refs/heads/release-[0-9]+\.[0-9]$ ]] && [[ ! "${{github.ref}}" =~ "refs/tags/.*" ]]; then + skip='true' + fi + echo Skip ${skip} + echo "skip-workflow=${skip}" >> $GITHUB_OUTPUT + + PR_DATA=$(curl \ + -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + -H "Accept: application/vnd.github.v3+json" \ + "https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}") + draft=$(echo "$PR_DATA" | jq .draft -r) + echo "is_draft=${draft}" >> $GITHUB_OUTPUT + + - name: Check out code + if: steps.skip-workflow.outputs.skip-workflow == 'false' + uses: actions/checkout@v4 + + - name: Check for changes in relevant files + if: steps.skip-workflow.outputs.skip-workflow == 'false' + uses: dorny/paths-filter@v3.0.1 + id: changes + with: + token: '' + filters: | + unit_tests: + - '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.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' + uses: actions/setup-go@v5 + with: + go-version: 1.22.5 + + - name: Set up python + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' + uses: actions/setup-python@v5 + + - name: Tune the OS + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' + run: | + sudo sysctl -w net.ipv4.ip_local_port_range="22768 65535" + # Increase the asynchronous non-blocking I/O. More information at https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_use_native_aio + echo "fs.aio-max-nr = 1048576" | sudo tee -a /etc/sysctl.conf + sudo sysctl -p /etc/sysctl.conf + + - name: Get dependencies + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' + run: | + export DEBIAN_FRONTEND="noninteractive" + sudo apt-get -qq update + + # Uninstall any previously installed MySQL first + sudo systemctl stop apparmor + sudo DEBIAN_FRONTEND="noninteractive" apt-get -qq remove -y --purge mysql-server mysql-client mysql-common + sudo apt-get -qq -y autoremove + sudo apt-get -qq -y autoclean + sudo deluser mysql + sudo rm -rf /var/lib/mysql + sudo rm -rf /etc/mysql + + # Get key to latest MySQL repo + sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb + + echo mysql-apt-config mysql-apt-config/select-server select mysql-8.4-lts | sudo debconf-set-selections + sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* + sudo apt-get -qq update + sudo DEBIAN_FRONTEND="noninteractive" apt-get -qq install -y mysql-server mysql-client + + sudo apt-get -qq install -y make unzip g++ curl git wget ant openjdk-11-jdk eatmydata + sudo service mysql stop + sudo bash -c "echo '/usr/sbin/mysqld { }' > /etc/apparmor.d/usr.sbin.mysqld" # https://bugs.launchpad.net/ubuntu/+source/mariadb-10.1/+bug/1806263 + sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/ + sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld || echo "could not remove mysqld profile" + + mkdir -p dist bin + curl -s -L https://github.com/coreos/etcd/releases/download/v3.3.10/etcd-v3.3.10-linux-amd64.tar.gz | tar -zxC dist + mv dist/etcd-v3.3.10-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.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' + run: | + make tools + + - name: Setup launchable dependencies + if: steps.skip-workflow.outputs.is_draft == 'false' && steps.skip-workflow.outputs.skip-workflow == '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.skip-workflow.outputs.skip-workflow == 'false' && 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" + + eatmydata -- make unit_test | tee -a output.txt | go-junit-report -set-exit-code > report.xml + + - name: Print test output and Record test result in launchable if PR is not a draft + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' && always() + run: | + if [[ "${{steps.skip-workflow.outputs.is_draft}}" == "false" ]]; then + # send recorded tests to launchable + launchable record tests --build "$GITHUB_RUN_ID" go-test . || true + fi + + # print test output + cat output.txt + + - name: Test Summary + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' && always() + uses: test-summary/action@v2 + with: + paths: "report.xml" + show: "fail, skip" diff --git a/.github/workflows/unit_test_mysql57.yml b/.github/workflows/unit_test_mysql57.yml index cf708f0b117..1ccf3e320a9 100644 --- a/.github/workflows/unit_test_mysql57.yml +++ b/.github/workflows/unit_test_mysql57.yml @@ -71,7 +71,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' @@ -102,9 +102,8 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb - # mysql57 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb # Bionic packages are still compatible for Jammy since there's no MySQL 5.7 # packages for Jammy. echo mysql-apt-config mysql-apt-config/repo-codename select bionic | sudo debconf-set-selections @@ -112,7 +111,7 @@ jobs: sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update sudo DEBIAN_FRONTEND="noninteractive" apt-get -qq install -y mysql-client=5.7* mysql-community-server=5.7* mysql-server=5.7* libncurses5 - + sudo apt-get -qq install -y make unzip g++ curl git wget ant openjdk-11-jdk eatmydata sudo service mysql stop sudo bash -c "echo '/usr/sbin/mysqld { }' > /etc/apparmor.d/usr.sbin.mysqld" # https://bugs.launchpad.net/ubuntu/+source/mariadb-10.1/+bug/1806263 diff --git a/.github/workflows/unit_test_mysql80.yml b/.github/workflows/unit_test_mysql80.yml index 7dac5c3eb96..1984d36a5a9 100644 --- a/.github/workflows/unit_test_mysql80.yml +++ b/.github/workflows/unit_test_mysql80.yml @@ -71,7 +71,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' @@ -102,14 +102,13 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb - # mysql80 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update sudo DEBIAN_FRONTEND="noninteractive" apt-get -qq install -y mysql-server mysql-client - + sudo apt-get -qq install -y make unzip g++ curl git wget ant openjdk-11-jdk eatmydata sudo service mysql stop sudo bash -c "echo '/usr/sbin/mysqld { }' > /etc/apparmor.d/usr.sbin.mysqld" # https://bugs.launchpad.net/ubuntu/+source/mariadb-10.1/+bug/1806263 diff --git a/.github/workflows/unit_test_mysql84.yml b/.github/workflows/unit_test_mysql84.yml new file mode 100644 index 00000000000..f3fab513358 --- /dev/null +++ b/.github/workflows/unit_test_mysql84.yml @@ -0,0 +1,175 @@ +# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" + +name: Unit Test (mysql84) +on: [push, pull_request] +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: gh-hosted-runners-4cores-1 + + 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 if workflow needs to be skipped + id: skip-workflow + run: | + skip='false' + if [[ "${{github.event.pull_request}}" == "" ]] && [[ "${{github.ref}}" != "refs/heads/main" ]] && [[ ! "${{github.ref}}" =~ ^refs/heads/release-[0-9]+\.[0-9]$ ]] && [[ ! "${{github.ref}}" =~ "refs/tags/.*" ]]; then + skip='true' + fi + echo Skip ${skip} + echo "skip-workflow=${skip}" >> $GITHUB_OUTPUT + + PR_DATA=$(curl \ + -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + -H "Accept: application/vnd.github.v3+json" \ + "https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}") + draft=$(echo "$PR_DATA" | jq .draft -r) + echo "is_draft=${draft}" >> $GITHUB_OUTPUT + + - name: Check out code + if: steps.skip-workflow.outputs.skip-workflow == 'false' + uses: actions/checkout@v4 + + - name: Check for changes in relevant files + if: steps.skip-workflow.outputs.skip-workflow == 'false' + uses: dorny/paths-filter@v3.0.1 + id: changes + with: + token: '' + filters: | + unit_tests: + - '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.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' + uses: actions/setup-go@v5 + with: + go-version: 1.22.5 + + - name: Set up python + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' + uses: actions/setup-python@v5 + + - name: Tune the OS + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' + run: | + sudo sysctl -w net.ipv4.ip_local_port_range="22768 65535" + # Increase the asynchronous non-blocking I/O. More information at https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_use_native_aio + echo "fs.aio-max-nr = 1048576" | sudo tee -a /etc/sysctl.conf + sudo sysctl -p /etc/sysctl.conf + + - name: Get dependencies + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' + run: | + export DEBIAN_FRONTEND="noninteractive" + sudo apt-get -qq update + + # Uninstall any previously installed MySQL first + sudo systemctl stop apparmor + sudo DEBIAN_FRONTEND="noninteractive" apt-get -qq remove -y --purge mysql-server mysql-client mysql-common + sudo apt-get -qq -y autoremove + sudo apt-get -qq -y autoclean + sudo deluser mysql + sudo rm -rf /var/lib/mysql + sudo rm -rf /etc/mysql + + # Get key to latest MySQL repo + sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb + + echo mysql-apt-config mysql-apt-config/select-server select mysql-8.4-lts | sudo debconf-set-selections + sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* + sudo apt-get -qq update + sudo DEBIAN_FRONTEND="noninteractive" apt-get -qq install -y mysql-server mysql-client + + sudo apt-get -qq install -y make unzip g++ curl git wget ant openjdk-11-jdk eatmydata + sudo service mysql stop + sudo bash -c "echo '/usr/sbin/mysqld { }' > /etc/apparmor.d/usr.sbin.mysqld" # https://bugs.launchpad.net/ubuntu/+source/mariadb-10.1/+bug/1806263 + sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/ + sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld || echo "could not remove mysqld profile" + + mkdir -p dist bin + curl -s -L https://github.com/coreos/etcd/releases/download/v3.3.10/etcd-v3.3.10-linux-amd64.tar.gz | tar -zxC dist + mv dist/etcd-v3.3.10-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.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' + run: | + make tools + + - name: Setup launchable dependencies + if: steps.skip-workflow.outputs.is_draft == 'false' && steps.skip-workflow.outputs.skip-workflow == '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.skip-workflow.outputs.skip-workflow == 'false' && 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" + + eatmydata -- make unit_test | tee -a output.txt | go-junit-report -set-exit-code > report.xml + + - name: Print test output and Record test result in launchable if PR is not a draft + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' && always() + run: | + if [[ "${{steps.skip-workflow.outputs.is_draft}}" == "false" ]]; then + # send recorded tests to launchable + launchable record tests --build "$GITHUB_RUN_ID" go-test . || true + fi + + # print test output + cat output.txt + + - name: Test Summary + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' && always() + uses: test-summary/action@v2 + with: + paths: "report.xml" + show: "fail, skip" diff --git a/.github/workflows/update_golang_dependencies.yml b/.github/workflows/update_golang_dependencies.yml index 0523eed6a97..7538090d51e 100644 --- a/.github/workflows/update_golang_dependencies.yml +++ b/.github/workflows/update_golang_dependencies.yml @@ -19,7 +19,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Check out code uses: actions/checkout@v4 diff --git a/.github/workflows/update_golang_version.yml b/.github/workflows/update_golang_version.yml index 59daadb8f3a..df9677e7cf4 100644 --- a/.github/workflows/update_golang_version.yml +++ b/.github/workflows/update_golang_version.yml @@ -15,14 +15,14 @@ jobs: pull-requests: write strategy: matrix: - branch: [ main, release-20.0, release-19.0, release-18.0, release-17.0 ] + branch: [ main, release-20.0, release-19.0, release-18.0 ] name: Update Golang Version runs-on: ubuntu-latest steps: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Check out code uses: actions/checkout@v4 diff --git a/.github/workflows/upgrade_downgrade_test_backups_e2e.yml b/.github/workflows/upgrade_downgrade_test_backups_e2e.yml index 209c96fd539..e8b8a688879 100644 --- a/.github/workflows/upgrade_downgrade_test_backups_e2e.yml +++ b/.github/workflows/upgrade_downgrade_test_backups_e2e.yml @@ -72,7 +72,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -100,8 +100,9 @@ jobs: 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 - sudo apt-get install -y percona-xtrabackup-24 + sudo apt-get install -y percona-xtrabackup-80 # Checkout to the last release of Vitess - name: Check out other version's code (${{ steps.output-previous-release-ref.outputs.previous_release_ref }}) 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 542c6a00483..0e24c534057 100644 --- a/.github/workflows/upgrade_downgrade_test_backups_e2e_next_release.yml +++ b/.github/workflows/upgrade_downgrade_test_backups_e2e_next_release.yml @@ -74,7 +74,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -102,8 +102,9 @@ jobs: 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 - sudo apt-get install -y percona-xtrabackup-24 + sudo apt-get install -y percona-xtrabackup-80 # Checkout to the next release of Vitess - name: Check out other version's code (${{ steps.output-next-release-ref.outputs.next_release_ref }}) diff --git a/.github/workflows/upgrade_downgrade_test_backups_manual.yml b/.github/workflows/upgrade_downgrade_test_backups_manual.yml index e0d7402c8ce..9c98b643c3e 100644 --- a/.github/workflows/upgrade_downgrade_test_backups_manual.yml +++ b/.github/workflows/upgrade_downgrade_test_backups_manual.yml @@ -76,7 +76,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -102,7 +102,7 @@ jobs: # Install MySQL 8.0 sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get update @@ -122,8 +122,9 @@ jobs: 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 - sudo apt-get install -y percona-xtrabackup-24 + sudo apt-get install -y percona-xtrabackup-80 # Checkout to the last release of Vitess - name: Checkout to the other version's code (${{ steps.output-previous-release-ref.outputs.previous_release_ref }}) 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 15aa0f05a19..1cdfcee1fec 100644 --- a/.github/workflows/upgrade_downgrade_test_backups_manual_next_release.yml +++ b/.github/workflows/upgrade_downgrade_test_backups_manual_next_release.yml @@ -77,7 +77,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -103,7 +103,7 @@ jobs: # Install MySQL 8.0 sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get update @@ -123,8 +123,9 @@ jobs: 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 - sudo apt-get install -y percona-xtrabackup-24 + sudo apt-get install -y percona-xtrabackup-80 # Checkout to the next release of Vitess - name: Checkout to the other version's code (${{ steps.output-next-release-ref.outputs.next_release_ref }}) diff --git a/.github/workflows/upgrade_downgrade_test_onlineddl_flow.yml b/.github/workflows/upgrade_downgrade_test_onlineddl_flow.yml index c0f6ed9b058..c32a24ab083 100644 --- a/.github/workflows/upgrade_downgrade_test_onlineddl_flow.yml +++ b/.github/workflows/upgrade_downgrade_test_onlineddl_flow.yml @@ -83,7 +83,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -108,7 +108,7 @@ jobs: sudo rm -rf /etc/mysql # Install mysql80 sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get update @@ -124,12 +124,6 @@ jobs: # install JUnit report formatter go install github.com/vitessio/go-junit-report@HEAD - 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 apt-get update - sudo apt-get install -y percona-xtrabackup-24 - # Checkout to the last release of Vitess - name: Check out last version's code (${{ steps.output-previous-release-ref.outputs.previous_release_ref }}) if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -146,6 +140,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' timeout-minutes: 10 run: | + echo "building last release: $(git rev-parse HEAD)" source build.env make build mkdir -p /tmp/vitess-build-last/ @@ -168,6 +163,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' timeout-minutes: 10 run: | + echo "building next release: $(git rev-parse HEAD)" source build.env NOVTADMINBUILD=1 make build mkdir -p /tmp/vitess-build-next/ @@ -188,6 +184,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' timeout-minutes: 10 run: | + echo "building this SHA: $(git rev-parse HEAD)" source build.env make build mkdir -p /tmp/vitess-build-current/ diff --git a/.github/workflows/upgrade_downgrade_test_query_serving_queries.yml b/.github/workflows/upgrade_downgrade_test_query_serving_queries.yml index 9926336f9c7..ded814c6ac9 100644 --- a/.github/workflows/upgrade_downgrade_test_query_serving_queries.yml +++ b/.github/workflows/upgrade_downgrade_test_query_serving_queries.yml @@ -75,7 +75,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -100,7 +100,7 @@ jobs: sudo rm -rf /etc/mysql # Install mysql80 sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get update @@ -116,12 +116,6 @@ jobs: # install JUnit report formatter go install github.com/vitessio/go-junit-report@HEAD - 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 apt-get update - sudo apt-get install -y percona-xtrabackup-24 - # Checkout to the last release of Vitess - name: Check out other version's code (${{ steps.output-previous-release-ref.outputs.previous_release_ref }}) if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' 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 233dd496a21..845ab33c6bb 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 @@ -76,7 +76,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -101,7 +101,7 @@ jobs: sudo rm -rf /etc/mysql # Install mysql80 sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get update @@ -117,12 +117,6 @@ jobs: # install JUnit report formatter go install github.com/vitessio/go-junit-report@HEAD - 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 apt-get update - sudo apt-get install -y percona-xtrabackup-24 - # Checkout to the next release of Vitess - name: Check out other version's code (${{ steps.output-next-release-ref.outputs.next_release_ref }}) if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' diff --git a/.github/workflows/upgrade_downgrade_test_query_serving_schema.yml b/.github/workflows/upgrade_downgrade_test_query_serving_schema.yml index 6664951d12c..1006179a97a 100644 --- a/.github/workflows/upgrade_downgrade_test_query_serving_schema.yml +++ b/.github/workflows/upgrade_downgrade_test_query_serving_schema.yml @@ -75,7 +75,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -100,7 +100,7 @@ jobs: sudo rm -rf /etc/mysql # Install mysql80 sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get update @@ -116,12 +116,6 @@ jobs: # install JUnit report formatter go install github.com/vitessio/go-junit-report@HEAD - 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 apt-get update - sudo apt-get install -y percona-xtrabackup-24 - # Checkout to the last release of Vitess - name: Check out other version's code (${{ steps.output-previous-release-ref.outputs.previous_release_ref }}) if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' 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 d9a31b56ffe..1c30fe53c2f 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 @@ -76,7 +76,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -101,7 +101,7 @@ jobs: sudo rm -rf /etc/mysql # Install mysql80 sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get update @@ -117,12 +117,6 @@ jobs: # install JUnit report formatter go install github.com/vitessio/go-junit-report@HEAD - 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 apt-get update - sudo apt-get install -y percona-xtrabackup-24 - # Checkout to the next release of Vitess - name: Check out other version's code (${{ steps.output-next-release-ref.outputs.next_release_ref }}) if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' diff --git a/.github/workflows/upgrade_downgrade_test_reparent_new_vtctl.yml b/.github/workflows/upgrade_downgrade_test_reparent_new_vtctl.yml index a6e533cf735..853dd172ff6 100644 --- a/.github/workflows/upgrade_downgrade_test_reparent_new_vtctl.yml +++ b/.github/workflows/upgrade_downgrade_test_reparent_new_vtctl.yml @@ -76,7 +76,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -101,7 +101,7 @@ jobs: sudo rm -rf /etc/mysql # Install mysql80 sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get update @@ -117,12 +117,6 @@ jobs: # install JUnit report formatter go install github.com/vitessio/go-junit-report@HEAD - 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 apt-get update - sudo apt-get install -y percona-xtrabackup-24 - # Checkout to the next release of Vitess - name: Check out other version's code (${{ steps.output-next-release-ref.outputs.next_release_ref }}) if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' diff --git a/.github/workflows/upgrade_downgrade_test_reparent_new_vttablet.yml b/.github/workflows/upgrade_downgrade_test_reparent_new_vttablet.yml index e13520fc46a..90c41d4ee09 100644 --- a/.github/workflows/upgrade_downgrade_test_reparent_new_vttablet.yml +++ b/.github/workflows/upgrade_downgrade_test_reparent_new_vttablet.yml @@ -76,7 +76,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -101,7 +101,7 @@ jobs: sudo rm -rf /etc/mysql # Install mysql80 sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get update @@ -120,8 +120,9 @@ jobs: 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 - sudo apt-get install -y percona-xtrabackup-24 + sudo apt-get install -y percona-xtrabackup-80 # Checkout to the next release of Vitess - name: Check out other version's code (${{ steps.output-next-release-ref.outputs.next_release_ref }}) diff --git a/.github/workflows/upgrade_downgrade_test_reparent_old_vtctl.yml b/.github/workflows/upgrade_downgrade_test_reparent_old_vtctl.yml index dcfdf06ae65..7008f07ce44 100644 --- a/.github/workflows/upgrade_downgrade_test_reparent_old_vtctl.yml +++ b/.github/workflows/upgrade_downgrade_test_reparent_old_vtctl.yml @@ -75,7 +75,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -100,7 +100,7 @@ jobs: sudo rm -rf /etc/mysql # Install mysql80 sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get update @@ -116,12 +116,6 @@ jobs: # install JUnit report formatter go install github.com/vitessio/go-junit-report@HEAD - 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 apt-get update - sudo apt-get install -y percona-xtrabackup-24 - # Checkout to the last release of Vitess - name: Check out other version's code (${{ steps.output-previous-release-ref.outputs.previous_release_ref }}) if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' diff --git a/.github/workflows/upgrade_downgrade_test_reparent_old_vttablet.yml b/.github/workflows/upgrade_downgrade_test_reparent_old_vttablet.yml index 9fec80feced..e1240dd9a13 100644 --- a/.github/workflows/upgrade_downgrade_test_reparent_old_vttablet.yml +++ b/.github/workflows/upgrade_downgrade_test_reparent_old_vttablet.yml @@ -75,7 +75,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -100,7 +100,7 @@ jobs: sudo rm -rf /etc/mysql # Install mysql80 sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get update @@ -116,12 +116,6 @@ jobs: # install JUnit report formatter go install github.com/vitessio/go-junit-report@HEAD - 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 apt-get update - sudo apt-get install -y percona-xtrabackup-24 - # Checkout to the last release of Vitess - name: Check out other version's code (${{ steps.output-previous-release-ref.outputs.previous_release_ref }}) if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' diff --git a/.github/workflows/upgrade_downgrade_test_semi_sync.yml b/.github/workflows/upgrade_downgrade_test_semi_sync.yml new file mode 100644 index 00000000000..91b3b22b93e --- /dev/null +++ b/.github/workflows/upgrade_downgrade_test_semi_sync.yml @@ -0,0 +1,164 @@ +name: Semi Sync Upgrade Downgrade Testing +on: + push: + pull_request: + +concurrency: + group: format('{0}-{1}', ${{ github.ref }}, 'Semi Sync Upgrade Downgrade Testing') + cancel-in-progress: true + +permissions: read-all + +jobs: + upgrade_downgrade_test_e2e: + timeout-minutes: 60 + name: Run Semi Sync Upgrade Downgrade Test + runs-on: gh-hosted-runners-16cores-1 + + 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 if workflow needs to be skipped + id: skip-workflow + run: | + skip='false' + if [[ "${{github.event.pull_request}}" == "" ]] && [[ "${{github.ref}}" != "refs/heads/main" ]] && [[ ! "${{github.ref}}" =~ ^refs/heads/release-[0-9]+\.[0-9]$ ]] && [[ ! "${{github.ref}}" =~ "refs/tags/.*" ]]; then + skip='true' + fi + echo Skip ${skip} + echo "skip-workflow=${skip}" >> $GITHUB_OUTPUT + + - name: Check out commit's code + if: steps.skip-workflow.outputs.skip-workflow == 'false' + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set output with latest release branch + if: steps.skip-workflow.outputs.skip-workflow == 'false' + id: output-previous-release-ref + run: | + previous_release_ref=$(./tools/get_previous_release.sh ${{github.base_ref}} ${{github.ref}}) + echo $previous_release_ref + echo "previous_release_ref=${previous_release_ref}" >> $GITHUB_OUTPUT + + - name: Check for changes in relevant files + if: steps.skip-workflow.outputs.skip-workflow == 'false' + uses: dorny/paths-filter@v3.0.1 + id: changes + with: + token: '' + filters: | + end_to_end: + - 'go/**' + - 'go/**/*.go' + - 'test.go' + - 'Makefile' + - 'build.env' + - 'go.sum' + - 'go.mod' + - 'proto/*.proto' + - 'tools/**' + - 'config/**' + - 'bootstrap.sh' + - '.github/workflows/upgrade_downgrade_test_semi_sync.yml' + + - name: Set up Go + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + uses: actions/setup-go@v5 + with: + go-version: 1.22.5 + + - name: Set up python + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + uses: actions/setup-python@v5 + + - name: Tune the OS + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + run: | + sudo sysctl -w net.ipv4.ip_local_port_range="22768 65535" + + - name: Get base dependencies + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + run: | + sudo apt-get update + sudo apt-get install -y mysql-server mysql-client make unzip g++ etcd curl git wget eatmydata + sudo service mysql stop + sudo service etcd stop + sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/ + sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld + go mod download + + # install JUnit report formatter + go install github.com/vitessio/go-junit-report@HEAD + + 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 + sudo apt-get install -y percona-xtrabackup-80 + + # Checkout to the last release of Vitess + - name: Check out other version's code (${{ steps.output-previous-release-ref.outputs.previous_release_ref }}) + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + uses: actions/checkout@v4 + with: + ref: ${{ steps.output-previous-release-ref.outputs.previous_release_ref }} + + - name: Get dependencies for the last release + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + run: | + go mod download + + - name: Building last release's binaries + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + timeout-minutes: 10 + run: | + source build.env + NOVTADMINBUILD=1 make build + mkdir -p /tmp/vitess-build-other/ + cp -R bin /tmp/vitess-build-other/ + rm -Rf bin/* + + # Checkout to this build's commit + - name: Check out commit's code + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + uses: actions/checkout@v4 + + - name: Get dependencies for this commit + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + run: | + go mod download + + - name: Building the binaries for this commit + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + timeout-minutes: 10 + run: | + source build.env + NOVTADMINBUILD=1 make build + mkdir -p /tmp/vitess-build-current/ + cp -R bin /tmp/vitess-build-current/ + + # Copy last releases vttablet + - name: Copy last release's VTTablet + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + run: | + source build.env + + cp /tmp/vitess-build-other/bin/vttablet $PWD/bin/vttabletold + vttabletold --version + + - name: Run semi sync tests + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + run: | + rm -rf /tmp/vtdataroot + mkdir -p /tmp/vtdataroot + set -x + source build.env + go test -v -count=1 -run="" ./go/test/endtoend/reparent/semisync -alsologtostderr \ No newline at end of file diff --git a/.github/workflows/vitess_tester_vtgate.yml b/.github/workflows/vitess_tester_vtgate.yml index dc84d511df6..f2a669289bc 100644 --- a/.github/workflows/vitess_tester_vtgate.yml +++ b/.github/workflows/vitess_tester_vtgate.yml @@ -73,7 +73,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -95,7 +95,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update @@ -134,6 +134,7 @@ jobs: # which musn't be more than 107 characters long. export VTDATAROOT="/tmp/" source build.env + export NOVTADMINBUILD=1 make build set -exo pipefail diff --git a/.gitignore b/.gitignore index 43f352d1b80..70ae13ad32d 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,8 @@ __debug_bin /php/composer.phar /php/vendor +report*.xml + # vitess.io preview site /preview-vitess.io/ diff --git a/.golangci.yml b/.golangci.yml index 74c55100516..d20e7d1e9fd 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -3,6 +3,13 @@ run: timeout: 10m linters-settings: + depguard: + rules: + use_modern_packages: + list-mode: lax + deny: + - pkg: "math/rand$" + desc: Please use math/rand/v2 errcheck: exclude: ./misc/errcheck_excludes.txt goimports: @@ -17,6 +24,7 @@ linters: disable-all: true enable: # Defaults + - depguard - errcheck - govet - ineffassign diff --git a/Makefile b/Makefile index 91cafd489d5..ab367408873 100644 --- a/Makefile +++ b/Makefile @@ -81,6 +81,7 @@ endif bash ./build.env go build -trimpath $(EXTRA_BUILD_FLAGS) $(VT_GO_PARALLEL) \ -ldflags "$(EXTRA_BUILD_LDFLAGS) $(shell tools/build_version_flags.sh)" \ + -tags "$(EXTRA_BUILD_TAGS)" \ -o ${VTROOTBIN} ./go/... # build the vitess binaries statically @@ -94,6 +95,7 @@ endif CGO_ENABLED=0 go build \ -trimpath $(EXTRA_BUILD_FLAGS) $(VT_GO_PARALLEL) \ -ldflags "$(EXTRA_BUILD_LDFLAGS) $(shell tools/build_version_flags.sh)" \ + -tags "$(EXTRA_BUILD_TAGS)" \ -o ${VTROOTBIN} ./go/... ifndef NOVTADMINBUILD echo "Building VTAdmin Web, disable VTAdmin build by setting 'NOVTADMINBUILD'" @@ -116,6 +118,7 @@ endif CGO_ENABLED=0 GOOS=${GOOS} GOARCH=${GOARCH} go build \ -trimpath $(EXTRA_BUILD_FLAGS) $(VT_GO_PARALLEL) \ -ldflags "$(EXTRA_BUILD_LDFLAGS) $(shell tools/build_version_flags.sh)" \ + -tags "$(EXTRA_BUILD_TAGS)" \ -o ${VTROOTBIN}/${GOOS}_${GOARCH} ./go/... @if [ ! -x "${VTROOTBIN}/${GOOS}_${GOARCH}/vttablet" ]; then \ @@ -130,6 +133,7 @@ endif go build -trimpath \ $(EXTRA_BUILD_FLAGS) $(VT_GO_PARALLEL) \ -ldflags "$(EXTRA_BUILD_LDFLAGS) $(shell tools/build_version_flags.sh)" \ + -tags "$(EXTRA_BUILD_TAGS)" \ -gcflags -'N -l' \ -o ${VTROOTBIN} ./go/... @@ -282,7 +286,7 @@ $(PROTO_GO_OUTS): minimaltools install_protoc-gen-go proto/*.proto # This rule builds the bootstrap images for all flavors. DOCKER_IMAGES_FOR_TEST = mysql57 mysql80 percona57 percona80 DOCKER_IMAGES = common $(DOCKER_IMAGES_FOR_TEST) -BOOTSTRAP_VERSION=33 +BOOTSTRAP_VERSION=34 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 @@ -331,16 +335,10 @@ docker_lite_all: docker_lite $(DOCKER_LITE_TARGETS) docker_lite: ${call build_docker_image,docker/lite/Dockerfile,vitess/lite} -docker_local: - ${call build_docker_image,docker/local/Dockerfile,vitess/local} - -docker_run_local: - ./docker/local/run.sh - docker_mini: ${call build_docker_image,docker/mini/Dockerfile,vitess/mini} -DOCKER_VTTESTSERVER_SUFFIX = mysql57 mysql80 +DOCKER_VTTESTSERVER_SUFFIX = mysql80 DOCKER_VTTESTSERVER_TARGETS = $(addprefix docker_vttestserver_,$(DOCKER_VTTESTSERVER_SUFFIX)) $(DOCKER_VTTESTSERVER_TARGETS): docker_vttestserver_%: ${call build_docker_image,docker/vttestserver/Dockerfile.$*,vitess/vttestserver:$*} diff --git a/build.env b/build.env index 18e3069fe09..ba741be4211 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.22.4 || echo "Go version reported: `go version`. Version 1.22.4+ recommended. See https://vitess.io/contributing/build-from-source for install instructions." +goversion_min 1.22.5 || echo "Go version reported: `go version`. Version 1.22.5+ recommended. See https://vitess.io/contributing/build-from-source for install instructions." mkdir -p dist mkdir -p bin diff --git a/changelog/18.0/18.0.6/changelog.md b/changelog/18.0/18.0.6/changelog.md new file mode 100644 index 00000000000..0e23b7ef6bc --- /dev/null +++ b/changelog/18.0/18.0.6/changelog.md @@ -0,0 +1,55 @@ +# Changelog of Vitess v18.0.6 + +### Bug fixes +#### Docker + * [release-18.0] Fix the install dependencies script in Docker (#16340) [#16345](https://github.com/vitessio/vitess/pull/16345) +#### Query Serving + * [release-18.0] fix: handle info_schema routing (#15899) [#15905](https://github.com/vitessio/vitess/pull/15905) + * [release-18.0] fix: remove keyspace when merging subqueries (#16019) [#16026](https://github.com/vitessio/vitess/pull/16026) + * [release-18.0] Fix Incorrect Optimization with LIMIT and GROUP BY (#16263) [#16266](https://github.com/vitessio/vitess/pull/16266) + * [release-18.0] planner: Handle ORDER BY inside derived tables (#16353) [#16358](https://github.com/vitessio/vitess/pull/16358) + * [release-18.0] Fix Join Predicate Cleanup Bug in Route Merging (#16386) [#16388](https://github.com/vitessio/vitess/pull/16388) +#### VReplication + * [release-18.0] vtctldclient: Apply (Shard | Keyspace| Table) Routing Rules commands don't work (#16096) [#16123](https://github.com/vitessio/vitess/pull/16123) + * [release-18.0] VDiff CLI: Fix VDiff `show` bug (#16177) [#16197](https://github.com/vitessio/vitess/pull/16197) + * [release-18.0] VReplication Workflow: set state correctly when restarting workflow streams in the copy phase (#16217) [#16221](https://github.com/vitessio/vitess/pull/16221) + * [release-18.0] VReplication: Properly handle target shards w/o a primary in Reshard (#16283) [#16290](https://github.com/vitessio/vitess/pull/16290) +#### VTTablet + * [18.x] Fix `schemacopy` collation issues [#15859](https://github.com/vitessio/vitess/pull/15859) +#### VTorc + * [release-18.0] Add timeout to all the contexts used for RPC calls in vtorc (#15991) [#16104](https://github.com/vitessio/vitess/pull/16104) +#### vtexplain + * [release-18.0] Fix `vtexplain` not handling `UNION` queries with `weight_string` results correctly. (#16129) [#16156](https://github.com/vitessio/vitess/pull/16156) +### CI/Build +#### Build/CI + * [release-18.0] Add DCO workflow (#16052) [#16055](https://github.com/vitessio/vitess/pull/16055) + * [release-18.0] Remove DCO workaround (#16087) [#16090](https://github.com/vitessio/vitess/pull/16090) + * [release-18.0] CI: Fix for xtrabackup install failures (#16329) [#16331](https://github.com/vitessio/vitess/pull/16331) +#### General + * [release-18.0] Upgrade the Golang version to `go1.21.11` [#16063](https://github.com/vitessio/vitess/pull/16063) + * [release-18.0] Upgrade the Golang version to `go1.21.12` [#16320](https://github.com/vitessio/vitess/pull/16320) +### Dependencies +#### VTAdmin + * [release-18.0] Update braces package (#16115) [#16117](https://github.com/vitessio/vitess/pull/16117) +### Internal Cleanup +#### Examples + * [release-18.0] Update env.sh so that is does not error when running on Mac (#15835) [#15914](https://github.com/vitessio/vitess/pull/15914) +### Performance +#### VTTablet + * [release-18.0] Do not load table stats when booting `vttablet`. (#15715) [#16099](https://github.com/vitessio/vitess/pull/16099) +### Regression +#### Query Serving + * [release-18.0] fix: insert on duplicate update to add list argument in the bind variables map (#15961) [#15966](https://github.com/vitessio/vitess/pull/15966) +### Release +#### General + * [release-18.0] Bump to `v18.0.6-SNAPSHOT` after the `v18.0.5` release [#15888](https://github.com/vitessio/vitess/pull/15888) + * [release-18.0] Code Freeze for `v18.0.6` [#16444](https://github.com/vitessio/vitess/pull/16444) +### Testing +#### Query Serving + * [release-18.0] test: Cleaner plan tests output (#15922) [#15923](https://github.com/vitessio/vitess/pull/15923) + * [release-18] Vitess tester workflow (#16127) [#16419](https://github.com/vitessio/vitess/pull/16419) +#### VTCombo + * [release-18.0] Fix flaky tests that use vtcombo (#16178) [#16211](https://github.com/vitessio/vitess/pull/16211) +#### vtexplain + * [release-18.0] Fix flakiness in `vtexplain` unit test case. (#16159) [#16166](https://github.com/vitessio/vitess/pull/16166) + diff --git a/changelog/18.0/18.0.6/release_notes.md b/changelog/18.0/18.0.6/release_notes.md new file mode 100644 index 00000000000..9dbeaa12276 --- /dev/null +++ b/changelog/18.0/18.0.6/release_notes.md @@ -0,0 +1,7 @@ +# Release of Vitess v18.0.6 +The entire changelog for this release can be found [here](https://github.com/vitessio/vitess/blob/main/changelog/18.0/18.0.6/changelog.md). + +The release includes 28 merged Pull Requests. + +Thanks to all our contributors: @GuptaManan100, @app/vitess-bot, @arthurschreiber, @shlomi-noach, @vitess-bot + diff --git a/changelog/18.0/README.md b/changelog/18.0/README.md index 77dddf2cfbc..b09ae51970a 100644 --- a/changelog/18.0/README.md +++ b/changelog/18.0/README.md @@ -1,4 +1,8 @@ ## v18.0 +* **[18.0.6](18.0.6)** + * [Changelog](18.0.6/changelog.md) + * [Release Notes](18.0.6/release_notes.md) + * **[18.0.5](18.0.5)** * [Changelog](18.0.5/changelog.md) * [Release Notes](18.0.5/release_notes.md) diff --git a/changelog/19.0/19.0.0/release_notes.md b/changelog/19.0/19.0.0/release_notes.md index 98603d4240a..0a3f33f0fd9 100644 --- a/changelog/19.0/19.0.0/release_notes.md +++ b/changelog/19.0/19.0.0/release_notes.md @@ -53,6 +53,10 @@ Vitess will however, continue to support importing from MySQL 5.7 into Vitess ev #### Docker Image vitess/lite +> [!CAUTION] +> If you are using incremental backups, you must remain on the `vitess/lite` image, as the official MySQL image does not have `mysqlbinlog` installed. +> See https://github.com/vitessio/vitess/issues/16281 for more information. + The `mysqld` binary is now deprecated in the `vitess/lite` Docker image and will be removed in a future release. This means that the MySQL/Percona version specific image tags for the `vitess/lite` image are deprecated. diff --git a/changelog/19.0/19.0.5/changelog.md b/changelog/19.0/19.0.5/changelog.md new file mode 100644 index 00000000000..4d0a520059d --- /dev/null +++ b/changelog/19.0/19.0.5/changelog.md @@ -0,0 +1,71 @@ +# Changelog of Vitess v19.0.5 + +### Bug fixes +#### Cluster management + * [release-19.0] Use default schema reload config values when config file is empty (#16393) [#16410](https://github.com/vitessio/vitess/pull/16410) +#### Docker + * [release-19.0] Fix the install dependencies script in Docker (#16340) [#16346](https://github.com/vitessio/vitess/pull/16346) +#### Documentation + * [release-19.0] Fix the `v19.0.0` release notes and use the `vitess/lite` image for the MySQL container (#16282) [#16285](https://github.com/vitessio/vitess/pull/16285) +#### Online DDL + * [release-19.0] Online DDL shadow table: rename referenced table name in self referencing FK (#16205) [#16207](https://github.com/vitessio/vitess/pull/16207) +#### Query Serving + * [release-19.0] fix: handle info_schema routing (#15899) [#15906](https://github.com/vitessio/vitess/pull/15906) + * [release-19.0] connpool: Allow time out during shutdown (#15979) [#16003](https://github.com/vitessio/vitess/pull/16003) + * [release-19.0] fix: remove keyspace when merging subqueries (#16019) [#16027](https://github.com/vitessio/vitess/pull/16027) + * [release-19.0] Handle Nullability for Columns from Outer Tables (#16174) [#16185](https://github.com/vitessio/vitess/pull/16185) + * [release-19.0] Fix vtgate crash in group concat [#16254](https://github.com/vitessio/vitess/pull/16254) + * [release-19.0] Fix Incorrect Optimization with LIMIT and GROUP BY (#16263) [#16267](https://github.com/vitessio/vitess/pull/16267) + * [release-19.0] planner: Handle ORDER BY inside derived tables (#16353) [#16359](https://github.com/vitessio/vitess/pull/16359) + * [release-19.0] fix issue with aggregation inside of derived tables (#16366) [#16384](https://github.com/vitessio/vitess/pull/16384) + * [release-19.0] Fix Join Predicate Cleanup Bug in Route Merging (#16386) [#16389](https://github.com/vitessio/vitess/pull/16389) + * [release-19.0] Fix panic in schema tracker in presence of keyspace routing rules (#16383) [#16406](https://github.com/vitessio/vitess/pull/16406) + * [release-19.0] Fix subquery planning having an aggregation that is used in order by as long as we can merge it all into a single route (#16402) [#16407](https://github.com/vitessio/vitess/pull/16407) +#### VReplication + * [release-19.0] vtctldclient: Apply (Shard | Keyspace| Table) Routing Rules commands don't work (#16096) [#16124](https://github.com/vitessio/vitess/pull/16124) + * [release-19.0] VDiff CLI: Fix VDiff `show` bug (#16177) [#16198](https://github.com/vitessio/vitess/pull/16198) + * [release-19.0] VReplication Workflow: set state correctly when restarting workflow streams in the copy phase (#16217) [#16222](https://github.com/vitessio/vitess/pull/16222) + * [release-19.0] VReplication: Properly handle target shards w/o a primary in Reshard (#16283) [#16291](https://github.com/vitessio/vitess/pull/16291) +#### VTorc + * [release-19.0] Add timeout to all the contexts used for RPC calls in vtorc (#15991) [#16103](https://github.com/vitessio/vitess/pull/16103) +#### vtexplain + * [release-19.0] Fix `vtexplain` not handling `UNION` queries with `weight_string` results correctly. (#16129) [#16157](https://github.com/vitessio/vitess/pull/16157) +### CI/Build +#### Build/CI + * [release-19.0] Add DCO workflow (#16052) [#16056](https://github.com/vitessio/vitess/pull/16056) + * [release-19.0] Remove DCO workaround (#16087) [#16091](https://github.com/vitessio/vitess/pull/16091) + * [release-19.0] CI: Fix for xtrabackup install failures (#16329) [#16332](https://github.com/vitessio/vitess/pull/16332) +#### General + * [release-19.0] Upgrade the Golang version to `go1.22.4` [#16061](https://github.com/vitessio/vitess/pull/16061) + * [release-19.0] Upgrade the Golang version to `go1.22.5` [#16322](https://github.com/vitessio/vitess/pull/16322) +#### VTAdmin + * [release-19.0] Update VTAdmin build script (#15839) [#15850](https://github.com/vitessio/vitess/pull/15850) +### Dependencies +#### VTAdmin + * [release-19.0] Update braces package (#16115) [#16118](https://github.com/vitessio/vitess/pull/16118) +### Internal Cleanup +#### Examples + * [release-19.0] Update env.sh so that is does not error when running on Mac (#15835) [#15915](https://github.com/vitessio/vitess/pull/15915) +### Performance +#### VTTablet + * [release-19.0] Do not load table stats when booting `vttablet`. (#15715) [#16100](https://github.com/vitessio/vitess/pull/16100) +### Regression +#### Query Serving + * [release-19.0] fix: derived table join column expression to be part of add join predicate on rewrite (#15956) [#15960](https://github.com/vitessio/vitess/pull/15960) + * [release-19.0] fix: insert on duplicate update to add list argument in the bind variables map (#15961) [#15967](https://github.com/vitessio/vitess/pull/15967) + * [release-19.0] fix: order by subquery planning (#16049) [#16132](https://github.com/vitessio/vitess/pull/16132) + * [release-19.0] feat: add a LIMIT 1 on EXISTS subqueries to limit network overhead (#16153) [#16191](https://github.com/vitessio/vitess/pull/16191) +### Release +#### General + * [release-19.0] Bump to `v19.0.5-SNAPSHOT` after the `v19.0.4` release [#15889](https://github.com/vitessio/vitess/pull/15889) +### Testing +#### Build/CI + * Run more test on release-19 branch [#16152](https://github.com/vitessio/vitess/pull/16152) +#### Query Serving + * [release-19.0] test: Cleaner plan tests output (#15922) [#15964](https://github.com/vitessio/vitess/pull/15964) + * [release-19] Vitess tester workflow (#16127) [#16418](https://github.com/vitessio/vitess/pull/16418) +#### VTCombo + * [release-19.0] Fix flaky tests that use vtcombo (#16178) [#16212](https://github.com/vitessio/vitess/pull/16212) +#### vtexplain + * [release-19.0] Fix flakiness in `vtexplain` unit test case. (#16159) [#16167](https://github.com/vitessio/vitess/pull/16167) + diff --git a/changelog/19.0/19.0.5/release_notes.md b/changelog/19.0/19.0.5/release_notes.md new file mode 100644 index 00000000000..5df66930dd1 --- /dev/null +++ b/changelog/19.0/19.0.5/release_notes.md @@ -0,0 +1,7 @@ +# Release of Vitess v19.0.5 +The entire changelog for this release can be found [here](https://github.com/vitessio/vitess/blob/main/changelog/19.0/19.0.5/changelog.md). + +The release includes 40 merged Pull Requests. + +Thanks to all our contributors: @GuptaManan100, @app/vitess-bot, @harshit-gangal, @systay, @vitess-bot + diff --git a/changelog/19.0/README.md b/changelog/19.0/README.md index b5c6489f101..ae90ef2df1b 100644 --- a/changelog/19.0/README.md +++ b/changelog/19.0/README.md @@ -1,4 +1,8 @@ ## v19.0 +* **[19.0.5](19.0.5)** + * [Changelog](19.0.5/changelog.md) + * [Release Notes](19.0.5/release_notes.md) + * **[19.0.4](19.0.4)** * [Changelog](19.0.4/changelog.md) * [Release Notes](19.0.4/release_notes.md) diff --git a/changelog/20.0/20.0.0/changelog.md b/changelog/20.0/20.0.0/changelog.md index a0e08dd87c4..5db48db10fd 100644 --- a/changelog/20.0/20.0.0/changelog.md +++ b/changelog/20.0/20.0.0/changelog.md @@ -41,7 +41,6 @@ * `schemadiff` INSTANT DDL: impossible changes on tables with `FULLTEXT` index [#15725](https://github.com/vitessio/vitess/pull/15725) * SchemaEngine: Ensure GetTableForPos returns table schema for "current" position by default [#15912](https://github.com/vitessio/vitess/pull/15912) * [release-20.0-rc] Online DDL shadow table: rename referenced table name in self referencing FK (#16205) [#16208](https://github.com/vitessio/vitess/pull/16208) - * [release-20.0] Online DDL shadow table: rename referenced table name in self referencing FK (#16205) [#16209](https://github.com/vitessio/vitess/pull/16209) #### Query Serving * Make connection killing resilient to MySQL hangs [#14500](https://github.com/vitessio/vitess/pull/14500) * TxThrottler: dont throttle unless lag [#14789](https://github.com/vitessio/vitess/pull/14789) @@ -83,9 +82,7 @@ * `schemadiff`: assume default collation for textual column when collation is undefined [#16000](https://github.com/vitessio/vitess/pull/16000) * fix: remove keyspace when merging subqueries [#16019](https://github.com/vitessio/vitess/pull/16019) * [release-20.0-rc] fix: rows affected count for multi table update for non-literal column value (#16181) [#16182](https://github.com/vitessio/vitess/pull/16182) - * [release-20.0] fix: rows affected count for multi table update for non-literal column value (#16181) [#16183](https://github.com/vitessio/vitess/pull/16183) * [release-20.0-rc] Handle Nullability for Columns from Outer Tables (#16174) [#16186](https://github.com/vitessio/vitess/pull/16186) - * [release-20.0] Handle Nullability for Columns from Outer Tables (#16174) [#16187](https://github.com/vitessio/vitess/pull/16187) #### TabletManager * mysqlctl: Improve handling of the lock file [#15404](https://github.com/vitessio/vitess/pull/15404) * Fix possible race in MySQL startup and vttablet in parallel [#15538](https://github.com/vitessio/vitess/pull/15538) @@ -111,17 +108,10 @@ * VReplication: Take replication lag into account in VStreamManager healthcheck result processing [#15761](https://github.com/vitessio/vitess/pull/15761) * VReplication: Improve workflow cancel/delete [#15977](https://github.com/vitessio/vitess/pull/15977) * [release-20.0-rc] vtctldclient: Apply (Shard | Keyspace| Table) Routing Rules commands don't work (#16096) [#16125](https://github.com/vitessio/vitess/pull/16125) - * [release-20.0] vtctldclient: Apply (Shard | Keyspace| Table) Routing Rules commands don't work (#16096) [#16126](https://github.com/vitessio/vitess/pull/16126) * [release-20.0-rc] VReplication: Improve workflow cancel/delete (#15977) [#16130](https://github.com/vitessio/vitess/pull/16130) - * [release-20.0] VReplication: Improve workflow cancel/delete (#15977) [#16131](https://github.com/vitessio/vitess/pull/16131) - * [release-20.0] CI Bug: Rename shard name back to match existing workflow file for vreplication_migrate_vdiff2_convert_tz (#16148) [#16151](https://github.com/vitessio/vitess/pull/16151) - * [release-20.0] CI flaky test: Fix flakiness in vreplication_migrate_vdiff2_convert_tz (#16180) [#16189](https://github.com/vitessio/vitess/pull/16189) * [release-20.0-rc] VDiff CLI: Fix VDiff `show` bug (#16177) [#16199](https://github.com/vitessio/vitess/pull/16199) - * [release-20.0] VDiff CLI: Fix VDiff `show` bug (#16177) [#16200](https://github.com/vitessio/vitess/pull/16200) * [release-20.0-rc] VReplication: handle escaped identifiers in vschema when initializing sequence tables (#16169) [#16218](https://github.com/vitessio/vitess/pull/16218) - * [release-20.0] VReplication: handle escaped identifiers in vschema when initializing sequence tables (#16169) [#16219](https://github.com/vitessio/vitess/pull/16219) * [release-20.0-rc] VReplication Workflow: set state correctly when restarting workflow streams in the copy phase (#16217) [#16223](https://github.com/vitessio/vitess/pull/16223) - * [release-20.0] VReplication Workflow: set state correctly when restarting workflow streams in the copy phase (#16217) [#16224](https://github.com/vitessio/vitess/pull/16224) #### VTAdmin * [VTAdmin API] Fix schema cache flag, add documentation [#15704](https://github.com/vitessio/vitess/pull/15704) * [VTAdmin] Remove vtctld web link, improve local example (#15607) [#15824](https://github.com/vitessio/vitess/pull/15824) @@ -133,7 +123,6 @@ #### vtexplain * vtexplain: Fix setting up the column information [#15275](https://github.com/vitessio/vitess/pull/15275) * vtexplain: Ensure memory topo is set up for throttler [#15279](https://github.com/vitessio/vitess/pull/15279) - * [release-20.0] Fix `vtexplain` not handling `UNION` queries with `weight_string` results correctly. (#16129) [#16158](https://github.com/vitessio/vitess/pull/16158) #### vttestserver * Revert unwanted logging change to `vttestserver` [#15148](https://github.com/vitessio/vitess/pull/15148) * use proper mysql version in the `vttestserver` images [#15235](https://github.com/vitessio/vitess/pull/15235) @@ -159,18 +148,14 @@ * Validate go versions in Static Code Checks CI [#15932](https://github.com/vitessio/vitess/pull/15932) * Add CODEOWNERS for tablet throttler and schemadiff [#16036](https://github.com/vitessio/vitess/pull/16036) * [release-20.0-rc] Add DCO workflow (#16052) [#16057](https://github.com/vitessio/vitess/pull/16057) - * [release-20.0] Add DCO workflow (#16052) [#16058](https://github.com/vitessio/vitess/pull/16058) * [release-20.0-rc] Remove DCO workaround (#16087) [#16092](https://github.com/vitessio/vitess/pull/16092) - * [release-20.0] Remove DCO workaround (#16087) [#16093](https://github.com/vitessio/vitess/pull/16093) * Revert "[release-20.0-rc] Bump to `v20.0.0-SNAPSHOT` after the `v20.00-RC1` release (#16142)" [#16144](https://github.com/vitessio/vitess/pull/16144) #### Docker * Docker/vtadmin: Update node version [#16145](https://github.com/vitessio/vitess/pull/16145) - * [release-20.0] Docker: Update node vtadmin version (#16147) [#16161](https://github.com/vitessio/vitess/pull/16161) #### General * [main] Upgrade the Golang version to `go1.22.1` [#15405](https://github.com/vitessio/vitess/pull/15405) * Upgrade go version to go1.22.2 [#15642](https://github.com/vitessio/vitess/pull/15642) * [main] Upgrade the Golang version to `go1.22.3` [#15865](https://github.com/vitessio/vitess/pull/15865) - * [release-20.0] Upgrade the Golang version to `go1.22.4` [#16060](https://github.com/vitessio/vitess/pull/16060) * [release-20.0-rc] [release-20.0] Upgrade the Golang version to `go1.22.4` (#16060) [#16064](https://github.com/vitessio/vitess/pull/16064) #### Online DDL * `onlineddl_scheduler` test: fix flakiness in artifact cleanup test [#15396](https://github.com/vitessio/vitess/pull/15396) @@ -193,7 +178,6 @@ #### VTAdmin * Bump vite from 4.5.2 to 4.5.3 in /web/vtadmin [#15634](https://github.com/vitessio/vitess/pull/15634) * [release-20.0-rc] Update braces package (#16115) [#16119](https://github.com/vitessio/vitess/pull/16119) - * [release-20.0] Update braces package (#16115) [#16120](https://github.com/vitessio/vitess/pull/16120) #### web UI * Remove highcharts dependency pt. 1 [#15970](https://github.com/vitessio/vitess/pull/15970) ### Documentation @@ -202,9 +186,9 @@ #### Documentation * Fix docs for unmanaged tablets [#15437](https://github.com/vitessio/vitess/pull/15437) * [release-20.0-rc] Changelog 20.0: Fix broken links (#16048) [#16075](https://github.com/vitessio/vitess/pull/16075) - * [release-20.0] Changelog 20.0: Fix broken links (#16048) [#16076](https://github.com/vitessio/vitess/pull/16076) #### General - * Add Shopify to `ADOPTERS.md` [#15853](https://github.com/vitessio/vitess/pull/15853) + * Add Shopify to `ADOPTERS.md` [#15853](https://github.com/vitessio/vitess/pull/15853) + * [release-20.0-rc] release notes: update dml related release notes (#16241) [#16246](https://github.com/vitessio/vitess/pull/16246) #### Governance * amend contributing guide to ban trivial contributions [#15618](https://github.com/vitessio/vitess/pull/15618) * remove koz from active maintainer list [#15733](https://github.com/vitessio/vitess/pull/15733) @@ -363,7 +347,6 @@ #### Docker * Revert the removal of the MySQL binaries in the `vitess/lite` image [#16042](https://github.com/vitessio/vitess/pull/16042) * [release-20.0-rc] Remove unnecessary Docker build workflows (#16196) [#16201](https://github.com/vitessio/vitess/pull/16201) - * [release-20.0] Remove unnecessary Docker build workflows (#16196) [#16202](https://github.com/vitessio/vitess/pull/16202) #### Examples * Update env.sh so that is does not error when running on Mac [#15835](https://github.com/vitessio/vitess/pull/15835) * Local Examples: Add --binary-as-hex=false flag to mysql alias [#15996](https://github.com/vitessio/vitess/pull/15996) @@ -452,7 +435,6 @@ #### VTTablet * Improve performance for `BaseShowTablesWithSizes` query. [#15713](https://github.com/vitessio/vitess/pull/15713) * Do not load table stats when booting `vttablet`. [#15715](https://github.com/vitessio/vitess/pull/15715) - * [release-20.0] Do not load table stats when booting `vttablet`. (#15715) [#16101](https://github.com/vitessio/vitess/pull/16101) ### Regression #### Query Serving * Fix routing rule query rewrite [#15253](https://github.com/vitessio/vitess/pull/15253) @@ -461,9 +443,7 @@ * fix: derived table join column expression to be part of add join predicate on rewrite [#15956](https://github.com/vitessio/vitess/pull/15956) * fix: insert on duplicate update to add list argument in the bind variables map [#15961](https://github.com/vitessio/vitess/pull/15961) * [release-20.0-rc] fix: order by subquery planning (#16049) [#16133](https://github.com/vitessio/vitess/pull/16133) - * [release-20.0] fix: order by subquery planning (#16049) [#16134](https://github.com/vitessio/vitess/pull/16134) * [release-20.0-rc] feat: add a LIMIT 1 on EXISTS subqueries to limit network overhead (#16153) [#16192](https://github.com/vitessio/vitess/pull/16192) - * [release-20.0] feat: add a LIMIT 1 on EXISTS subqueries to limit network overhead (#16153) [#16193](https://github.com/vitessio/vitess/pull/16193) #### Throttler * Enable 'heartbeat_on_demand_duration' in local/examples [#15204](https://github.com/vitessio/vitess/pull/15204) #### vttestserver @@ -485,9 +465,10 @@ * [release-20.0-rc] Code Freeze for `v20.0.0-RC1` [#16046](https://github.com/vitessio/vitess/pull/16046) * Bump to `v21.0.0-SNAPSHOT` after the `v20.0.0-RC1` release [#16047](https://github.com/vitessio/vitess/pull/16047) * [release-20.0-rc] Release of `v20.0.0-RC1` [#16137](https://github.com/vitessio/vitess/pull/16137) - * [release-20.0] Copy `v20.0.0-RC1` release notes [#16141](https://github.com/vitessio/vitess/pull/16141) * [release-20.0-rc] Bump to `v20.0.0-SNAPSHOT` after the `v20.0.0-RC1` release [#16142](https://github.com/vitessio/vitess/pull/16142) * [release-20.0-rc] Bump to `v20.0.0-SNAPSHOT` after the `v20.0.0-RC1` release [#16146](https://github.com/vitessio/vitess/pull/16146) + * [release-20.0-rc] Release of `v20.0.0-RC2` [#16225](https://github.com/vitessio/vitess/pull/16225) + * [release-20.0-rc] Bump to `v20.0.0-SNAPSHOT` after the `v20.0.0-RC2` release [#16236](https://github.com/vitessio/vitess/pull/16236) ### Testing #### Build/CI * Rewrite _many_ tests to use vtctldclient invocations, mostly non-output related stuff [#15270](https://github.com/vitessio/vitess/pull/15270) @@ -519,7 +500,6 @@ * Fix unit-test-runner bug [#15815](https://github.com/vitessio/vitess/pull/15815) * test: Add tests for `go/ioutil` and refactor existing [#15885](https://github.com/vitessio/vitess/pull/15885) * test: Add required tests for `vt/key`, `timer` and `cache/theine/bf` [#15976](https://github.com/vitessio/vitess/pull/15976) - * [release-20.0] CI Summary Addition [#16172](https://github.com/vitessio/vitess/pull/16172) #### Observability * VStreamer: add throttled logs when row/result/vstreamers get throttled. [#14936](https://github.com/vitessio/vitess/pull/14936) #### Query Serving @@ -551,14 +531,10 @@ * VStreamer unit test: port remaining tests to new framework [#15366](https://github.com/vitessio/vitess/pull/15366) * VReplication: Fix vtctldclient SwitchReads related bugs and move the TestBasicV2Workflows e2e test to vtctldclient [#15579](https://github.com/vitessio/vitess/pull/15579) * VStreamer unit tests: refactor pending test [#15845](https://github.com/vitessio/vitess/pull/15845) -#### VTCombo - * [release-20.0] Fix flaky tests that use vtcombo (#16178) [#16213](https://github.com/vitessio/vitess/pull/16213) #### VTorc * Add missing tests for `go/vt/vtorc/collection` [#15070](https://github.com/vitessio/vitess/pull/15070) #### vtctldclient * Add tests for GetTablets partial results [#15829](https://github.com/vitessio/vitess/pull/15829) -#### vtexplain - * [release-20.0] Fix flakiness in `vtexplain` unit test case. (#16159) [#16168](https://github.com/vitessio/vitess/pull/16168) #### vttestserver * Add `no_scatter` flag to vttestserver [#15670](https://github.com/vitessio/vitess/pull/15670) diff --git a/changelog/20.0/20.0.0/release_notes.md b/changelog/20.0/20.0.0/release_notes.md index 7e1eda59da2..32cf7fb7e81 100644 --- a/changelog/20.0/20.0.0/release_notes.md +++ b/changelog/20.0/20.0.0/release_notes.md @@ -29,6 +29,9 @@ - [Delete with Multi Target Support](#delete-multi-target) - [User Defined Functions Support](#udf-support) - [Insert Row Alias Support](#insert-row-alias-support) + - **[VReplication](#vreplication)** + - [Multi-tenant Imports](#multi-tenant) + - [VDiff Support For OnlineDDL Migrations](#vdiff-online-ddl) - **[Query Timeout](#query-timeout)** - **[Flag changes](#flag-changes)** - [`pprof-http` default change](#pprof-http-default) @@ -238,7 +241,8 @@ Support is added for sharded update with limit. Example: `update t1 set t1.foo = 'abc', t1.bar = 23 where t1.baz > 5 limit 1` -More details about how it works is available in [MySQL Docs](https://dev.mysql.com/doc/refman/8.0/en/update.html) +The support is built on performing a selection of primary keys and then performing an update with those primary keys. +For query syntax, refer to the [MySQL Docs](https://dev.mysql.com/doc/refman/8.0/en/update.html) #### Update with Multi Table Support @@ -246,7 +250,8 @@ Support is added for sharded multi-table update with column update on single tar Example: `update t1 join t2 on t1.id = t2.id join t3 on t1.col = t3.col set t1.baz = 'abc', t1.apa = 23 where t3.foo = 5 and t2.bar = 7` -More details about how it works is available in [MySQL Docs](https://dev.mysql.com/doc/refman/8.0/en/update.html) +The support is built on performing a selection of primary keys and then performing an update with those primary keys. +For query syntax, refer to the [MySQL Docs](https://dev.mysql.com/doc/refman/8.0/en/update.html) #### Update with Multi Target Support @@ -254,7 +259,9 @@ Support is added for sharded multi table target update. Example: `update t1 join t2 on t1.id = t2.id set t1.foo = 'abc', t2.bar = 23` -More details about how it works is available in [MySQL Docs](https://dev.mysql.com/doc/refman/8.0/en/update.html) +The support is built on performing a selection of primary keys from all target tables and +then performing an update for each table with their selected primary keys. +For query syntax, refer to the [MySQL Docs](https://dev.mysql.com/doc/refman/8.0/en/update.html) #### Delete with Subquery Support @@ -262,13 +269,17 @@ Support is added for sharded table delete with subquery Example: `delete from t1 where id in (select col from t2 where foo = 32 and bar = 43)` +The support is built by performing the uncorrelated subquery first and then providing the value for deletion. + #### Delete with Multi Target Support Support is added for sharded multi table target delete. Example: `delete t1, t3 from t1 join t2 on t1.id = t2.id join t3 on t1.col = t3.col` -More details about how it works is available in [MySQL Docs](https://dev.mysql.com/doc/refman/8.0/en/delete.html) +The support is built on performing a selection of primary keys from all target tables and +then performing a delete operation for each table with their selected primary keys. +For query syntax, refer to the [MySQL Docs](https://dev.mysql.com/doc/refman/8.0/en/delete.html) #### User Defined Functions Support @@ -289,7 +300,7 @@ Example: - `insert into user(id, name, email) valies (100, 'Alice', 'alice@mail.com') as new on duplicate key update name = new.name, email = new.email` - `insert into user(id, name, email) valies (100, 'Alice', 'alice@mail.com') as new(m, n, p) on duplicate key update name = n, email = p` -More details about how it works is available in [MySQL Docs](https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html) +For query syntax, refer to the [MySQL Docs](https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html) ### Query Timeout On a query timeout, Vitess closed the connection using the `kill connection` statement. This leads to connection churn @@ -328,6 +339,19 @@ The new flag `--querylog-sample-rate float` adds support for sampling queries ba The new flag `--tablet-filter-tags StringMap` adds support to VTGate for filtering tablets by tablet tag key/values, specified as comma-separated list of key:values. The tags of a tablet are defined by the VTTablet flag `--init_tags`, which is also defined as a comma-separated list of key:values. +### VReplication + +#### Multi-tenant Imports + +Support for multi-tenant imports has been added to `MoveTables`. If you have a multi-tenant architecture where each +tenant has their own database, you can import the tenants using multiple `MoveTables` workfows, one per tenant. +Each import is initiated with the new `--tenant-id` flag. The column name (and data type) need to be specified in +the VSchema of the target keyspace. + +#### VDiff support for OnlineDDL migrations + +You can now run `VDiff`s on OnlineDDL schema change migrations, which are not yet cut over. + ## Minor Changes ### New Stats @@ -336,8 +360,12 @@ The new flag `--tablet-filter-tags StringMap` adds support to VTGate for filteri VTTablet exposes two new counter stats: - * `QueryCacheHits`: Query engine query cache hits - * `QueryCacheMisses`: Query engine query cache misses + * `QueryCacheHits`: Query engine query plan cache hits + * `QueryCacheMisses`: Query engine query plan cache misses + +> [!NOTE] +> `QueryCache` does not refer to a query cache, but to a query plan cache. +> In v21, these metrics will be deprecated and renamed. ### VTTablet Query Text Characters Processed @@ -363,7 +391,7 @@ The vtadmin-web UI no longer has a dependency on highcharts for licensing reason ------------ The entire changelog for this release can be found [here](https://github.com/vitessio/vitess/blob/main/changelog/20.0/20.0.0/changelog.md). -The release includes 441 merged Pull Requests. +The release includes 419 merged Pull Requests. Thanks to all our contributors: @Aoang, @Ari1009, @GuptaManan100, @Its-Maniaco, @Maniktherana, @VaibhavMalik4187, @ajm188, @aparajon, @app/dependabot, @app/github-actions, @app/vitess-bot, @arthurschreiber, @bddicken, @beingnoble03, @brendar, @crazeteam, @dbussink, @deepthi, @demmer, @derekperkins, @ejortegau, @frouioui, @harshit-gangal, @mattlord, @maxenglander, @mdlayher, @notfelineit, @pavedroad, @rafer, @rohit-nayak-ps, @rvrangel, @shlomi-noach, @systay, @timvaillancourt, @tycol7, @vitess-bot, @vmg, @wangweicugw, @whuang8, @yoheimuta diff --git a/changelog/20.0/20.0.0/summary.md b/changelog/20.0/20.0.0/summary.md index 6e09cc982ef..3e7731a79b8 100644 --- a/changelog/20.0/20.0.0/summary.md +++ b/changelog/20.0/20.0.0/summary.md @@ -28,6 +28,9 @@ - [Delete with Multi Target Support](#delete-multi-target) - [User Defined Functions Support](#udf-support) - [Insert Row Alias Support](#insert-row-alias-support) + - **[VReplication](#vreplication)** + - [Multi-tenant Imports](#multi-tenant) + - [VDiff Support For OnlineDDL Migrations](#vdiff-online-ddl) - **[Query Timeout](#query-timeout)** - **[Flag changes](#flag-changes)** - [`pprof-http` default change](#pprof-http-default) @@ -237,7 +240,8 @@ Support is added for sharded update with limit. Example: `update t1 set t1.foo = 'abc', t1.bar = 23 where t1.baz > 5 limit 1` -More details about how it works is available in [MySQL Docs](https://dev.mysql.com/doc/refman/8.0/en/update.html) +The support is built on performing a selection of primary keys and then performing an update with those primary keys. +For query syntax, refer to the [MySQL Docs](https://dev.mysql.com/doc/refman/8.0/en/update.html) #### Update with Multi Table Support @@ -245,7 +249,8 @@ Support is added for sharded multi-table update with column update on single tar Example: `update t1 join t2 on t1.id = t2.id join t3 on t1.col = t3.col set t1.baz = 'abc', t1.apa = 23 where t3.foo = 5 and t2.bar = 7` -More details about how it works is available in [MySQL Docs](https://dev.mysql.com/doc/refman/8.0/en/update.html) +The support is built on performing a selection of primary keys and then performing an update with those primary keys. +For query syntax, refer to the [MySQL Docs](https://dev.mysql.com/doc/refman/8.0/en/update.html) #### Update with Multi Target Support @@ -253,7 +258,9 @@ Support is added for sharded multi table target update. Example: `update t1 join t2 on t1.id = t2.id set t1.foo = 'abc', t2.bar = 23` -More details about how it works is available in [MySQL Docs](https://dev.mysql.com/doc/refman/8.0/en/update.html) +The support is built on performing a selection of primary keys from all target tables and +then performing an update for each table with their selected primary keys. +For query syntax, refer to the [MySQL Docs](https://dev.mysql.com/doc/refman/8.0/en/update.html) #### Delete with Subquery Support @@ -261,13 +268,17 @@ Support is added for sharded table delete with subquery Example: `delete from t1 where id in (select col from t2 where foo = 32 and bar = 43)` +The support is built by performing the uncorrelated subquery first and then providing the value for deletion. + #### Delete with Multi Target Support Support is added for sharded multi table target delete. Example: `delete t1, t3 from t1 join t2 on t1.id = t2.id join t3 on t1.col = t3.col` -More details about how it works is available in [MySQL Docs](https://dev.mysql.com/doc/refman/8.0/en/delete.html) +The support is built on performing a selection of primary keys from all target tables and +then performing a delete operation for each table with their selected primary keys. +For query syntax, refer to the [MySQL Docs](https://dev.mysql.com/doc/refman/8.0/en/delete.html) #### User Defined Functions Support @@ -288,7 +299,7 @@ Example: - `insert into user(id, name, email) valies (100, 'Alice', 'alice@mail.com') as new on duplicate key update name = new.name, email = new.email` - `insert into user(id, name, email) valies (100, 'Alice', 'alice@mail.com') as new(m, n, p) on duplicate key update name = n, email = p` -More details about how it works is available in [MySQL Docs](https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html) +For query syntax, refer to the [MySQL Docs](https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html) ### Query Timeout On a query timeout, Vitess closed the connection using the `kill connection` statement. This leads to connection churn @@ -327,6 +338,19 @@ The new flag `--querylog-sample-rate float` adds support for sampling queries ba The new flag `--tablet-filter-tags StringMap` adds support to VTGate for filtering tablets by tablet tag key/values, specified as comma-separated list of key:values. The tags of a tablet are defined by the VTTablet flag `--init_tags`, which is also defined as a comma-separated list of key:values. +### VReplication + +#### Multi-tenant Imports + +Support for multi-tenant imports has been added to `MoveTables`. If you have a multi-tenant architecture where each +tenant has their own database, you can import the tenants using multiple `MoveTables` workfows, one per tenant. +Each import is initiated with the new `--tenant-id` flag. The column name (and data type) need to be specified in +the VSchema of the target keyspace. + +#### VDiff support for OnlineDDL migrations + +You can now run `VDiff`s on OnlineDDL schema change migrations, which are not yet cut over. + ## Minor Changes ### New Stats @@ -335,8 +359,12 @@ The new flag `--tablet-filter-tags StringMap` adds support to VTGate for filteri VTTablet exposes two new counter stats: - * `QueryCacheHits`: Query engine query cache hits - * `QueryCacheMisses`: Query engine query cache misses + * `QueryCacheHits`: Query engine query plan cache hits + * `QueryCacheMisses`: Query engine query plan cache misses + +> [!NOTE] +> `QueryCache` does not refer to a query cache, but to a query plan cache. +> In v21, these metrics will be deprecated and renamed. ### VTTablet Query Text Characters Processed diff --git a/changelog/20.0/20.0.1/changelog.md b/changelog/20.0/20.0.1/changelog.md new file mode 100644 index 00000000000..fc420a61eec --- /dev/null +++ b/changelog/20.0/20.0.1/changelog.md @@ -0,0 +1,40 @@ +# Changelog of Vitess v20.0.1 + +### Bug fixes +#### Cluster management + * Fix Downgrade problem from v20 in semi-sync plugin [#16357](https://github.com/vitessio/vitess/pull/16357) + * [release-20.0] Use default schema reload config values when config file is empty (#16393) [#16411](https://github.com/vitessio/vitess/pull/16411) +#### Docker + * [release-20.0] Fix the install dependencies script in Docker (#16340) [#16347](https://github.com/vitessio/vitess/pull/16347) +#### Documentation + * [release-20.0] Fix the `v19.0.0` release notes and use the `vitess/lite` image for the MySQL container (#16282) [#16286](https://github.com/vitessio/vitess/pull/16286) +#### Query Serving + * [release-20.0] Fix Incorrect Optimization with LIMIT and GROUP BY (#16263) [#16268](https://github.com/vitessio/vitess/pull/16268) + * [release-20.0] planner: Handle ORDER BY inside derived tables (#16353) [#16360](https://github.com/vitessio/vitess/pull/16360) + * [release-20.0] fix issue with aggregation inside of derived tables (#16366) [#16385](https://github.com/vitessio/vitess/pull/16385) + * [release-20.0] Fix Join Predicate Cleanup Bug in Route Merging (#16386) [#16390](https://github.com/vitessio/vitess/pull/16390) + * [release-20.0] Fix panic in user defined aggregation functions planning (#16398) [#16404](https://github.com/vitessio/vitess/pull/16404) + * [release-20.0] Fix panic in schema tracker in presence of keyspace routing rules (#16383) [#16405](https://github.com/vitessio/vitess/pull/16405) + * [release-20.0] Fix subquery planning having an aggregation that is used in order by as long as we can merge it all into a single route (#16402) [#16408](https://github.com/vitessio/vitess/pull/16408) +#### VReplication + * [release-20.0] VReplication: Properly handle target shards w/o a primary in Reshard (#16283) [#16292](https://github.com/vitessio/vitess/pull/16292) + * [release-20.0] VDiff: Copy non in_keyrange workflow filters to target tablet query (#16307) [#16315](https://github.com/vitessio/vitess/pull/16315) +### CI/Build +#### Build/CI + * [release-20.0] CI: Fix for xtrabackup install failures (#16329) [#16333](https://github.com/vitessio/vitess/pull/16333) +#### General + * [release-20.0] Upgrade the Golang version to `go1.22.5` [#16323](https://github.com/vitessio/vitess/pull/16323) +### Internal Cleanup +#### Documentation + * [release-20.0] Add a note on `QueryCacheHits` and `QueryCacheMisses` in the release notes (#16299) [#16306](https://github.com/vitessio/vitess/pull/16306) +#### General + * [release-20.0] Update post release `v20.0.0` [#16287](https://github.com/vitessio/vitess/pull/16287) +### Release +#### General + * [release-20.0-rc] Bump to `v20.0.1-SNAPSHOT` after the `v20.0.0` release [#16275](https://github.com/vitessio/vitess/pull/16275) + * [release-20.0] Bump to `v20.0.1-SNAPSHOT` after the `v20.0.0` release [#16276](https://github.com/vitessio/vitess/pull/16276) +### Testing +#### Query Serving + * [release-20.0] fix flaky test TestQueryTimeoutWithShardTargeting (#16150) [#16179](https://github.com/vitessio/vitess/pull/16179) + * [release-20] Vitess tester workflow (#16127) [#16417](https://github.com/vitessio/vitess/pull/16417) + diff --git a/changelog/20.0/20.0.1/release_notes.md b/changelog/20.0/20.0.1/release_notes.md new file mode 100644 index 00000000000..f9f3d04937a --- /dev/null +++ b/changelog/20.0/20.0.1/release_notes.md @@ -0,0 +1,7 @@ +# Release of Vitess v20.0.1 +The entire changelog for this release can be found [here](https://github.com/vitessio/vitess/blob/main/changelog/20.0/20.0.1/changelog.md). + +The release includes 21 merged Pull Requests. + +Thanks to all our contributors: @GuptaManan100, @app/vitess-bot, @frouioui, @shlomi-noach, @vitess-bot + diff --git a/changelog/20.0/README.md b/changelog/20.0/README.md index a143396b60c..fff48ac737f 100644 --- a/changelog/20.0/README.md +++ b/changelog/20.0/README.md @@ -1,4 +1,8 @@ ## v20.0 +* **[20.0.1](20.0.1)** + * [Changelog](20.0.1/changelog.md) + * [Release Notes](20.0.1/release_notes.md) + * **[20.0.0](20.0.0)** * [Changelog](20.0.0/changelog.md) * [Release Notes](20.0.0/release_notes.md) diff --git a/changelog/21.0/21.0.0/summary.md b/changelog/21.0/21.0.0/summary.md index 1d894120cae..0d046ae9d75 100644 --- a/changelog/21.0/21.0.0/summary.md +++ b/changelog/21.0/21.0.0/summary.md @@ -4,13 +4,17 @@ ### Table of Contents - **[Major Changes](#major-changes)** - - **[Deletions](#deletions)** + - **[Deprecations and Deletions](#deprecations-and-deletions)** - [Deletion of deprecated metrics](#metric-deletion) - - **[Breaking changes](#breaking-changes)** + - [VTTablet Flags](#vttablet-flags) + - [Metrics](#deprecations-metrics) + - **[Traffic Mirroring](#traffic-mirroring)** + - **[New VTGate Shutdown Behavior](#new-vtgate-shutdown-behavior)** + - **[Tablet Throttler: Multi-Metric support](#tablet-throttler)** ## Major Changes -### Deletion +### Deprecations and Deletions #### Deletion of deprecated metrics @@ -31,6 +35,64 @@ The following metrics that were deprecated in the previous release, have now bee | `emergency_reparent_counts` | | `planned_reparent_counts` | | `reparent_shard_operation_timings` | - +#### VTTablet Flags +- `queryserver-enable-settings-pool` flag, added in v15, has been on by default since v17. +It is now deprecated and will be removed in a future release. + +#### Metrics + +The following metrics are now deprecated, if provided please use their replacement. + +| Component | Metric Name | Replaced By | +|------------|:---------------------:|:-------------------------------:| +| `vttablet` | `QueryCacheLength` | `QueryEnginePlanCacheLength` | +| `vttablet` | `QueryCacheSize` | `QueryEnginePlanCacheSize` | +| `vttablet` | `QueryCacheCapacity` | `QueryEnginePlanCacheCapacity` | +| `vttablet` | `QueryCacheEvictions` | `QueryEnginePlanCacheEvictions` | +| `vttablet` | `QueryCacheHits` | `QueryEnginePlanCacheHits` | +| `vttablet` | `QueryCacheMisses` | `QueryEnginePlanCacheMisses` | + + +### Traffic Mirroring + +Traffic mirroring is intended to help reduce some of the uncertainty inherent to `MoveTables SwitchTraffic`. When traffic mirroring is enabled, VTGate will mirror a percentage of traffic from one keyspace to another. + +Mirror rules may be enabled through `vtctldclient` with `MoveTables MirrorTraffic`. For example: + +```bash +$ vtctldclient --server :15999 MoveTables --target-keyspace customer --workflow commerce2customer MirrorTraffic --percent 5.0 +``` + +Mirror rules can be inspected with `GetMirrorRules`. + +### New VTGate Shutdown Behavior + +We added a new option to affect the VTGate shutdown process in v21 by using a connection drain timeout rather than the older activity drain timeout. +The goal of this new behavior, connection draining option, is to disallow new connections when VTGate is shutting down, +but continue allowing existing connections to finish their work until they manually disconnect or until the `--onterm_timeout` timeout is reached, +without getting a `Server shutdown in progress` error. + +This new behavior can be enabled by specifying the new `--mysql-server-drain-onterm` flag to VTGate. + +See more information about this change by [reading its RFC](https://github.com/vitessio/vitess/issues/15971). + +### Tablet Throttler: Multi-Metric support + +Up till `v20`, the tablet throttler would only monitor and use a single metric. That would be replication lag, by default, or could be the result of a custom query. `v21` introduces a major redesign where the throttler monitors and uses multiple metrics at the same time, including the above two. + +Backwards compatible with `v20`, the default behavior in `v21` is to monitor all metrics, but only use `lag` (if the cutsom query is undefined) or the `cutsom` metric (if the custom query is defined). A `v20` `PRIMARY` is compatible with a `v21` `REPLICA`, and a `v21` `PRIMARY` is compatible with a `v20` `REPLICA`. + +However, with `v21` it is possible to assign any combination of metrics (one or more) for a given app. The throttler would then accept or reject the app's requests based on the health of _all_ assigned metrics. `v21` comes with a preset list metrics, expected to be expanded: + +- `lag`: replication lag based on heartbeat injection. +- `threads_running`: concurrent active threads on the MySQL server. +- `loadavg`: per core load average measured on the tablet instance/pod. +- `custom`: the result of a custom query executed on the MySQL server. + +Each metric has a factory threshold which can be overridden by the `UpdateThrottlerConfig` command. + +The throttler also supports the catch-all `"all"` app name, and it is thus possible to assign metrics to _all_ apps. Explicit app to metric assignments will override the catch-all configuration. + +Metrics are assigned a default _scope_, which could be `self` (isolated to the tablet) or `shard` (max, aka _worst_ value among shard tablets). It is further possible to require a different scope for each metric. diff --git a/config/mycnf/mysql84.cnf b/config/mycnf/mysql84.cnf index 90d7a535602..93e4bd571e1 100644 --- a/config/mycnf/mysql84.cnf +++ b/config/mycnf/mysql84.cnf @@ -14,7 +14,7 @@ mysqlx = 0 # 8.4 changes the default auth-plugin to caching_sha2_password and # disables mysql_native_password by default. mysql_native_password = ON -default_authentication_plugin = mysql_native_password +authentication_policy = 'mysql_native_password' # Semi-sync replication is required for automated unplanned failover # (when the primary goes away). Here we just load the plugin so it's diff --git a/config/tablet/default.yaml b/config/tablet/default.yaml index ec9d1f94833..d0e4eca477b 100644 --- a/config/tablet/default.yaml +++ b/config/tablet/default.yaml @@ -99,7 +99,6 @@ hotRowProtection: consolidator: enable|disable|notOnPrimary # enable-consolidator, enable-consolidator-replicas passthroughDML: false # queryserver-config-passthrough-dmls streamBufferSize: 32768 # queryserver-config-stream-buffer-size -queryCacheSize: 5000 # queryserver-config-query-cache-size schemaReloadIntervalSeconds: 1800 # queryserver-config-schema-reload-time watchReplication: false # watch_replication_stream terseErrors: false # queryserver-config-terse-errors diff --git a/doc/design-docs/TabletServerParamsAsYAML.md b/doc/design-docs/TabletServerParamsAsYAML.md index 52d48a5e6f6..e14712f4ff8 100644 --- a/doc/design-docs/TabletServerParamsAsYAML.md +++ b/doc/design-docs/TabletServerParamsAsYAML.md @@ -126,7 +126,6 @@ heartbeatIntervalMilliseconds: 0 # heartbeat_enable, heartbeat_interval shutdownGracePeriodSeconds: 0 # transaction_shutdown_grace_period passthroughDML: false # queryserver-config-passthrough-dmls streamBufferSize: 32768 # queryserver-config-stream-buffer-size -queryCacheSize: 5000 # queryserver-config-query-cache-size schemaReloadIntervalSeconds: 1800 # queryserver-config-schema-reload-time watchReplication: false # watch_replication_stream terseErrors: false # queryserver-config-terse-errors diff --git a/doc/internal/release/eol-process.md b/doc/internal/release/eol-process.md index f1d2a343d0f..98af2218d68 100644 --- a/doc/internal/release/eol-process.md +++ b/doc/internal/release/eol-process.md @@ -6,7 +6,8 @@ To properly deprecate a major of Vitess follow the following steps: - **Update the website documentation** > - In the ['Releases' documentation](https://vitess.io/docs/releases/), the EOL version must be moved under the ['Archived Releases' section](https://vitess.io/docs/releases/#archived-releases). > - The sidebar of the website must be changed. We need to remove the EOL version from it. To do so, we move the version folder onto the `archive` folder. + > - Add a redirect from the old URL to the new URL in `./layouts/index.redirects` under the `Redirect archived docs` section. - **Delete the `Backport To: ...` label** > - Delete the corresponding label for the EOL version, we do not want to motivate anymore backport to the EOL release branch. - **Make proper announcement on Slack** - > - Notify the community of this deprecation. \ No newline at end of file + > - Notify the community of this deprecation. diff --git a/docker/binaries/vtctldclient/Dockerfile b/docker/binaries/vtctldclient/Dockerfile new file mode 100644 index 00000000000..4dc8678827e --- /dev/null +++ b/docker/binaries/vtctldclient/Dockerfile @@ -0,0 +1,35 @@ +# Copyright 2024 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. + +ARG VT_BASE_VER=latest +ARG DEBIAN_VER=stable-slim + +FROM vitess/lite:${VT_BASE_VER} AS lite + +FROM debian:${DEBIAN_VER} + +RUN apt-get update && \ + apt-get upgrade -qq && \ + apt-get install jq curl -qq --no-install-recommends && \ + apt-get autoremove && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +COPY --from=lite /vt/bin/vtctldclient /usr/bin/ + +# add vitess user/group and add permissions +RUN groupadd -r --gid 2000 vitess && \ + useradd -r -g vitess --uid 1000 vitess + +CMD ["/usr/bin/vtctldclient"] diff --git a/docker/bootstrap/CHANGELOG.md b/docker/bootstrap/CHANGELOG.md index 1fe7f8d6acb..dd9d1c19f17 100644 --- a/docker/bootstrap/CHANGELOG.md +++ b/docker/bootstrap/CHANGELOG.md @@ -128,4 +128,8 @@ List of changes between bootstrap image versions. ## [33] - 2024-06-05 ### Changes -- Update build to golang 1.22.4 \ No newline at end of file +- Update build to golang 1.22.4 + +## [34] - 2024-07-02 +### Changes +- Update build to golang 1.22.5 \ No newline at end of file diff --git a/docker/bootstrap/Dockerfile.common b/docker/bootstrap/Dockerfile.common index 7e340b79cd7..c48a485bec3 100644 --- a/docker/bootstrap/Dockerfile.common +++ b/docker/bootstrap/Dockerfile.common @@ -1,4 +1,4 @@ -FROM --platform=linux/amd64 golang:1.22.4-bullseye +FROM --platform=linux/amd64 golang:1.22.5-bullseye # Install Vitess build dependencies RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ diff --git a/docker/bootstrap/Dockerfile.mysql57 b/docker/bootstrap/Dockerfile.mysql57 index c5be81c1cdc..983f3640472 100644 --- a/docker/bootstrap/Dockerfile.mysql57 +++ b/docker/bootstrap/Dockerfile.mysql57 @@ -16,6 +16,7 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins echo percona-server-server-5.7 percona-server-server/root_password password 'unused'; \ echo percona-server-server-5.7 percona-server-server/root_password_again password 'unused'; \ } | debconf-set-selections && \ + percona-release enable-only tools \ apt-get update -y && \ DEBIAN_FRONTEND=noninteractive apt-get install -y mysql-server libmysqlclient-dev libdbd-mysql-perl rsync libev4 percona-xtrabackup-24 && \ rm -rf /var/lib/apt/lists/* diff --git a/docker/bootstrap/Dockerfile.percona57 b/docker/bootstrap/Dockerfile.percona57 index 96a23da221a..e9cd5043d44 100644 --- a/docker/bootstrap/Dockerfile.percona57 +++ b/docker/bootstrap/Dockerfile.percona57 @@ -13,6 +13,7 @@ RUN for i in $(seq 1 10); do apt-key adv --no-tty --keyserver keyserver.ubuntu.c echo percona-server-server-5.7 percona-server-server/root_password password 'unused'; \ echo percona-server-server-5.7 percona-server-server/root_password_again password 'unused'; \ } | debconf-set-selections && \ + percona-release enable-only tools \ apt-get update && \ apt-get install -y --no-install-recommends percona-server-server-5.7 && \ apt-get install -y --no-install-recommends libperconaserverclient20-dev percona-xtrabackup-24 && \ diff --git a/docker/lite/Dockerfile b/docker/lite/Dockerfile index d5c46cac133..7c0b22aed3c 100644 --- a/docker/lite/Dockerfile +++ b/docker/lite/Dockerfile @@ -12,29 +12,26 @@ # See the License for the specific language governing permissions and # limitations under the License. -# NOTE: We have to build the Vitess binaries from scratch instead of sharing -# a base image because Docker Hub dropped the feature we relied upon to -# ensure images contain the right binaries. - -# Use a temporary layer for the build stage. -ARG bootstrap_version=33 -ARG image="vitess/bootstrap:${bootstrap_version}-mysql80" - -FROM "${image}" AS builder +FROM --platform=linux/amd64 golang:1.22.5-bullseye AS builder # Allows docker builds to set the BUILD_NUMBER ARG BUILD_NUMBER -# Re-copy sources from working tree. -COPY --chown=vitess:vitess . /vt/src/vitess.io/vitess +WORKDIR /vt/src/vitess.io/vitess -# Build and install Vitess in a temporary output directory. +# Create vitess user +RUN groupadd -r vitess && useradd -r -g vitess vitess +RUN mkdir -p /vt/vtdataroot /home/vitess +RUN chown -R vitess:vitess /vt /home/vitess USER vitess +# Re-copy sources from working tree. +COPY --chown=vitess:vitess . /vt/src/vitess.io/vitess + RUN make install PREFIX=/vt/install # Start over and build the final image. -FROM debian:bullseye-slim +FROM --platform=linux/amd64 debian:bullseye-slim # Install dependencies COPY docker/utils/install_dependencies.sh /vt/dist/install_dependencies.sh @@ -45,7 +42,7 @@ RUN groupadd -r vitess && useradd -r -g vitess vitess RUN mkdir -p /vt/vtdataroot && chown -R vitess:vitess /vt # Set up Vitess environment (just enough to run pre-built Go binaries) -ENV VTROOT /vt/src/vitess.io/vitess +ENV VTROOT /vt ENV VTDATAROOT /vt/vtdataroot ENV PATH $VTROOT/bin:$PATH diff --git a/docker/lite/Dockerfile.percona80 b/docker/lite/Dockerfile.percona80 index 96523044eff..cded55438ec 100644 --- a/docker/lite/Dockerfile.percona80 +++ b/docker/lite/Dockerfile.percona80 @@ -12,28 +12,26 @@ # See the License for the specific language governing permissions and # limitations under the License. -# NOTE: We have to build the Vitess binaries from scratch instead of sharing -# a base image because Docker Hub dropped the feature we relied upon to -# ensure images contain the right binaries. - -# Use a temporary layer for the build stage. -ARG bootstrap_version=33 -ARG image="vitess/bootstrap:${bootstrap_version}-percona80" - -FROM "${image}" AS builder +FROM --platform=linux/amd64 golang:1.22.5-bullseye AS builder # Allows docker builds to set the BUILD_NUMBER ARG BUILD_NUMBER +WORKDIR /vt/src/vitess.io/vitess + +# Create vitess user +RUN groupadd -r vitess && useradd -r -g vitess vitess +RUN mkdir -p /vt/vtdataroot /home/vitess +RUN chown -R vitess:vitess /vt /home/vitess +USER vitess + # Re-copy sources from working tree. COPY --chown=vitess:vitess . /vt/src/vitess.io/vitess -# Build and install Vitess in a temporary output directory. -USER vitess RUN make install PREFIX=/vt/install # Start over and build the final image. -FROM debian:bullseye-slim +FROM --platform=linux/amd64 debian:bullseye-slim # Install dependencies COPY docker/utils/install_dependencies.sh /vt/dist/install_dependencies.sh @@ -44,7 +42,7 @@ RUN groupadd -r vitess && useradd -r -g vitess vitess RUN mkdir -p /vt/vtdataroot && chown -R vitess:vitess /vt # Set up Vitess environment (just enough to run pre-built Go binaries) -ENV VTROOT /vt/src/vitess.io/vitess +ENV VTROOT /vt ENV VTDATAROOT /vt/vtdataroot ENV PATH $VTROOT/bin:$PATH diff --git a/docker/local/Dockerfile b/docker/local/Dockerfile deleted file mode 100644 index 33c2dfd6cd8..00000000000 --- a/docker/local/Dockerfile +++ /dev/null @@ -1,45 +0,0 @@ -ARG bootstrap_version=33 -ARG image="vitess/bootstrap:${bootstrap_version}-common" - -FROM "${image}" - -RUN apt-get update -RUN apt-get install -y sudo curl vim jq - -# Install dependencies -COPY docker/utils/install_dependencies.sh /vt/dist/install_dependencies.sh -RUN /vt/dist/install_dependencies.sh mysql80 - -COPY docker/local/install_local_dependencies.sh /vt/dist/install_local_dependencies.sh -RUN /vt/dist/install_local_dependencies.sh -RUN echo "source /vt/common/env.sh" >> /etc/bash.bashrc - -# Allows some docker builds to disable CGO -ARG CGO_ENABLED=0 - -# Re-copy sources from working tree. -COPY --chown=vitess:vitess . /vt/src/vitess.io/vitess - -# Build and install Vitess in a temporary output directory. -USER vitess - -WORKDIR /vt/src/vitess.io/vitess -RUN make install PREFIX=/vt/install - -ENV VTROOT /vt/src/vitess.io/vitess -ENV VTDATAROOT /vt/vtdataroot -ENV PATH $VTROOT/bin:$PATH -ENV PATH="/var/opt/etcd:${PATH}" - -RUN mkdir /vt/local -COPY examples/local /vt/local - -# Copy the vtadmin web app to the correct location and npm install -COPY --chown=vitess:vitess web /web -RUN npm install /web/vtadmin -RUN /web/vtadmin/build.sh - -RUN mkdir /vt/common -COPY examples/common /vt/common - -CMD cd /vt/local && ./101_initial_cluster.sh && /bin/bash diff --git a/docker/local/install_local_dependencies.sh b/docker/local/install_local_dependencies.sh deleted file mode 100755 index 07fd302e283..00000000000 --- a/docker/local/install_local_dependencies.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -# This is a script that gets run as part of the Dockerfile build -# to install dependencies for the vitess/mini image. -# -# Usage: install_local_dependencies.sh - -set -euo pipefail - -# Install etcd -ETCD_VER=v3.4.9 -DOWNLOAD_URL=https://storage.googleapis.com/etcd - -curl -k -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz -mkdir -p /var/opt/etcd -sudo tar xzvf /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz -C /var/opt/etcd --strip-components=1 -rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz - -mkdir -p /var/run/etcd && chown -R vitess:vitess /var/run/etcd - -# Clean up files we won't need in the final image. -rm -rf /var/lib/apt/lists/* - -# Install npm and node dependencies for vtadmin -curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && apt-get install -y nodejs diff --git a/docker/local/run.sh b/docker/local/run.sh deleted file mode 100755 index 16b07fc426c..00000000000 --- a/docker/local/run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker run -d -p 14200:14200 -p 14201:14201 -p 15000:15000 -p 15001:15001 -p 15991:15991 -p 15999:15999 -p 16000:16000 --rm -it vitess/local diff --git a/docker/vttestserver/Dockerfile.mysql80 b/docker/vttestserver/Dockerfile.mysql80 index 7f1d989ee5b..2e79d389c7d 100644 --- a/docker/vttestserver/Dockerfile.mysql80 +++ b/docker/vttestserver/Dockerfile.mysql80 @@ -12,28 +12,26 @@ # See the License for the specific language governing permissions and # limitations under the License. -# NOTE: We have to build the Vitess binaries from scratch instead of sharing -# a base image because Docker Hub dropped the feature we relied upon to -# ensure images contain the right binaries. - -# Use a temporary layer for the build stage. -ARG bootstrap_version=33 -ARG image="vitess/bootstrap:${bootstrap_version}-mysql80" - -FROM "${image}" AS builder +FROM --platform=linux/amd64 golang:1.22.5-bullseye AS builder # Allows docker builds to set the BUILD_NUMBER ARG BUILD_NUMBER +WORKDIR /vt/src/vitess.io/vitess + +# Create vitess user +RUN groupadd -r vitess && useradd -r -g vitess vitess +RUN mkdir -p /vt/vtdataroot /home/vitess +RUN chown -R vitess:vitess /vt /home/vitess +USER vitess + # Re-copy sources from working tree. COPY --chown=vitess:vitess . /vt/src/vitess.io/vitess -# Build and install Vitess in a temporary output directory. -USER vitess RUN make install-testing PREFIX=/vt/install # Start over and build the final image. -FROM debian:bullseye-slim +FROM --platform=linux/amd64 debian:bullseye-slim # Install dependencies COPY docker/utils/install_dependencies.sh /vt/dist/install_dependencies.sh diff --git a/examples/operator/101_initial_cluster.yaml b/examples/operator/101_initial_cluster.yaml index 2fc7ebe6a92..de627c61c50 100644 --- a/examples/operator/101_initial_cluster.yaml +++ b/examples/operator/101_initial_cluster.yaml @@ -15,7 +15,7 @@ spec: vtbackup: vitess/lite:latest vtorc: vitess/lite:latest mysqld: - mysql80Compatible: mysql:8.0.30 + mysql80Compatible: vitess/lite:latest mysqldExporter: prom/mysqld-exporter:v0.11.0 cells: - name: zone1 diff --git a/examples/operator/201_customer_tablets.yaml b/examples/operator/201_customer_tablets.yaml index 25c9d26d892..5800a5e05df 100644 --- a/examples/operator/201_customer_tablets.yaml +++ b/examples/operator/201_customer_tablets.yaml @@ -11,7 +11,7 @@ spec: vtbackup: vitess/lite:latest vtorc: vitess/lite:latest mysqld: - mysql80Compatible: mysql:8.0.30 + mysql80Compatible: vitess/lite:latest mysqldExporter: prom/mysqld-exporter:v0.11.0 cells: - name: zone1 diff --git a/examples/operator/302_new_shards.yaml b/examples/operator/302_new_shards.yaml index 4caf35ed856..2e15bc40d28 100644 --- a/examples/operator/302_new_shards.yaml +++ b/examples/operator/302_new_shards.yaml @@ -11,7 +11,7 @@ spec: vtbackup: vitess/lite:latest vtorc: vitess/lite:latest mysqld: - mysql80Compatible: mysql:8.0.30 + mysql80Compatible: vitess/lite:latest mysqldExporter: prom/mysqld-exporter:v0.11.0 cells: - name: zone1 diff --git a/examples/operator/306_down_shard_0.yaml b/examples/operator/306_down_shard_0.yaml index adc22280490..4bdb694d678 100644 --- a/examples/operator/306_down_shard_0.yaml +++ b/examples/operator/306_down_shard_0.yaml @@ -11,7 +11,7 @@ spec: vtbackup: vitess/lite:latest vtorc: vitess/lite:latest mysqld: - mysql80Compatible: mysql:8.0.30 + mysql80Compatible: vitess/lite:latest mysqldExporter: prom/mysqld-exporter:v0.11.0 cells: - name: zone1 diff --git a/examples/operator/401_scheduled_backups.yaml b/examples/operator/401_scheduled_backups.yaml index 07eab98b69d..5cb0f6c3ea1 100644 --- a/examples/operator/401_scheduled_backups.yaml +++ b/examples/operator/401_scheduled_backups.yaml @@ -52,7 +52,7 @@ spec: vtbackup: vitess/lite:latest vtorc: vitess/lite:latest mysqld: - mysql80Compatible: mysql:8.0.30 + mysql80Compatible: vitess/lite:latest mysqldExporter: prom/mysqld-exporter:v0.11.0 cells: - name: zone1 diff --git a/go.mod b/go.mod index a7516c65ee0..59d0ad29827 100644 --- a/go.mod +++ b/go.mod @@ -1,16 +1,16 @@ module vitess.io/vitess -go 1.22.4 +go 1.22.5 require ( - cloud.google.com/go/storage v1.42.0 + cloud.google.com/go/storage v1.43.0 github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 github.com/Azure/azure-pipeline-go v0.2.3 github.com/Azure/azure-storage-blob-go v0.15.0 github.com/HdrHistogram/hdrhistogram-go v0.9.0 // indirect github.com/aquarapid/vaultlib v0.5.1 github.com/armon/go-metrics v0.4.1 // indirect - github.com/aws/aws-sdk-go v1.54.2 + github.com/aws/aws-sdk-go v1.54.19 github.com/buger/jsonparser v1.1.1 github.com/cespare/xxhash/v2 v2.3.0 github.com/corpix/uarand v0.1.1 // indirect @@ -18,7 +18,7 @@ require ( github.com/evanphx/json-patch v5.9.0+incompatible github.com/fsnotify/fsnotify v1.7.0 github.com/go-sql-driver/mysql v1.7.1 - github.com/golang/glog v1.2.1 + github.com/golang/glog v1.2.2 github.com/golang/protobuf v1.5.4 github.com/golang/snappy v0.0.4 github.com/google/go-cmp v0.6.0 @@ -28,7 +28,7 @@ require ( github.com/gorilla/mux v1.8.1 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 - github.com/hashicorp/consul/api v1.29.1 + github.com/hashicorp/consul/api v1.29.2 github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/serf v0.10.1 // indirect github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428 @@ -43,14 +43,14 @@ require ( github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e github.com/opentracing/opentracing-go v1.2.0 github.com/patrickmn/go-cache v2.1.0+incompatible - github.com/philhofer/fwd v1.1.2 // indirect + github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 // indirect github.com/pierrec/lz4 v2.6.1+incompatible github.com/pires/go-proxyproto v0.7.0 github.com/pkg/errors v0.9.1 github.com/planetscale/pargzip v0.0.0-20201116224723-90c7fc03ea8a github.com/planetscale/vtprotobuf v0.5.0 github.com/prometheus/client_golang v1.19.1 - github.com/prometheus/common v0.54.0 + github.com/prometheus/common v0.55.0 github.com/sjmudd/stopwatch v0.1.1 github.com/soheilhy/cmux v0.1.5 github.com/spf13/cobra v1.8.1 @@ -59,7 +59,7 @@ require ( github.com/stretchr/testify v1.9.0 github.com/tchap/go-patricia v2.3.0+incompatible github.com/tidwall/gjson v1.17.1 - github.com/tinylib/msgp v1.1.9 // indirect + github.com/tinylib/msgp v1.2.0 // indirect github.com/uber/jaeger-client-go v2.30.0+incompatible github.com/uber/jaeger-lib v2.4.1+incompatible // indirect github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 @@ -68,22 +68,22 @@ require ( go.etcd.io/etcd/client/pkg/v3 v3.5.14 go.etcd.io/etcd/client/v3 v3.5.14 go.uber.org/mock v0.2.0 - golang.org/x/crypto v0.24.0 // indirect - golang.org/x/mod v0.18.0 // indirect - golang.org/x/net v0.26.0 + golang.org/x/crypto v0.25.0 // indirect + golang.org/x/mod v0.19.0 // indirect + golang.org/x/net v0.27.0 golang.org/x/oauth2 v0.21.0 - golang.org/x/sys v0.21.0 - golang.org/x/term v0.21.0 + golang.org/x/sys v0.22.0 + golang.org/x/term v0.22.0 golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.5.0 - golang.org/x/tools v0.22.0 - google.golang.org/api v0.184.0 - google.golang.org/genproto v0.0.0-20240610135401-a8a62080eff3 // indirect - google.golang.org/grpc v1.64.0 + golang.org/x/tools v0.23.0 + google.golang.org/api v0.188.0 + google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d // indirect + google.golang.org/grpc v1.65.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 google.golang.org/grpc/examples v0.0.0-20210430044426-28078834f35b google.golang.org/protobuf v1.34.2 - gopkg.in/DataDog/dd-trace-go.v1 v1.65.0 + gopkg.in/DataDog/dd-trace-go.v1 v1.65.1 gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect gopkg.in/ldap.v2 v2.5.1 sigs.k8s.io/yaml v1.4.0 @@ -104,25 +104,25 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 github.com/xlab/treeprint v1.2.0 go.uber.org/goleak v1.3.0 - golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 + golang.org/x/exp v0.0.0-20240707233637-46b078467d37 golang.org/x/sync v0.7.0 gonum.org/v1/gonum v0.14.0 - modernc.org/sqlite v1.30.1 + modernc.org/sqlite v1.30.2 ) require ( cloud.google.com/go v0.115.0 // indirect - cloud.google.com/go/auth v0.5.1 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect - cloud.google.com/go/compute/metadata v0.3.0 // indirect - cloud.google.com/go/iam v1.1.8 // indirect - github.com/DataDog/appsec-internal-go v1.6.0 // indirect - github.com/DataDog/datadog-agent/pkg/obfuscate v0.54.0 // indirect - github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.54.0 // indirect - github.com/DataDog/go-libddwaf/v3 v3.2.1 // indirect + cloud.google.com/go/auth v0.7.1 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.3 // indirect + cloud.google.com/go/compute/metadata v0.5.0 // indirect + cloud.google.com/go/iam v1.1.11 // indirect + github.com/DataDog/appsec-internal-go v1.7.0 // indirect + github.com/DataDog/datadog-agent/pkg/obfuscate v0.55.0 // indirect + github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.55.0 // indirect + github.com/DataDog/go-libddwaf/v3 v3.3.0 // indirect github.com/DataDog/go-sqllexer v0.0.12 // indirect github.com/DataDog/go-tuf v1.1.0-0.5.2 // indirect - github.com/DataDog/sketches-go v1.4.5 // indirect + github.com/DataDog/sketches-go v1.4.6 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/coreos/go-semver v0.3.1 // indirect @@ -139,7 +139,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/google/s2a-go v0.1.7 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect - github.com/googleapis/gax-go/v2 v2.12.4 // indirect + github.com/googleapis/gax-go/v2 v2.12.5 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect @@ -154,6 +154,7 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 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 @@ -175,22 +176,22 @@ require ( github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 // indirect - go.opentelemetry.io/otel v1.27.0 // indirect - go.opentelemetry.io/otel/metric v1.27.0 // indirect - go.opentelemetry.io/otel/trace v1.27.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect + go.opentelemetry.io/otel v1.28.0 // indirect + go.opentelemetry.io/otel/metric v1.28.0 // indirect + go.opentelemetry.io/otel/trace v1.28.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 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240610135401-a8a62080eff3 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect - modernc.org/libc v1.53.3 // indirect + modernc.org/libc v1.55.1 // indirect modernc.org/mathutil v1.6.0 // indirect modernc.org/memory v1.8.0 // indirect modernc.org/strutil v1.2.0 // indirect diff --git a/go.sum b/go.sum index eae93980f46..3ff3456402a 100644 --- a/go.sum +++ b/go.sum @@ -2,18 +2,18 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14= cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU= -cloud.google.com/go/auth v0.5.1 h1:0QNO7VThG54LUzKiQxv8C6x1YX7lUrzlAa1nVLF8CIw= -cloud.google.com/go/auth v0.5.1/go.mod h1:vbZT8GjzDf3AVqCcQmqeeM32U9HBFc32vVVAbwDsa6s= -cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= -cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= -cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= -cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/iam v1.1.8 h1:r7umDwhj+BQyz0ScZMp4QrGXjSTI3ZINnpgU2nlB/K0= -cloud.google.com/go/iam v1.1.8/go.mod h1:GvE6lyMmfxXauzNq8NbgJbeVQNspG+tcdL/W8QO1+zE= -cloud.google.com/go/longrunning v0.5.7 h1:WLbHekDbjK1fVFD3ibpFFVoyizlLRl73I7YKuAKilhU= -cloud.google.com/go/longrunning v0.5.7/go.mod h1:8GClkudohy1Fxm3owmBGid8W0pSgodEMwEAztp38Xng= -cloud.google.com/go/storage v1.42.0 h1:4QtGpplCVt1wz6g5o1ifXd656P5z+yNgzdw1tVfp0cU= -cloud.google.com/go/storage v1.42.0/go.mod h1:HjMXRFq65pGKFn6hxj6x3HCyR41uSB72Z0SO/Vn6JFQ= +cloud.google.com/go/auth v0.7.1 h1:Iv1bbpzJ2OIg16m94XI9/tlzZZl3cdeR3nGVGj78N7s= +cloud.google.com/go/auth v0.7.1/go.mod h1:VEc4p5NNxycWQTMQEDQF0bd6aTMb6VgYDXEwiJJQAbs= +cloud.google.com/go/auth/oauth2adapt v0.2.3 h1:MlxF+Pd3OmSudg/b1yZ5lJwoXCEaeedAguodky1PcKI= +cloud.google.com/go/auth/oauth2adapt v0.2.3/go.mod h1:tMQXOfZzFuNuUxOypHlQEXgdfX5cuhwU+ffUuXRJE8I= +cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= +cloud.google.com/go/iam v1.1.11 h1:0mQ8UKSfdHLut6pH9FM3bI55KWR46ketn0PuXleDyxw= +cloud.google.com/go/iam v1.1.11/go.mod h1:biXoiLWYIKntto2joP+62sd9uW5EpkZmKIvfNcTWlnQ= +cloud.google.com/go/longrunning v0.5.9 h1:haH9pAuXdPAMqHvzX0zlWQigXT7B0+CL4/2nXXdBo5k= +cloud.google.com/go/longrunning v0.5.9/go.mod h1:HD+0l9/OOW0za6UWdKJtXoFAX/BGg/3Wj8p10NeWF7c= +cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs= +cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U= @@ -32,25 +32,25 @@ github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/DataDog/appsec-internal-go v1.6.0 h1:QHvPOv/O0s2fSI/BraZJNpRDAtdlrRm5APJFZNBxjAw= -github.com/DataDog/appsec-internal-go v1.6.0/go.mod h1:pEp8gjfNLtEOmz+iZqC8bXhu0h4k7NUsW/qiQb34k1U= -github.com/DataDog/datadog-agent/pkg/obfuscate v0.54.0 h1:rLQBdJQSvuFXGs5jK9Mc8BSpD5dalmxwKPPiwzXmlTk= -github.com/DataDog/datadog-agent/pkg/obfuscate v0.54.0/go.mod h1:4/9D8y6pQo5a/Tg8GAQN8SaRIRWxxyl5QHzPRuu8D0k= -github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.54.0 h1:6t+OZCHDCzaCZwanZI+XD/gw5L4va6d/7hGjI1F1mms= -github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.54.0/go.mod h1:3yFk56PJ57yS1GqI9HAsS4PSlAeGCC9RQA7jxKzYj6g= +github.com/DataDog/appsec-internal-go v1.7.0 h1:iKRNLih83dJeVya3IoUfK+6HLD/hQsIbyBlfvLmAeb0= +github.com/DataDog/appsec-internal-go v1.7.0/go.mod h1:wW0cRfWBo4C044jHGwYiyh5moQV2x0AhnwqMuiX7O/g= +github.com/DataDog/datadog-agent/pkg/obfuscate v0.55.0 h1:q8n6qVTPATzBL02e0rxCOrLFWDNw4as0GcuKWkJENFk= +github.com/DataDog/datadog-agent/pkg/obfuscate v0.55.0/go.mod h1:/C99KWKukVnTtIiYCQ55izSNDQceREb8vSPa3zUn6jc= +github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.55.0 h1:+T+3WXCFC9g8r4AVBaD3v1LOKSLyKAtl/LtXyCTcm7I= +github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.55.0/go.mod h1:3yFk56PJ57yS1GqI9HAsS4PSlAeGCC9RQA7jxKzYj6g= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go/v5 v5.5.0 h1:G5KHeB8pWBNXT4Jtw0zAkhdxEAWSpWH00geHI6LDrKU= github.com/DataDog/datadog-go/v5 v5.5.0/go.mod h1:K9kcYBlxkcPP8tvvjZZKs/m1edNAUFzBbdpTUKfCsuw= -github.com/DataDog/go-libddwaf/v3 v3.2.1 h1:lZPc6UxCOwioHc++nsldKR50FpIrRh1uGnGLuryqnE8= -github.com/DataDog/go-libddwaf/v3 v3.2.1/go.mod h1:AP+7Atb8ftSsrha35wht7+K3R+xuzfVSQhabSO4w6CY= +github.com/DataDog/go-libddwaf/v3 v3.3.0 h1:jS72fuQpFgJZEdEJDmHJCPAgNTEMZoz1EUvimPUOiJ4= +github.com/DataDog/go-libddwaf/v3 v3.3.0/go.mod h1:Bz/0JkpGf689mzbUjKJeheJINqsyyhM8p9PDuHdK2Ec= github.com/DataDog/go-sqllexer v0.0.12 h1:ncvAr5bbwtc7JMezzcU2379oKz1oHhRF1hkR6BSvhqM= github.com/DataDog/go-sqllexer v0.0.12/go.mod h1:KwkYhpFEVIq+BfobkTC1vfqm4gTi65skV/DpDBXtexc= github.com/DataDog/go-tuf v1.1.0-0.5.2 h1:4CagiIekonLSfL8GMHRHcHudo1fQnxELS9g4tiAupQ4= github.com/DataDog/go-tuf v1.1.0-0.5.2/go.mod h1:zBcq6f654iVqmkk8n2Cx81E1JnNTMOAx1UEO/wZR+P0= github.com/DataDog/gostackparse v0.7.0 h1:i7dLkXHvYzHV308hnkvVGDL3BR4FWl7IsXNPz/IGQh4= github.com/DataDog/gostackparse v0.7.0/go.mod h1:lTfqcJKqS9KnXQGnyQMCugq3u1FP6UZMfWR0aitKFMM= -github.com/DataDog/sketches-go v1.4.5 h1:ki7VfeNz7IcNafq7yI/j5U/YCkO3LJiMDtXz9OMQbyE= -github.com/DataDog/sketches-go v1.4.5/go.mod h1:7Y8GN8Jf66DLyDhc94zuWA3uHEt/7ttt8jHOBWWrSOg= +github.com/DataDog/sketches-go v1.4.6 h1:acd5fb+QdUzGrosfNLwrIhqyrbMORpvBy7mE+vHlT3I= +github.com/DataDog/sketches-go v1.4.6/go.mod h1:7Y8GN8Jf66DLyDhc94zuWA3uHEt/7ttt8jHOBWWrSOg= github.com/HdrHistogram/hdrhistogram-go v0.9.0 h1:dpujRju0R4M/QZzcnR1LH1qm+TVG3UzkWdp5tH1WMcg= github.com/HdrHistogram/hdrhistogram-go v0.9.0/go.mod h1:nxrse8/Tzg2tg3DZcZjm6qEclQKK70g0KxO61gFFZD4= github.com/Masterminds/glide v0.13.2/go.mod h1:STyF5vcenH/rUqTEv+/hBXlSTo7KYwg2oc2f4tzPWic= @@ -73,8 +73,8 @@ github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJ github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aws/aws-sdk-go v1.54.2 h1:Wo6AVWcleNHrYa48YzfYz60hzxGRqsJrK5s/qePe+3I= -github.com/aws/aws-sdk-go v1.54.2/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go v1.54.19 h1:tyWV+07jagrNiCcGRzRhdtVjQs7Vy41NwsuOcl0IbVI= +github.com/aws/aws-sdk-go v1.54.19/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -162,8 +162,8 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= -github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= +github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -218,8 +218,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= -github.com/googleapis/gax-go/v2 v2.12.4 h1:9gWcmF85Wvq4ryPFvGFaOgPIs1AQX0d0bcbGw4Z96qg= -github.com/googleapis/gax-go/v2 v2.12.4/go.mod h1:KYEYLorsnIGDi/rPC8b5TdlB9kbKoFubselGIoBMCwI= +github.com/googleapis/gax-go/v2 v2.12.5 h1:8gw9KZK8TiVKB6q3zHY3SBzLnrGp6HQjyfYBYGmXdxA= +github.com/googleapis/gax-go/v2 v2.12.5/go.mod h1:BUDKcWo+RaKq5SC9vVYL0wLADa3VcfswbOMMRmB9H3E= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= @@ -230,10 +230,10 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vb github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= -github.com/hashicorp/consul/api v1.29.1 h1:UEwOjYJrd3lG1x5w7HxDRMGiAUPrb3f103EoeKuuEcc= -github.com/hashicorp/consul/api v1.29.1/go.mod h1:lumfRkY/coLuqMICkI7Fh3ylMG31mQSRZyef2c5YvJI= -github.com/hashicorp/consul/proto-public v0.6.1 h1:+uzH3olCrksXYWAYHKqK782CtK9scfqH+Unlw3UHhCg= -github.com/hashicorp/consul/proto-public v0.6.1/go.mod h1:cXXbOg74KBNGajC+o8RlA502Esf0R9prcoJgiOX/2Tg= +github.com/hashicorp/consul/api v1.29.2 h1:aYyRn8EdE2mSfG14S1+L9Qkjtz8RzmaWh6AcNGRNwPw= +github.com/hashicorp/consul/api v1.29.2/go.mod h1:0YObcaLNDSbtlgzIRtmRXI1ZkeuK0trCBxwZQ4MYnIk= +github.com/hashicorp/consul/proto-public v0.6.2 h1:+DA/3g/IiKlJZb88NBn0ZgXrxJp2NlvCZdEyl+qxvL0= +github.com/hashicorp/consul/proto-public v0.6.2/go.mod h1:cXXbOg74KBNGajC+o8RlA502Esf0R9prcoJgiOX/2Tg= github.com/hashicorp/consul/sdk v0.16.1 h1:V8TxTnImoPD5cj0U9Spl0TUxcytjcbbJeADFF07KdHg= github.com/hashicorp/consul/sdk v0.16.1/go.mod h1:fSXvwxB2hmh1FMZCNl6PwX0Q/1wdWtHJcZ7Ea5tns0s= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -357,6 +357,8 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= @@ -390,8 +392,8 @@ github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaR github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= -github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= -github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= +github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 h1:jYi87L8j62qkXzaYHAQAhEapgukhenIMZRBKTNRLHJ4= +github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwyq0Hs= @@ -423,8 +425,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.54.0 h1:ZlZy0BgJhTwVZUn7dLOkwCZHUkrAqd3WYtcFCWnM1D8= -github.com/prometheus/common v0.54.0/go.mod h1:/TQgMJP5CuVYveyT7n/0Ix8yLNNXy9yRSkhnLTHPDIQ= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= @@ -507,8 +509,8 @@ github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JT github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/tinylib/msgp v1.1.9 h1:SHf3yoO2sGA0veCJeCBYLHuttAVFHGm2RHgNodW7wQU= -github.com/tinylib/msgp v1.1.9/go.mod h1:BCXGB54lDD8qUEPmiG0cQQUANC4IUQyB2ItS2UDlO/k= +github.com/tinylib/msgp v1.2.0 h1:0uKB/662twsVBpYUPbokj4sTSKhWFKB7LopO2kWK8lY= +github.com/tinylib/msgp v1.2.0/go.mod h1:2vIGs3lcUo8izAATNobrCHevYZC/LMsJtw4JPiYPHro= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= @@ -531,18 +533,18 @@ go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 h1:vS1Ao/R55RNV4O7TA2Qopok8yN+X0LIP6RVWLFkprck= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0/go.mod h1:BMsdeOxN04K0L5FNUBfjFdvwWGNe/rkmSwH4Aelu/X0= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 h1:9l89oX4ba9kHbBol3Xin3leYJ+252h0zszDtBwyKe2A= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0/go.mod h1:XLZfZboOJWHNKUv7eH0inh0E9VV6eWDFB/9yJyTLPp0= -go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg= -go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= -go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik= -go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= -go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw= -go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= 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= @@ -566,11 +568,11 @@ 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= -golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= +golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w= +golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -578,8 +580,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.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= -golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 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= @@ -603,8 +605,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= @@ -655,11 +657,11 @@ golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= 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= @@ -680,8 +682,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.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= -golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= +golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= 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= @@ -690,8 +692,8 @@ golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSm golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0= gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU= -google.golang.org/api v0.184.0 h1:dmEdk6ZkJNXy1JcDhn/ou0ZUq7n9zropG2/tR4z+RDg= -google.golang.org/api v0.184.0/go.mod h1:CeDTtUEiYENAf8PPG5VZW2yNp2VM3VWbCeTioAZBTBA= +google.golang.org/api v0.188.0 h1:51y8fJ/b1AaaBRJr4yWm96fPcuxSo0JcegXE3DaHQHw= +google.golang.org/api v0.188.0/go.mod h1:VR0d+2SIiWOYG3r/jdm7adPW9hI2aRv9ETOSCQ9Beag= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -699,12 +701,12 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20240610135401-a8a62080eff3 h1:8RTI1cmuvdY9J7q/jpJWEj5UfgWjhV5MCoXaYmwLBYQ= -google.golang.org/genproto v0.0.0-20240610135401-a8a62080eff3/go.mod h1:qb66gsewNb7Ghv1enkhJiRfYGWUklv3n6G8UvprOhzA= -google.golang.org/genproto/googleapis/api v0.0.0-20240610135401-a8a62080eff3 h1:QW9+G6Fir4VcRXVH8x3LilNAb6cxBGLa6+GM4hRwexE= -google.golang.org/genproto/googleapis/api v0.0.0-20240610135401-a8a62080eff3/go.mod h1:kdrSS/OiLkPrNUpzD4aHgCq2rVuC/YRxok32HXZ4vRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3 h1:9Xyg6I9IWQZhRVfCWjKK+l6kI0jHcPesVlMnT//aHNo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d h1:/hmn0Ku5kWij/kjGsrcJeC1T/MrJi2iNWwgAqrihFwc= +google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d/go.mod h1:FfBgJBJg9GcpPvKIuHSZ/aE1g2ecGL74upMzGZjiGEY= +google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d h1:kHjw/5UfflP/L5EbledDrcG4C2597RtymmGRZvHiCuY= +google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:JU0iKnSg02Gmb5ZdV8nYsKEKsP6o/FGVWTrw4i1DA9A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= @@ -713,8 +715,8 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= -google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y= google.golang.org/grpc/examples v0.0.0-20210430044426-28078834f35b h1:D/GTYPo6I1oEo08Bfpuj3xl5XE+UGHj7//5fVyKxhsQ= @@ -733,8 +735,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= -gopkg.in/DataDog/dd-trace-go.v1 v1.65.0 h1:mMix4feEsbn2/wONR8e68JLob2QSdpiAMINhpG/8s7k= -gopkg.in/DataDog/dd-trace-go.v1 v1.65.0/go.mod h1:beNFIWd/H04d0k96cfltgiDH2+t0T5sDbyYLF3VTXqk= +gopkg.in/DataDog/dd-trace-go.v1 v1.65.1 h1:Ne7kzWr/br/jwhUJR7CnqPl/mUpNxa6LfgZs0S4htZM= +gopkg.in/DataDog/dd-trace-go.v1 v1.65.1/go.mod h1:beNFIWd/H04d0k96cfltgiDH2+t0T5sDbyYLF3VTXqk= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= @@ -767,18 +769,18 @@ honnef.co/go/gotraceui v0.2.0 h1:dmNsfQ9Vl3GwbiVD7Z8d/osC6WtGGrasyrC2suc4ZIQ= honnef.co/go/gotraceui v0.2.0/go.mod h1:qHo4/W75cA3bX0QQoSvDjbJa4R8mAyyFjbWAj63XElc= 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.21.3 h1:2mhBdWKtivdFlLR1ecKXTljPG1mfvbByX7QKztAIJl8= -modernc.org/cc/v4 v4.21.3/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= -modernc.org/ccgo/v4 v4.18.1 h1:1zF5kPBFq/ZVTulBOKgQPQITdOzzyBUfC51gVYP62E4= -modernc.org/ccgo/v4 v4.18.1/go.mod h1:ao1fAxf9a2KEOL15WY8+yP3wnpaOpP/QuyFOZ9HJolM= +modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ= +modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= +modernc.org/ccgo/v4 v4.19.2 h1:lwQZgvboKD0jBwdaeVCTouxhxAyN6iawF3STraAal8Y= +modernc.org/ccgo/v4 v4.19.2/go.mod h1:ysS3mxiMV38XGRTTcgo0DQTeTmAO4oCmJl1nX9VFI3s= modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw= modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b h1:BnN1t+pb1cy61zbvSUV7SeI0PwosMhlAEi/vBY4qxp8= modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= -modernc.org/libc v1.53.3 h1:9O0aSLZuHPgp49we24NoFFteRgXNLGBAQ3TODrW3XLg= -modernc.org/libc v1.53.3/go.mod h1:kb+Erju4FfHNE59xd2fNpv5CBeAeej6fHbx8p8xaiyI= +modernc.org/libc v1.55.1 h1:2K/vMbMDGymj0CO4mcQybYW8SW3czB+u9rlghpMkTrI= +modernc.org/libc v1.55.1/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= @@ -787,8 +789,8 @@ modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= -modernc.org/sqlite v1.30.1 h1:YFhPVfu2iIgUf9kuA1CR7iiHdcEEsI2i+yjRYHscyxk= -modernc.org/sqlite v1.30.1/go.mod h1:DUmsiWQDaAvU4abhc/N+djlom/L2o8f7gZ95RCvyoLU= +modernc.org/sqlite v1.30.2 h1:IPVVkhLu5mMVnS1dQgh3h0SAACRWcVk7aoLP9Us3UCk= +modernc.org/sqlite v1.30.2/go.mod h1:DUmsiWQDaAvU4abhc/N+djlom/L2o8f7gZ95RCvyoLU= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= diff --git a/go/cmd/vtcombo/cli/main.go b/go/cmd/vtcombo/cli/main.go index 189441594bb..5f27e581a24 100644 --- a/go/cmd/vtcombo/cli/main.go +++ b/go/cmd/vtcombo/cli/main.go @@ -206,6 +206,11 @@ func run(cmd *cobra.Command, args []string) (err error) { return fmt.Errorf("Failed to load routing rules: %w", err) } + // attempt to load any mirror rules specified by tpb + if err := vtcombo.InitMirrorRules(context.Background(), ts, tpb.GetMirrorRules()); err != nil { + return fmt.Errorf("Failed to load mirror rules: %w", err) + } + servenv.Init() tabletenv.Init() diff --git a/go/cmd/vtctldclient/command/mirror_rules.go b/go/cmd/vtctldclient/command/mirror_rules.go new file mode 100644 index 00000000000..d143546b1a8 --- /dev/null +++ b/go/cmd/vtctldclient/command/mirror_rules.go @@ -0,0 +1,58 @@ +/* +Copyright 2024 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 command + +import ( + "fmt" + + "github.com/spf13/cobra" + + "vitess.io/vitess/go/cmd/vtctldclient/cli" + + vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" +) + +// GetMirrorRules makes a GetMirrorRules gRPC call to a vtctld. +var GetMirrorRules = &cobra.Command{ + Use: "GetMirrorRules", + Short: "Displays the VSchema mirror rules.", + DisableFlagsInUseLine: true, + Args: cobra.NoArgs, + RunE: commandGetMirrorRules, +} + +func commandGetMirrorRules(cmd *cobra.Command, args []string) error { + cli.FinishedParsing(cmd) + + resp, err := client.GetMirrorRules(commandCtx, &vtctldatapb.GetMirrorRulesRequest{}) + if err != nil { + return err + } + + data, err := cli.MarshalJSON(resp.MirrorRules) + if err != nil { + return err + } + + fmt.Printf("%s\n", data) + + return nil +} + +func init() { + Root.AddCommand(GetMirrorRules) +} diff --git a/go/cmd/vtctldclient/command/onlineddl.go b/go/cmd/vtctldclient/command/onlineddl.go index 6193de9b2af..cec60ddd988 100644 --- a/go/cmd/vtctldclient/command/onlineddl.go +++ b/go/cmd/vtctldclient/command/onlineddl.go @@ -33,6 +33,7 @@ import ( topodatapb "vitess.io/vitess/go/vt/proto/topodata" vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" + "vitess.io/vitess/go/vt/proto/vttime" ) const ( @@ -55,8 +56,8 @@ var ( RunE: commandOnlineDDLCancel, } OnlineDDLCleanup = &cobra.Command{ - Use: "cleanup ", - Short: "Mark a given schema migration ready for artifact cleanup.", + Use: "cleanup ", + Short: "Mark a given schema migration, or all complete/failed/cancelled migrations, ready for artifact cleanup.", Example: "OnlineDDL cleanup test_keyspace 82fa54ac_e83e_11ea_96b7_f875a4d24e90", DisableFlagsInUseLine: true, Args: cobra.ExactArgs(2), @@ -167,12 +168,10 @@ func commandOnlineDDLCancel(cmd *cobra.Command, args []string) error { } func commandOnlineDDLCleanup(cmd *cobra.Command, args []string) error { - keyspace := cmd.Flags().Arg(0) - uuid := cmd.Flags().Arg(1) - if !schema.IsOnlineDDLUUID(uuid) { - return fmt.Errorf("%s is not a valid UUID", uuid) + keyspace, uuid, err := analyzeOnlineDDLCommandWithUuidOrAllArgument(cmd) + if err != nil { + return err } - cli.FinishedParsing(cmd) resp, err := client.CleanupSchemaMigration(commandCtx, &vtctldatapb.CleanupSchemaMigrationRequest{ @@ -307,7 +306,7 @@ func throttleCommandHelper(cmd *cobra.Command, throttleType bool) error { rule.ExpiresAt = protoutil.TimeToProto(time.Now().Add(throttle.DefaultAppThrottleDuration)) } else { rule.Ratio = 0 - rule.ExpiresAt = protoutil.TimeToProto(time.Now()) + rule.ExpiresAt = &vttime.Time{} // zero } if strings.ToLower(uuid) == AllMigrationsIndicator { diff --git a/go/cmd/vtctldclient/command/shards.go b/go/cmd/vtctldclient/command/shards.go index 1a3288a30b8..70032299f16 100644 --- a/go/cmd/vtctldclient/command/shards.go +++ b/go/cmd/vtctldclient/command/shards.go @@ -671,10 +671,10 @@ func init() { Root.AddCommand(SetShardIsPrimaryServing) - SetShardTabletControl.Flags().StringSliceVarP(&setShardTabletControlOptions.Cells, "cells", "c", nil, "Specifies a comma-separated list of cells to update.") - SetShardTabletControl.Flags().StringSliceVar(&setShardTabletControlOptions.DeniedTables, "denied-tables", nil, "Specifies a comma-separated list of tables to add to the denylist (for MoveTables). Each table name is either an exact match, or a regular expression of the form '/regexp/'.") - SetShardTabletControl.Flags().BoolVarP(&setShardTabletControlOptions.Remove, "remove", "r", false, "Removes the specified cells for MoveTables operations.") - SetShardTabletControl.Flags().BoolVar(&setShardTabletControlOptions.DisableQueryService, "disable-query-service", false, "Sets the DisableQueryService flag in the specified cells. This flag requires --denied-tables and --remove to be unset; if either is set, this flag is ignored.") + SetShardTabletControl.Flags().StringSliceVarP(&setShardTabletControlOptions.Cells, "cells", "c", nil, "Specifies a comma-separated list of cells to update (all cells will be used by default).") + SetShardTabletControl.Flags().StringSliceVar(&setShardTabletControlOptions.DeniedTables, "denied-tables", nil, "Specifies a comma-separated list of tables to add to the DeniedTables list, or remove from the list if --remove is also specified, in the Shard records (MoveTables). Each table name is either an exact match, or a regular expression of the form '/regexp/'.") + SetShardTabletControl.Flags().BoolVarP(&setShardTabletControlOptions.Remove, "remove", "r", false, "Removes the TabletControl field and its DeniedTables entries, or if specified with --denied-tables then only remove the specified tables from the DeniedTables list, in the Shard records (MoveTables) in the specified cells (using all cells by default).") + SetShardTabletControl.Flags().BoolVar(&setShardTabletControlOptions.DisableQueryService, "disable-query-service", false, "Adds or removes the DisableQueryService field in the SrvKeyspace record (Reshard) for the specified cells (using all cells by deefault). This flag requires --denied-tables and --remove to be unset; if either is set, this flag is ignored.") Root.AddCommand(SetShardTabletControl) Root.AddCommand(ShardReplicationAdd) diff --git a/go/cmd/vtctldclient/command/throttler.go b/go/cmd/vtctldclient/command/throttler.go index 9783f76720d..7a4f6c92653 100644 --- a/go/cmd/vtctldclient/command/throttler.go +++ b/go/cmd/vtctldclient/command/throttler.go @@ -27,7 +27,11 @@ import ( topodatapb "vitess.io/vitess/go/vt/proto/topodata" vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" + "vitess.io/vitess/go/vt/proto/vttime" + "vitess.io/vitess/go/vt/topo/topoproto" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle" + "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base" + "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/throttlerapp" ) var ( @@ -37,8 +41,26 @@ var ( Short: "Update the tablet throttler configuration for all tablets in the given keyspace (across all cells)", DisableFlagsInUseLine: true, Args: cobra.ExactArgs(1), + PreRunE: validateUpdateThrottlerConfig, RunE: commandUpdateThrottlerConfig, } + CheckThrottler = &cobra.Command{ + Use: "CheckThrottler [--app-name ] ", + Short: "Issue a throttler check on the given tablet.", + Example: "CheckThrottler --app-name online-ddl zone1-0000000101", + DisableFlagsInUseLine: true, + Args: cobra.ExactArgs(1), + RunE: commandCheckThrottler, + } + + GetThrottlerStatus = &cobra.Command{ + Use: "GetThrottlerStatus ", + Short: "Get the throttler status for the given tablet.", + Example: "GetThrottlerStatus zone1-0000000101", + DisableFlagsInUseLine: true, + Args: cobra.ExactArgs(1), + RunE: commandGetThrottlerStatus, + } ) var ( @@ -46,16 +68,26 @@ var ( throttledAppRule topodatapb.ThrottledAppRule unthrottledAppRule topodatapb.ThrottledAppRule throttledAppDuration time.Duration + + checkThrottlerOptions vtctldatapb.CheckThrottlerRequest + requestHeartbeats bool ) +func validateUpdateThrottlerConfig(cmd *cobra.Command, args []string) error { + if updateThrottlerConfigOptions.MetricName != "" && !cmd.Flags().Changed("threshold") { + return fmt.Errorf("--metric-name flag requires --threshold flag. Set threshold to 0 to disable the metric threshold configuration") + } + if cmd.Flags().Changed("app-name") && updateThrottlerConfigOptions.AppName == "" { + return fmt.Errorf("--app-name must not be empty") + } + + return nil +} + func commandUpdateThrottlerConfig(cmd *cobra.Command, args []string) error { keyspace := cmd.Flags().Arg(0) cli.FinishedParsing(cmd) - if throttledAppRule.Name != "" && unthrottledAppRule.Name != "" { - return fmt.Errorf("throttle-app and unthrottle-app are mutually exclusive") - } - updateThrottlerConfigOptions.CustomQuerySet = cmd.Flags().Changed("custom-query") updateThrottlerConfigOptions.Keyspace = keyspace @@ -63,7 +95,7 @@ func commandUpdateThrottlerConfig(cmd *cobra.Command, args []string) error { throttledAppRule.ExpiresAt = protoutil.TimeToProto(time.Now().Add(throttledAppDuration)) updateThrottlerConfigOptions.ThrottledApp = &throttledAppRule } else if unthrottledAppRule.Name != "" { - unthrottledAppRule.ExpiresAt = protoutil.TimeToProto(time.Now()) + unthrottledAppRule.ExpiresAt = &vttime.Time{} // zero updateThrottlerConfigOptions.ThrottledApp = &unthrottledAppRule } @@ -74,9 +106,67 @@ func commandUpdateThrottlerConfig(cmd *cobra.Command, args []string) error { return nil } +func commandCheckThrottler(cmd *cobra.Command, args []string) error { + alias, err := topoproto.ParseTabletAlias(cmd.Flags().Arg(0)) + if err != nil { + return err + } + + cli.FinishedParsing(cmd) + if _, err := base.ScopeFromString(checkThrottlerOptions.Scope); err != nil { + return err + } + resp, err := client.CheckThrottler(commandCtx, &vtctldatapb.CheckThrottlerRequest{ + TabletAlias: alias, + AppName: checkThrottlerOptions.AppName, + Scope: checkThrottlerOptions.Scope, + SkipRequestHeartbeats: !requestHeartbeats, + OkIfNotExists: checkThrottlerOptions.OkIfNotExists, + }) + if err != nil { + return err + } + + data, err := cli.MarshalJSON(resp) + if err != nil { + return err + } + + fmt.Printf("%s\n", data) + + return nil +} + +func commandGetThrottlerStatus(cmd *cobra.Command, args []string) error { + alias, err := topoproto.ParseTabletAlias(cmd.Flags().Arg(0)) + if err != nil { + return err + } + + cli.FinishedParsing(cmd) + + resp, err := client.GetThrottlerStatus(commandCtx, &vtctldatapb.GetThrottlerStatusRequest{ + TabletAlias: alias, + }) + if err != nil { + return err + } + + data, err := cli.MarshalJSON(resp) + if err != nil { + return err + } + + fmt.Printf("%s\n", data) + + return nil +} + func init() { + // UpdateThrottlerConfig UpdateThrottlerConfig.Flags().BoolVar(&updateThrottlerConfigOptions.Enable, "enable", false, "Enable the throttler") UpdateThrottlerConfig.Flags().BoolVar(&updateThrottlerConfigOptions.Disable, "disable", false, "Disable the throttler") + UpdateThrottlerConfig.Flags().StringVar(&updateThrottlerConfigOptions.MetricName, "metric-name", "", "name of the metric for which we apply a new threshold (requires --threshold). If empty, the default (either 'lag' or 'custom') metric is used.") UpdateThrottlerConfig.Flags().Float64Var(&updateThrottlerConfigOptions.Threshold, "threshold", 0, "threshold for the either default check (replication lag seconds) or custom check") UpdateThrottlerConfig.Flags().StringVar(&updateThrottlerConfigOptions.CustomQuery, "custom-query", "", "custom throttler check query") UpdateThrottlerConfig.Flags().BoolVar(&updateThrottlerConfigOptions.CheckAsCheckSelf, "check-as-check-self", false, "/throttler/check requests behave as is /throttler/check-self was called") @@ -87,6 +177,19 @@ func init() { UpdateThrottlerConfig.Flags().Float64Var(&throttledAppRule.Ratio, "throttle-app-ratio", throttle.DefaultThrottleRatio, "ratio to throttle app (app specififed in --throttled-app)") UpdateThrottlerConfig.Flags().DurationVar(&throttledAppDuration, "throttle-app-duration", throttle.DefaultAppThrottleDuration, "duration after which throttled app rule expires (app specififed in --throttled-app)") UpdateThrottlerConfig.Flags().BoolVar(&throttledAppRule.Exempt, "throttle-app-exempt", throttledAppRule.Exempt, "exempt this app from being at all throttled. WARNING: use with extreme care, as this is likely to push metrics beyond the throttler's threshold, and starve other apps") + UpdateThrottlerConfig.Flags().StringVar(&updateThrottlerConfigOptions.AppName, "app-name", "", "app name for which to assign metrics (requires --app-metrics)") + UpdateThrottlerConfig.Flags().StringSliceVar(&updateThrottlerConfigOptions.AppCheckedMetrics, "app-metrics", nil, "metrics to be used when checking the throttler for the app (requires --app-name). Empty to restore to default metrics") + UpdateThrottlerConfig.MarkFlagsMutuallyExclusive("unthrottle-app", "throttle-app") + UpdateThrottlerConfig.MarkFlagsRequiredTogether("app-name", "app-metrics") Root.AddCommand(UpdateThrottlerConfig) + // Check Throttler + CheckThrottler.Flags().StringVar(&checkThrottlerOptions.AppName, "app-name", throttlerapp.VitessName.String(), "app name to check") + CheckThrottler.Flags().StringVar(&checkThrottlerOptions.Scope, "scope", base.UndefinedScope.String(), "check scope ('shard', 'self' or leave empty for per-metric defaults)") + CheckThrottler.Flags().BoolVar(&requestHeartbeats, "request-heartbeats", false, "request heartbeat lease") + CheckThrottler.Flags().BoolVar(&checkThrottlerOptions.OkIfNotExists, "ok-if-not-exists", false, "return OK even if metric does not exist") + Root.AddCommand(CheckThrottler) + + // GetThrottlerStatus + Root.AddCommand(GetThrottlerStatus) } diff --git a/go/cmd/vtctldclient/command/vreplication/common/mirrortraffic.go b/go/cmd/vtctldclient/command/vreplication/common/mirrortraffic.go new file mode 100644 index 00000000000..68f0cfbc68c --- /dev/null +++ b/go/cmd/vtctldclient/command/vreplication/common/mirrortraffic.go @@ -0,0 +1,89 @@ +/* +Copyright 2024 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 common + +import ( + "bytes" + "fmt" + + "github.com/spf13/cobra" + + "vitess.io/vitess/go/cmd/vtctldclient/cli" + + topodatapb "vitess.io/vitess/go/vt/proto/topodata" + vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" +) + +func GetMirrorTrafficCommand(opts *SubCommandsOpts) *cobra.Command { + cmd := &cobra.Command{ + Use: "mirrortraffic", + Short: fmt.Sprintf("Mirror traffic for a %s MoveTables workflow.", opts.SubCommand), + Example: fmt.Sprintf(`vtctldclient --server localhost:15999 %s --workflow %s --target-keyspace customer mirrortraffic --percent 5.0`, opts.SubCommand, opts.Workflow), + DisableFlagsInUseLine: true, + Aliases: []string{"MirrorTraffic"}, + Args: cobra.NoArgs, + PreRun: func(cmd *cobra.Command, args []string) { + if !cmd.Flags().Lookup("tablet-types").Changed { + // We mirror traffic for all tablet types if none are provided. + MirrorTrafficOptions.TabletTypes = []topodatapb.TabletType{ + topodatapb.TabletType_PRIMARY, + topodatapb.TabletType_REPLICA, + topodatapb.TabletType_RDONLY, + } + } + }, + RunE: commandMirrorTraffic, + } + return cmd +} + +func commandMirrorTraffic(cmd *cobra.Command, args []string) error { + format, err := GetOutputFormat(cmd) + if err != nil { + return err + } + + cli.FinishedParsing(cmd) + + req := &vtctldatapb.WorkflowMirrorTrafficRequest{ + Keyspace: BaseOptions.TargetKeyspace, + Workflow: BaseOptions.Workflow, + TabletTypes: MirrorTrafficOptions.TabletTypes, + Percent: MirrorTrafficOptions.Percent, + } + resp, err := GetClient().WorkflowMirrorTraffic(GetCommandCtx(), req) + if err != nil { + return err + } + + var output []byte + if format == "json" { + output, err = cli.MarshalJSONPretty(resp) + if err != nil { + return err + } + } else { + tout := bytes.Buffer{} + tout.WriteString(resp.Summary + "\n\n") + tout.WriteString(fmt.Sprintf("Start State: %s\n", resp.StartState)) + tout.WriteString(fmt.Sprintf("Current State: %s\n", resp.CurrentState)) + output = tout.Bytes() + } + fmt.Printf("%s\n", output) + + return nil +} diff --git a/go/cmd/vtctldclient/command/vreplication/common/switchtraffic.go b/go/cmd/vtctldclient/command/vreplication/common/switchtraffic.go index 4004afc0ac0..3429c10303c 100644 --- a/go/cmd/vtctldclient/command/vreplication/common/switchtraffic.go +++ b/go/cmd/vtctldclient/command/vreplication/common/switchtraffic.go @@ -48,6 +48,9 @@ func GetSwitchTrafficCommand(opts *SubCommandsOpts) *cobra.Command { topodatapb.TabletType_RDONLY, } } + if SwitchTrafficOptions.Timeout.Seconds() < 1 { + return fmt.Errorf("timeout value must be at least 1 second") + } return nil }, RunE: commandSwitchTraffic, diff --git a/go/cmd/vtctldclient/command/vreplication/common/utils.go b/go/cmd/vtctldclient/command/vreplication/common/utils.go index a742f31a9ff..da774647c38 100644 --- a/go/cmd/vtctldclient/command/vreplication/common/utils.go +++ b/go/cmd/vtctldclient/command/vreplication/common/utils.go @@ -47,7 +47,6 @@ var ( } onDDLDefault = binlogdatapb.OnDDLAction_IGNORE.String() MaxReplicationLagDefault = 30 * time.Second - TimeoutDefault = 30 * time.Second BaseOptions = struct { Workflow string @@ -224,6 +223,12 @@ func AddCommonCreateFlags(cmd *cobra.Command) { cmd.Flags().BoolVar(&CreateOptions.StopAfterCopy, "stop-after-copy", false, "Stop the workflow after it's finished copying the existing rows and before it starts replicating changes.") } +var MirrorTrafficOptions = struct { + DryRun bool + Percent float32 + TabletTypes []topodatapb.TabletType +}{} + var SwitchTrafficOptions = struct { Cells []string TabletTypes []topodatapb.TabletType @@ -239,7 +244,7 @@ var SwitchTrafficOptions = struct { func AddCommonSwitchTrafficFlags(cmd *cobra.Command, initializeTargetSequences bool) { cmd.Flags().StringSliceVarP(&SwitchTrafficOptions.Cells, "cells", "c", nil, "Cells and/or CellAliases to switch traffic in.") cmd.Flags().Var((*topoproto.TabletTypeListFlag)(&SwitchTrafficOptions.TabletTypes), "tablet-types", "Tablet types to switch traffic for.") - cmd.Flags().DurationVar(&SwitchTrafficOptions.Timeout, "timeout", TimeoutDefault, "Specifies the maximum time to wait, in seconds, for VReplication to catch up on primary tablets. The traffic switch will be cancelled on timeout.") + cmd.Flags().DurationVar(&SwitchTrafficOptions.Timeout, "timeout", workflow.DefaultTimeout, "Specifies the maximum time to wait, in seconds, for VReplication to catch up on primary tablets. The traffic switch will be cancelled on timeout.") cmd.Flags().DurationVar(&SwitchTrafficOptions.MaxReplicationLagAllowed, "max-replication-lag-allowed", MaxReplicationLagDefault, "Allow traffic to be switched only if VReplication lag is below this.") cmd.Flags().BoolVar(&SwitchTrafficOptions.EnableReverseReplication, "enable-reverse-replication", true, "Setup replication going back to the original source keyspace to support rolling back the traffic cutover.") cmd.Flags().BoolVar(&SwitchTrafficOptions.DryRun, "dry-run", false, "Print the actions that would be taken and report any known errors that would have occurred.") diff --git a/go/cmd/vtctldclient/command/vreplication/lookupvindex/lookupvindex.go b/go/cmd/vtctldclient/command/vreplication/lookupvindex/lookupvindex.go index b703e873bd0..9650a52e8a5 100644 --- a/go/cmd/vtctldclient/command/vreplication/lookupvindex/lookupvindex.go +++ b/go/cmd/vtctldclient/command/vreplication/lookupvindex/lookupvindex.go @@ -291,7 +291,7 @@ func registerCommands(root *cobra.Command) { create.Flags().StringSliceVar(&createOptions.TableOwnerColumns, "table-owner-columns", nil, "The columns to read from the owner table. These will be used to build the hash which gets stored as the keyspace_id value in the lookup table.") create.MarkFlagRequired("table-owner-columns") create.Flags().StringVar(&createOptions.TableName, "table-name", "", "The name of the lookup table. If not specified, then it will be created using the same name as the Lookup Vindex.") - create.Flags().StringVar(&createOptions.TableVindexType, "table-vindex-type", "", "The primary vindex name/type to use for the lookup table, if the table-keyspace is sharded. This must match the name of a vindex defined in the table-keyspace. If no value is provided then the default type will be used based on the table-owner-columns types.") + create.Flags().StringVar(&createOptions.TableVindexType, "table-vindex-type", "", "The primary vindex name/type to use for the lookup table, if the table-keyspace is sharded. If no value is provided then the default type will be used based on the table-owner-columns types.") create.Flags().BoolVar(&createOptions.IgnoreNulls, "ignore-nulls", false, "Do not add corresponding records in the lookup table if any of the owner table's 'from' fields are NULL.") create.Flags().BoolVar(&createOptions.ContinueAfterCopyWithOwner, "continue-after-copy-with-owner", true, "Vindex will continue materialization after the backfill completes when an owner is provided.") // VReplication specific flags. diff --git a/go/cmd/vtctldclient/command/vreplication/movetables/movetables.go b/go/cmd/vtctldclient/command/vreplication/movetables/movetables.go index d729230e7a7..4d8f9eaf3f0 100644 --- a/go/cmd/vtctldclient/command/vreplication/movetables/movetables.go +++ b/go/cmd/vtctldclient/command/vreplication/movetables/movetables.go @@ -20,6 +20,7 @@ import ( "github.com/spf13/cobra" "vitess.io/vitess/go/cmd/vtctldclient/command/vreplication/common" + "vitess.io/vitess/go/vt/topo/topoproto" ) var ( @@ -67,6 +68,11 @@ func registerCommands(root *cobra.Command) { base.AddCommand(common.GetStartCommand(opts)) base.AddCommand(common.GetStopCommand(opts)) + mirrorTrafficCommand := common.GetMirrorTrafficCommand(opts) + mirrorTrafficCommand.Flags().Var((*topoproto.TabletTypeListFlag)(&common.MirrorTrafficOptions.TabletTypes), "tablet-types", "Tablet types to mirror traffic for.") + mirrorTrafficCommand.Flags().Float32Var(&common.MirrorTrafficOptions.Percent, "percent", 1.0, "Percentage of traffic to mirror.") + base.AddCommand(mirrorTrafficCommand) + switchTrafficCommand := common.GetSwitchTrafficCommand(opts) common.AddCommonSwitchTrafficFlags(switchTrafficCommand, true) common.AddShardSubsetFlag(switchTrafficCommand, &common.SwitchTrafficOptions.Shards) diff --git a/go/cmd/vtctldclient/command/vreplication/vdiff/vdiff.go b/go/cmd/vtctldclient/command/vreplication/vdiff/vdiff.go index dfca3386491..9355049e39b 100644 --- a/go/cmd/vtctldclient/command/vreplication/vdiff/vdiff.go +++ b/go/cmd/vtctldclient/command/vreplication/vdiff/vdiff.go @@ -35,6 +35,7 @@ import ( "vitess.io/vitess/go/cmd/vtctldclient/command/vreplication/common" "vitess.io/vitess/go/protoutil" "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/vt/vtctl/workflow" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vttablet/tabletmanager/vdiff" @@ -874,7 +875,7 @@ func registerCommands(root *cobra.Command) { create.Flags().StringSliceVar(&createOptions.TargetCells, "target-cells", nil, "The target cell(s) to compare with; default is any available cell.") create.Flags().Var((*topoprotopb.TabletTypeListFlag)(&createOptions.TabletTypes), "tablet-types", "Tablet types to use on the source and target.") create.Flags().BoolVar(&common.CreateOptions.TabletTypesInPreferenceOrder, "tablet-types-in-preference-order", true, "When performing source tablet selection, look for candidates in the type order as they are listed in the tablet-types flag.") - create.Flags().DurationVar(&createOptions.FilteredReplicationWaitTime, "filtered-replication-wait-time", 30*time.Second, "Specifies the maximum time to wait, in seconds, for replication to catch up when syncing tablet streams.") + create.Flags().DurationVar(&createOptions.FilteredReplicationWaitTime, "filtered-replication-wait-time", workflow.DefaultTimeout, "Specifies the maximum time to wait, in seconds, for replication to catch up when syncing tablet streams.") create.Flags().Int64Var(&createOptions.Limit, "limit", math.MaxInt64, "Max rows to stop comparing after.") create.Flags().BoolVar(&createOptions.DebugQuery, "debug-query", false, "Adds a mysql query to the report that can be used for further debugging.") create.Flags().Int64Var(&createOptions.MaxReportSampleRows, "max-report-sample-rows", 10, "Maximum number of row differences to report (0 for all differences). NOTE: when increasing this value it is highly recommended to also specify --only-pks") diff --git a/go/cmd/vtctldclient/command/vschemas.go b/go/cmd/vtctldclient/command/vschemas.go index 37ad00ccb6b..0965b81a785 100644 --- a/go/cmd/vtctldclient/command/vschemas.go +++ b/go/cmd/vtctldclient/command/vschemas.go @@ -102,7 +102,7 @@ func commandApplyVSchema(cmd *cobra.Command, args []string) error { } var vs vschemapb.Keyspace - err = json2.Unmarshal(schema, &vs) + err = json2.UnmarshalPB(schema, &vs) if err != nil { return err } diff --git a/go/cmd/vtgateclienttest/services/fallback.go b/go/cmd/vtgateclienttest/services/fallback.go index 72175fe01ce..dab0e912ddb 100644 --- a/go/cmd/vtgateclienttest/services/fallback.go +++ b/go/cmd/vtgateclienttest/services/fallback.go @@ -60,10 +60,6 @@ func (c fallbackClient) CloseSession(ctx context.Context, session *vtgatepb.Sess return c.fallback.CloseSession(ctx, session) } -func (c fallbackClient) ResolveTransaction(ctx context.Context, dtid string) error { - return c.fallback.ResolveTransaction(ctx, dtid) -} - func (c fallbackClient) VStream(ctx context.Context, tabletType topodatapb.TabletType, vgtid *binlogdatapb.VGtid, filter *binlogdatapb.Filter, flags *vtgatepb.VStreamFlags, send func([]*binlogdatapb.VEvent) error) error { return c.fallback.VStream(ctx, tabletType, vgtid, filter, flags, send) } diff --git a/go/cmd/vtgateclienttest/services/terminal.go b/go/cmd/vtgateclienttest/services/terminal.go index 7245be547ac..8fa321e2606 100644 --- a/go/cmd/vtgateclienttest/services/terminal.go +++ b/go/cmd/vtgateclienttest/services/terminal.go @@ -71,10 +71,6 @@ func (c *terminalClient) CloseSession(ctx context.Context, session *vtgatepb.Ses return errTerminal } -func (c *terminalClient) ResolveTransaction(ctx context.Context, dtid string) error { - return errTerminal -} - func (c *terminalClient) VStream(ctx context.Context, tabletType topodatapb.TabletType, vgtid *binlogdatapb.VGtid, filter *binlogdatapb.Filter, flags *vtgatepb.VStreamFlags, send func([]*binlogdatapb.VEvent) error) error { return errTerminal } diff --git a/go/cmd/vttestserver/cli/main.go b/go/cmd/vttestserver/cli/main.go index 5601623b2fa..479ea4441f8 100644 --- a/go/cmd/vttestserver/cli/main.go +++ b/go/cmd/vttestserver/cli/main.go @@ -206,7 +206,7 @@ func New() (cmd *cobra.Command) { cmd.Flags().BoolVar(&config.EnableSystemSettings, "enable_system_settings", true, "This will enable the system settings to be changed per session at the database connection level") cmd.Flags().StringVar(&config.TransactionMode, "transaction_mode", "MULTI", "Transaction mode MULTI (default), SINGLE or TWOPC ") - cmd.Flags().Float64Var(&config.TransactionTimeout, "queryserver-config-transaction-timeout", 0, "query server transaction timeout (in seconds), a transaction will be killed if it takes longer than this value") + cmd.Flags().DurationVar(&config.TransactionTimeout, "queryserver-config-transaction-timeout", 30*time.Second, "query server transaction timeout, a transaction will be killed if it takes longer than this value") cmd.Flags().StringVar(&config.TabletHostName, "tablet_hostname", "localhost", "The hostname to use for the tablet otherwise it will be derived from OS' hostname") diff --git a/go/flags/endtoend/vtcombo.txt b/go/flags/endtoend/vtcombo.txt index 8d868e9f49c..c59cd789ed3 100644 --- a/go/flags/endtoend/vtcombo.txt +++ b/go/flags/endtoend/vtcombo.txt @@ -223,6 +223,7 @@ Flags: --mycnf_slow_log_path string mysql slow query log path --mycnf_socket_file string mysql socket file --mycnf_tmp_dir string mysql tmp directory + --mysql-server-drain-onterm If set, the server waits for --onterm_timeout for already connected clients to complete their in flight work --mysql-server-keepalive-period duration TCP period between keep-alives --mysql-server-pool-conn-read-buffers If set, the server will pool incoming connection read buffers --mysql-shutdown-timeout duration timeout to use when MySQL is being shut down. (default 5m0s) @@ -298,7 +299,6 @@ Flags: --queryserver-config-truncate-error-len int truncate errors sent to client if they are longer than this value (0 means do not truncate) --queryserver-config-txpool-timeout duration query server transaction pool timeout, it is how long vttablet waits if tx pool is full (default 1s) --queryserver-config-warn-result-size int query server result size warning threshold, warn if number of rows returned from vttablet for non-streaming queries exceeds this - --queryserver-enable-settings-pool Enable pooling of connections with modified system settings (default true) --queryserver-enable-views Enable views support in vttablet. --queryserver_enable_online_ddl Enable online DDL. (default true) --redact-debug-ui-queries redact full queries and bind variables from debug UI @@ -389,7 +389,6 @@ Flags: --transaction_mode string SINGLE: disallow multi-db transactions, MULTI: allow multi-db transactions with best effort commit, TWOPC: allow multi-db transactions with 2pc commit (default "MULTI") --truncate-error-len int truncate errors sent to client if they are longer than this value (0 means do not truncate) --twopc_abandon_age float time in seconds. Any unresolved transaction older than this time will be sent to the coordinator to be resolved. - --twopc_coordinator_address string address of the (VTGate) process(es) that will be used to notify of abandoned transactions. --twopc_enable if the flag is on, 2pc is enabled. Other 2pc flags must be supplied. --tx-throttler-config string Synonym to -tx_throttler_config (default "target_replication_lag_sec:2 max_replication_lag_sec:10 initial_rate:100 max_increase:1 emergency_decrease:0.5 min_duration_between_increases_sec:40 max_duration_between_increases_sec:62 min_duration_between_decreases_sec:20 spread_backlog_across_sec:20 age_bad_rate_after_sec:180 bad_rate_increase:0.1 max_rate_approach_threshold:0.9") --tx-throttler-default-priority int Default priority assigned to queries that lack priority information (default 100) diff --git a/go/flags/endtoend/vtctldclient.txt b/go/flags/endtoend/vtctldclient.txt index 393b9ada10d..01db05f602d 100644 --- a/go/flags/endtoend/vtctldclient.txt +++ b/go/flags/endtoend/vtctldclient.txt @@ -19,6 +19,7 @@ Available Commands: Backup Uses the BackupStorage service on the given tablet to create and store a new backup. BackupShard Finds the most up-to-date REPLICA, RDONLY, or SPARE tablet in the given shard and uses the BackupStorage service on that tablet to create and store a new backup. ChangeTabletType Changes the db type for the specified tablet, if possible. + CheckThrottler Issue a throttler check on the given tablet. CreateKeyspace Creates the specified keyspace in the topology. CreateShard Creates the specified shard in the topology. DeleteCellInfo Deletes the CellInfo for the provided cell. @@ -42,6 +43,7 @@ Available Commands: GetKeyspace Returns information about the given keyspace from the topology. GetKeyspaceRoutingRules Displays the currently active keyspace routing rules. GetKeyspaces Returns information about every keyspace in the topology. + GetMirrorRules Displays the VSchema mirror rules. GetPermissions Displays the permissions for a tablet. GetRoutingRules Displays the VSchema routing rules. GetSchema Displays the full schema for a tablet, optionally restricted to the specified tables/views. @@ -55,6 +57,7 @@ Available Commands: GetTablet Outputs a JSON structure that contains information about the tablet. GetTabletVersion Print the version of a tablet from its debug vars. GetTablets Looks up tablets according to filter criteria. + GetThrottlerStatus Get the throttler status for the given tablet. GetTopologyPath Gets the value associated with the particular path (key) in the topology server. GetVSchema Prints a JSON representation of a keyspace's topo record. GetWorkflows Gets all vreplication workflows (Reshard, MoveTables, etc) in the given keyspace. diff --git a/go/flags/endtoend/vtgate.txt b/go/flags/endtoend/vtgate.txt index 16f261194ca..6d68e09d09b 100644 --- a/go/flags/endtoend/vtgate.txt +++ b/go/flags/endtoend/vtgate.txt @@ -119,6 +119,7 @@ Flags: --max_payload_size int The threshold for query payloads in bytes. A payload greater than this threshold will result in a failure to handle the query. --message_stream_grace_period duration the amount of time to give for a vttablet to resume if it ends a message stream, usually because of a reparent. (default 30s) --min_number_serving_vttablets int The minimum number of vttablets for each replicating tablet_type (e.g. replica, rdonly) that will be continue to be used even with replication lag above discovery_low_replication_lag, but still below discovery_high_replication_lag_minimum_serving. (default 2) + --mysql-server-drain-onterm If set, the server waits for --onterm_timeout for already connected clients to complete their in flight work --mysql-server-keepalive-period duration TCP period between keep-alives --mysql-server-pool-conn-read-buffers If set, the server will pool incoming connection read buffers --mysql_allow_clear_text_without_tls If set, the server will allow the use of a clear text password over non-SSL connections. diff --git a/go/flags/endtoend/vttablet.txt b/go/flags/endtoend/vttablet.txt index d160968e014..f5a7f8e8f51 100644 --- a/go/flags/endtoend/vttablet.txt +++ b/go/flags/endtoend/vttablet.txt @@ -289,7 +289,6 @@ Flags: --queryserver-config-truncate-error-len int truncate errors sent to client if they are longer than this value (0 means do not truncate) --queryserver-config-txpool-timeout duration query server transaction pool timeout, it is how long vttablet waits if tx pool is full (default 1s) --queryserver-config-warn-result-size int query server result size warning threshold, warn if number of rows returned from vttablet for non-streaming queries exceeds this - --queryserver-enable-settings-pool Enable pooling of connections with modified system settings (default true) --queryserver-enable-views Enable views support in vttablet. --queryserver_enable_online_ddl Enable online DDL. (default true) --redact-debug-ui-queries redact full queries and bind variables from debug UI @@ -388,7 +387,6 @@ Flags: --transaction_limit_by_username Include VTGateCallerID.username when considering who the user is for the purpose of transaction limit. (default true) --transaction_limit_per_user float Maximum number of transactions a single user is allowed to use at any time, represented as fraction of -transaction_cap. (default 0.4) --twopc_abandon_age float time in seconds. Any unresolved transaction older than this time will be sent to the coordinator to be resolved. - --twopc_coordinator_address string address of the (VTGate) process(es) that will be used to notify of abandoned transactions. --twopc_enable if the flag is on, 2pc is enabled. Other 2pc flags must be supplied. --tx-throttler-config string Synonym to -tx_throttler_config (default "target_replication_lag_sec:2 max_replication_lag_sec:10 initial_rate:100 max_increase:1 emergency_decrease:0.5 min_duration_between_increases_sec:40 max_duration_between_increases_sec:62 min_duration_between_decreases_sec:20 spread_backlog_across_sec:20 age_bad_rate_after_sec:180 bad_rate_increase:0.1 max_rate_approach_threshold:0.9") --tx-throttler-default-priority int Default priority assigned to queries that lack priority information (default 100) @@ -418,7 +416,6 @@ Flags: --vstream-binlog-rotation-threshold int Byte size at which a VStreamer will attempt to rotate the source's open binary log before starting a GTID snapshot based stream (e.g. a ResultStreamer or RowStreamer) (default 67108864) --vstream_dynamic_packet_size Enable dynamic packet sizing for VReplication. This will adjust the packet size during replication to improve performance. (default true) --vstream_packet_size int Suggested packet size for VReplication streamer. This is used only as a recommendation. The actual packet size may be more or less than this amount. (default 250000) - --vtgate_protocol string how to talk to vtgate (default "grpc") --vttablet_skip_buildinfo_tags string comma-separated list of buildinfo tags to skip from merging with --init_tags. each tag is either an exact match or a regular expression of the form '/regexp/'. (default "/.*/") --wait_for_backup_interval duration (init restore parameter) if this is greater than 0, instead of starting up empty when no backups are found, keep checking at this interval for a backup to appear --watch_replication_stream When enabled, vttablet will stream the MySQL replication stream from the local server, and use it to update schema when it sees a DDL. diff --git a/go/flags/endtoend/vttestserver.txt b/go/flags/endtoend/vttestserver.txt index 8cce76afc65..95c69714e59 100644 --- a/go/flags/endtoend/vttestserver.txt +++ b/go/flags/endtoend/vttestserver.txt @@ -106,7 +106,7 @@ Flags: --pprof-http enable pprof http endpoints --proto_topo string Define the fake cluster topology as a compact text format encoded vttest proto. See vttest.proto for more information. --purge_logs_interval duration how often try to remove old logs (default 1h0m0s) - --queryserver-config-transaction-timeout float query server transaction timeout (in seconds), a transaction will be killed if it takes longer than this value + --queryserver-config-transaction-timeout duration query server transaction timeout, a transaction will be killed if it takes longer than this value (default 30s) --rdonly_count int Rdonly tablets per shard (default 1) --replica_count int Replica tablets per shard (includes primary) (default 2) --replication_connect_retry duration how long to wait in between replica reconnect attempts. Only precise to the second. (default 10s) diff --git a/go/mysql/binlog/constants.go b/go/mysql/binlog/constants.go index d08889efde8..89a08b7f209 100644 --- a/go/mysql/binlog/constants.go +++ b/go/mysql/binlog/constants.go @@ -79,6 +79,9 @@ const ( // TypeTime2 is MYSQL_TYPE_TIME2 TypeTime2 = 19 + // TypeVector is MYSQL_TYPE_VECTOR + TypeVector = 242 + // TypeJSON is MYSQL_TYPE_JSON TypeJSON = 245 diff --git a/go/mysql/binlog/rbr.go b/go/mysql/binlog/rbr.go index 73c293a8750..23faf188ae9 100644 --- a/go/mysql/binlog/rbr.go +++ b/go/mysql/binlog/rbr.go @@ -111,7 +111,7 @@ func CellLength(data []byte, pos int, typ byte, metadata uint16) (int, error) { return intg0*4 + dig2bytes[intg0x] + frac0*4 + dig2bytes[frac0x], nil case TypeEnum, TypeSet: return int(metadata & 0xff), nil - case TypeJSON, TypeTinyBlob, TypeMediumBlob, TypeLongBlob, TypeBlob, TypeGeometry: + case TypeJSON, TypeTinyBlob, TypeMediumBlob, TypeLongBlob, TypeBlob, TypeGeometry, TypeVector: // Of the Blobs, only TypeBlob is used in binary logs, // but supports others just in case. switch metadata { @@ -652,8 +652,8 @@ func CellValue(data []byte, pos int, typ byte, metadata uint16, field *querypb.F return sqltypes.MakeTrusted(querypb.Type_SET, data[pos:pos+l]), l, nil - case TypeJSON, TypeTinyBlob, TypeMediumBlob, TypeLongBlob, TypeBlob: - // Only TypeBlob is used in binary logs, + case TypeJSON, TypeTinyBlob, TypeMediumBlob, TypeLongBlob, TypeBlob, TypeVector: + // Only TypeBlob and TypeVector is used in binary logs, // but supports others just in case. l := 0 switch metadata { diff --git a/go/mysql/binlog_event.go b/go/mysql/binlog_event.go index 3acf99c2408..5e5ce01eac3 100644 --- a/go/mysql/binlog_event.go +++ b/go/mysql/binlog_event.go @@ -124,9 +124,12 @@ type BinlogEvent interface { // IsWriteRows(), IsUpdateRows(), or IsDeleteRows() returns // true. Rows(BinlogFormat, *TableMap) (Rows, error) - // TransactionPayload returns a list of BinlogEvents contained - // within the compressed transaction. - TransactionPayload(BinlogFormat) ([]BinlogEvent, error) + // TransactionPayload returns a TransactionPayload type which provides + // a GetNextEvent() method to iterate over the events contained within + // the uncompressed payload. You must call Close() when you are done + // with the TransactionPayload to ensure that the underlying resources + // used are cleaned up. + TransactionPayload(BinlogFormat) (*TransactionPayload, error) // NextLogFile returns the name of the next binary log file & pos. // This is only valid if IsRotate() returns true NextLogFile(BinlogFormat) (string, uint64, error) @@ -155,7 +158,7 @@ type BinlogFormat struct { HeaderSizes []byte // ServerVersion is the name of the MySQL server version. - // It starts with something like 5.6.33-xxxx. + // It starts with something like 8.0.34-xxxx. ServerVersion string // FormatVersion is the version number of the binlog file format. diff --git a/go/mysql/binlog_event_common.go b/go/mysql/binlog_event_common.go index f95ed847e0a..c95873614f0 100644 --- a/go/mysql/binlog_event_common.go +++ b/go/mysql/binlog_event_common.go @@ -55,8 +55,6 @@ const ( BinlogFixedHeaderLen = 19 // The offset from 0 where the type is stored as 1 byte. BinlogEventTypeOffset = 4 - // Offset from 0 where the 4 byte length is stored. - BinlogEventLenOffset = 9 // Byte length of the checksum suffix when the CRC32 algorithm is used. BinlogCRC32ChecksumLen = 4 ) diff --git a/go/mysql/binlog_event_compression.go b/go/mysql/binlog_event_compression.go index 325bfeb4827..378698bc64b 100644 --- a/go/mysql/binlog_event_compression.go +++ b/go/mysql/binlog_event_compression.go @@ -19,13 +19,16 @@ package mysql import ( "bytes" "encoding/binary" - "fmt" "io" + "sync" "github.com/klauspost/compress/zstd" - vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" + "vitess.io/vitess/go/stats" + "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/vterrors" + + vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" ) // This file contains code related to handling compression related @@ -41,35 +44,78 @@ const ( payloadUncompressedSizeField ) -// Compression algorithms that are supported (only zstd today -// in MySQL 8.0): -// https://dev.mysql.com/doc/refman/8.0/en/binary-log-transaction-compression.html const ( + // Compression algorithms that are supported (only zstd today + // in MySQL 8.0): + // https://dev.mysql.com/doc/refman/8.0/en/binary-log-transaction-compression.html TransactionPayloadCompressionZstd = 0 TransactionPayloadCompressionNone = 255 + + // Bytes used to store the internal event length as a uint32 at + // the end of the binlog event header. + eventLenBytes = 4 + // Offset from 0 where the eventLenBytes are stored. + binlogEventLenOffset = 9 + // Length of the binlog event header for internal events within + // the transaction payload. + headerLen = binlogEventLenOffset + eventLenBytes + + // At what size should we switch from the in-memory buffer + // decoding to streaming mode which is much slower, but does + // not require everything be done in memory. + zstdInMemoryDecompressorMaxSize = 128 << (10 * 2) // 128MiB ) -var TransactionPayloadCompressionTypes = map[uint64]string{ - TransactionPayloadCompressionZstd: "ZSTD", - TransactionPayloadCompressionNone: "NONE", -} +var ( + TransactionPayloadCompressionTypes = map[uint64]string{ + TransactionPayloadCompressionZstd: "ZSTD", + TransactionPayloadCompressionNone: "NONE", + } -// Create a reader that caches decompressors. This is used for -// smaller events that we want to handle entirely using in-memory -// buffers. -var zstdDecoder, _ = zstd.NewReader(nil, zstd.WithDecoderConcurrency(0)) + // Metrics. + compressedTrxPayloadsInMem = stats.NewCounter("CompressedTransactionPayloadsInMemory", "The number of compressed binlog transaction payloads that were processed in memory") + compressedTrxPayloadsUsingStream = stats.NewCounter("CompressedTransactionPayloadsViaStream", "The number of compressed binlog transaction payloads that were processed using a stream") + + // A concurrent stateless decoder that caches decompressors. This is + // used for smaller payloads that we want to handle entirely using + // in-memory buffers via DecodeAll. + statelessDecoder *zstd.Decoder + + // A pool of stateful decoders for larger payloads that we want to + // stream. The number of large (> zstdInMemoryDecompressorMaxSize) + // payloads should typically be relatively low, but there may be times + // where there are many of them -- and users like vstreamer may have + // N concurrent streams per tablet which could lead to a lot of + // allocations and GC overhead so this pool allows us to handle + // concurrent cases better while still scaling to 0 when there's no + // usage. + statefulDecoderPool sync.Pool +) -// At what size should we switch from the in-memory buffer -// decoding to streaming mode -- which is slower, but does not -// require everything be done in memory. -const zstdInMemoryDecompressorMaxSize = 128 << (10 * 2) // 128MiB +func init() { + var err error + statelessDecoder, err = zstd.NewReader(nil, zstd.WithDecoderConcurrency(0)) + if err != nil { // Should only happen e.g. due to ENOMEM + log.Errorf("Error creating stateless decoder: %v", err) + } + statefulDecoderPool = sync.Pool{ + New: func() any { + d, err := zstd.NewReader(nil, zstd.WithDecoderMaxMemory(zstdInMemoryDecompressorMaxSize)) + if err != nil { // Should only happen e.g. due to ENOMEM + log.Errorf("Error creating stateful decoder: %v", err) + } + return d + }, + } +} type TransactionPayload struct { - Size uint64 - CompressionType uint64 - UncompressedSize uint64 - Payload []byte - Events []BinlogEvent + size uint64 + compressionType uint64 + uncompressedSize uint64 + payload []byte + reader io.Reader + iterator func() (BinlogEvent, error) } // IsTransactionPayload returns true if a compressed transaction @@ -78,8 +124,12 @@ func (ev binlogEvent) IsTransactionPayload() bool { return ev.Type() == eTransactionPayloadEvent } -// TransactionPayload returns the BinlogEvents contained within -// the compressed transaction. +// TransactionPayload processes the payload and provides a GetNextEvent() +// method which should be used in a loop to read BinlogEvents one by one +// that were within the compressed transaction. That function will return +// io.EOF when there are no more events left in the payload. You must +// call Close() when you are done with the TransactionPayload to ensure +// that the underlying reader and related resources are cleaned up. // The following event types are compressed as part of the // transaction payload: // @@ -129,16 +179,18 @@ func (ev binlogEvent) IsTransactionPayload() bool { // We need to extract the compressed transaction payload from the GTID // event, decompress it with zstd, and then process the internal events // (e.g. Query and Row events) that make up the transaction. -func (ev binlogEvent) TransactionPayload(format BinlogFormat) ([]BinlogEvent, error) { +func (ev binlogEvent) TransactionPayload(format BinlogFormat) (*TransactionPayload, error) { tp := &TransactionPayload{} - if err := tp.Decode(ev.Bytes()[format.HeaderLength:]); err != nil { - return nil, vterrors.Wrapf(err, "error decoding transaction payload event") + if err := tp.process(ev.Bytes()[format.HeaderLength:]); err != nil { + return nil, vterrors.Wrap(err, "error decoding transaction payload event") } - return tp.Events, nil + return tp, nil } -// Decode decodes and decompresses the payload. -func (tp *TransactionPayload) Decode(data []byte) error { +// process reads and decompresses the payload, setting up the iterator +// that can then be used in GetNextEvent() to read the binlog events +// from the uncompressed payload one at a time. +func (tp *TransactionPayload) process(data []byte) error { if err := tp.read(data); err != nil { return err } @@ -147,7 +199,8 @@ func (tp *TransactionPayload) Decode(data []byte) error { // read unmarshalls the transaction payload event into the // TransactionPayload struct. The compressed payload itself will still -// need to be decoded -- meaning decompressing it and extracting the +// need to be decoded -- meaning decompressing it and setting up the +// iterator that can then be used by GetNextEvent() to extract the // internal events. func (tp *TransactionPayload) read(data []byte) error { pos := uint64(0) @@ -160,7 +213,7 @@ func (tp *TransactionPayload) read(data []byte) error { pos++ if fieldType == payloadHeaderEndMark { - tp.Payload = data[pos:] + tp.payload = data[pos:] return nil // we're done } @@ -172,17 +225,17 @@ func (tp *TransactionPayload) read(data []byte) error { switch fieldType { case payloadSizeField: - tp.Size, ok = readFixedLenUint64(data[pos : pos+fieldLen]) + tp.size, ok = readFixedLenUint64(data[pos : pos+fieldLen]) if !ok { return vterrors.New(vtrpcpb.Code_INTERNAL, "error reading payload size") } case payloadCompressionTypeField: - tp.CompressionType, ok = readFixedLenUint64(data[pos : pos+fieldLen]) + tp.compressionType, ok = readFixedLenUint64(data[pos : pos+fieldLen]) if !ok { return vterrors.New(vtrpcpb.Code_INTERNAL, "error reading compression type") } case payloadUncompressedSizeField: - tp.UncompressedSize, ok = readFixedLenUint64(data[pos : pos+fieldLen]) + tp.uncompressedSize, ok = readFixedLenUint64(data[pos : pos+fieldLen]) if !ok { return vterrors.New(vtrpcpb.Code_INTERNAL, "error reading uncompressed payload size") } @@ -192,78 +245,126 @@ func (tp *TransactionPayload) read(data []byte) error { } } -// decode decompresses the payload and extracts the internal binlog -// events. +// decode decompresses the payload and assigns the iterator to a +// function that can then be used to retrieve the events from the +// uncompressed transaction one at a time. func (tp *TransactionPayload) decode() error { - if tp.CompressionType != TransactionPayloadCompressionZstd { - return vterrors.New(vtrpcpb.Code_INTERNAL, - fmt.Sprintf("TransactionPayload has unsupported compression type of %d", tp.CompressionType)) + if tp.compressionType != TransactionPayloadCompressionZstd { + return vterrors.Errorf(vtrpcpb.Code_INTERNAL, + "TransactionPayload has unsupported compression type of %d", tp.compressionType) } - decompressedPayload, err := tp.decompress() - decompressedPayloadLen := uint64(len(decompressedPayload)) - if err != nil { - return vterrors.Wrapf(err, "error decompressing transaction payload") + err := tp.decompress() + if err != nil || tp.reader == nil { + return vterrors.Wrap(err, "error decompressing transaction payload") } - pos := uint64(0) - - for { - eventLenPosEnd := pos + BinlogEventLenOffset + 4 - if eventLenPosEnd > decompressedPayloadLen { // No more events in the payload - break + header := make([]byte, headerLen) + tp.iterator = func() (ble BinlogEvent, err error) { + bytesRead, err := io.ReadFull(tp.reader, header) + if err != nil { + if err == io.EOF { + return nil, io.EOF + } + return nil, vterrors.Wrap(err, "error reading event header from uncompressed transaction payload") } - eventLen := uint64(binary.LittleEndian.Uint32(decompressedPayload[pos+BinlogEventLenOffset : eventLenPosEnd])) - if pos+eventLen > decompressedPayloadLen { - return vterrors.New(vtrpcpb.Code_INTERNAL, - fmt.Sprintf("[BUG] event length of %d at pos %d in decompressed transaction payload is beyond the expected payload length of %d", - eventLen, pos, decompressedPayloadLen)) + if bytesRead != headerLen { + return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "[BUG] expected header length of %d but only read %d bytes", + headerLen, bytesRead) } - eventData := decompressedPayload[pos : pos+eventLen] - ble := NewMysql56BinlogEvent(eventData) - tp.Events = append(tp.Events, ble) - - pos += eventLen + eventLen := int64(binary.LittleEndian.Uint32(header[binlogEventLenOffset:headerLen])) + eventData := make([]byte, eventLen) + copy(eventData, header) // The event includes the header + bytesRead, err = io.ReadFull(tp.reader, eventData[headerLen:]) + if err != nil && err != io.EOF { + return nil, vterrors.Wrap(err, "error reading binlog event data from uncompressed transaction payload") + } + if int64(bytesRead+headerLen) != eventLen { + return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "[BUG] expected binlog event length of %d but only read %d bytes", + eventLen, bytesRead) + } + return NewMysql56BinlogEvent(eventData), nil } - return nil } -// Decompress the payload. -func (tp *TransactionPayload) decompress() ([]byte, error) { - if len(tp.Payload) == 0 { - return []byte{}, vterrors.New(vtrpcpb.Code_INVALID_ARGUMENT, "cannot decompress empty payload") +// decompress decompresses the payload. If the payload is larger than +// zstdInMemoryDecompressorMaxSize then we stream the decompression via +// the package's pool of zstd.Decoders, otherwise we use in-memory +// buffers with the package's concurrent statelessDecoder. +// In either case, we setup the reader that can be used within the +// iterator to read the events one at a time from the decompressed +// payload in GetNextEvent(). +func (tp *TransactionPayload) decompress() error { + if len(tp.payload) == 0 { + return vterrors.New(vtrpcpb.Code_INVALID_ARGUMENT, "cannot decompress empty compressed transaction payload") } - var ( - decompressedBytes []byte - err error - ) - - // Switch to slower but less memory intensive stream mode for larger payloads. - if tp.UncompressedSize > zstdInMemoryDecompressorMaxSize { - in := bytes.NewReader(tp.Payload) - streamDecoder, err := zstd.NewReader(in) - if err != nil { - return nil, err - } - defer streamDecoder.Close() - out := io.Writer(&bytes.Buffer{}) - _, err = io.Copy(out, streamDecoder) - if err != nil { - return nil, err + + // Switch to slower but less memory intensive stream mode for + // larger payloads. + if tp.uncompressedSize > zstdInMemoryDecompressorMaxSize { + in := bytes.NewReader(tp.payload) + streamDecoder := statefulDecoderPool.Get().(*zstd.Decoder) + if streamDecoder == nil { + return vterrors.New(vtrpcpb.Code_INTERNAL, "failed to create stateful stream decoder") } - decompressedBytes = out.(*bytes.Buffer).Bytes() - } else { // Process smaller payloads using in-memory buffers. - decompressedBytes, err = zstdDecoder.DecodeAll(tp.Payload, nil) - if err != nil { - return nil, err + if err := streamDecoder.Reset(in); err != nil { + return vterrors.Wrap(err, "error resetting stateful stream decoder") } + compressedTrxPayloadsUsingStream.Add(1) + tp.reader = streamDecoder + return nil } - if uint64(len(decompressedBytes)) != tp.UncompressedSize { - return []byte{}, vterrors.New(vtrpcpb.Code_INVALID_ARGUMENT, - fmt.Sprintf("decompressed size %d does not match expected size %d", len(decompressedBytes), tp.UncompressedSize)) + // Process smaller payloads using only in-memory buffers. + if statelessDecoder == nil { // Should never happen + return vterrors.New(vtrpcpb.Code_INTERNAL, "failed to create stateless decoder") + } + decompressedBytes := make([]byte, 0, tp.uncompressedSize) // Perform a single pre-allocation + decompressedBytes, err := statelessDecoder.DecodeAll(tp.payload, decompressedBytes[:0]) + if err != nil { + return err } + if uint64(len(decompressedBytes)) != tp.uncompressedSize { + return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, + "uncompressed transaction payload size %d does not match expected size %d", len(decompressedBytes), tp.uncompressedSize) + } + compressedTrxPayloadsInMem.Add(1) + tp.reader = bytes.NewReader(decompressedBytes) + return nil +} - return decompressedBytes, nil +// Close should be called in a defer where the TransactionPayload is +// used to ensure that the underlying reader and related resources +// used are cleaned up. +func (tp *TransactionPayload) Close() { + switch reader := tp.reader.(type) { + case *zstd.Decoder: + if err := reader.Reset(nil); err == nil || err == io.EOF { + readersPool.Put(reader) + } + default: + reader = nil + } + tp.iterator = nil } + +// GetNextEvent returns the next binlog event that was contained within +// the compressed transaction payload. It will return io.EOF when there +// are no more events left in the payload. +func (tp *TransactionPayload) GetNextEvent() (BinlogEvent, error) { + if tp == nil || tp.iterator == nil { + return nil, vterrors.New(vtrpcpb.Code_INVALID_ARGUMENT, "TransactionPayload has been closed") + } + return tp.iterator() +} + +// Events returns an iterator over the internal binlog events that +// were contained within the compressed transaction payload/event. +// It returns a single-use iterator. +// TODO(mattlord): implement this when main is on go 1.23. See: +// - https://tip.golang.org/wiki/RangefuncExperiment +// - https://github.com/golang/go/blob/release-branch.go1.23/src/iter/iter.go +//func (tp *TransactionPayload) Events() iter.Seq[BinlogEvent] { +// return tp.iterator +//} diff --git a/go/mysql/binlog_event_filepos.go b/go/mysql/binlog_event_filepos.go index 4edc4bb91ff..8a2976da80d 100644 --- a/go/mysql/binlog_event_filepos.go +++ b/go/mysql/binlog_event_filepos.go @@ -247,8 +247,8 @@ func (ev filePosFakeEvent) Rows(BinlogFormat, *TableMap) (Rows, error) { return Rows{}, nil } -func (ev filePosFakeEvent) TransactionPayload(BinlogFormat) ([]BinlogEvent, error) { - return []BinlogEvent{}, nil +func (ev filePosFakeEvent) TransactionPayload(BinlogFormat) (*TransactionPayload, error) { + return &TransactionPayload{}, nil } func (ev filePosFakeEvent) NextLogFile(BinlogFormat) (string, uint64, error) { diff --git a/go/mysql/binlog_event_mysql56_test.go b/go/mysql/binlog_event_mysql56_test.go index e5fa3545278..f173e27e4af 100644 --- a/go/mysql/binlog_event_mysql56_test.go +++ b/go/mysql/binlog_event_mysql56_test.go @@ -17,8 +17,11 @@ limitations under the License. package mysql import ( + _ "embed" "fmt" + "io" "reflect" + "strings" "testing" "github.com/stretchr/testify/assert" @@ -29,15 +32,16 @@ import ( // Sample event data for MySQL 5.6. var ( - mysql56FormatEvent = NewMysql56BinlogEvent([]byte{0x78, 0x4e, 0x49, 0x55, 0xf, 0x64, 0x0, 0x0, 0x0, 0x74, 0x0, 0x0, 0x0, 0x78, 0x0, 0x0, 0x0, 0x1, 0x0, 0x4, 0x0, 0x35, 0x2e, 0x36, 0x2e, 0x32, 0x34, 0x2d, 0x6c, 0x6f, 0x67, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x78, 0x4e, 0x49, 0x55, 0x13, 0x38, 0xd, 0x0, 0x8, 0x0, 0x12, 0x0, 0x4, 0x4, 0x4, 0x4, 0x12, 0x0, 0x0, 0x5c, 0x0, 0x4, 0x1a, 0x8, 0x0, 0x0, 0x0, 0x8, 0x8, 0x8, 0x2, 0x0, 0x0, 0x0, 0xa, 0xa, 0xa, 0x19, 0x19, 0x0, 0x1, 0x18, 0x4a, 0xf, 0xca}) - mysql56GTIDEvent = NewMysql56BinlogEvent([]byte{0xff, 0x4e, 0x49, 0x55, 0x21, 0x64, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0xf5, 0x2, 0x0, 0x0, 0x0, 0x0, 0x1, 0x43, 0x91, 0x92, 0xbd, 0xf3, 0x7c, 0x11, 0xe4, 0xbb, 0xeb, 0x2, 0x42, 0xac, 0x11, 0x3, 0x5a, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x48, 0x45, 0x82, 0x27}) - // This is the result of: begin; insert into customer values (1, "mlord@planetscale.com"), (2, "sup@planetscale.com"); commit; - mysql56TransactionPayloadEvent = NewMysql56BinlogEvent([]byte{0xc7, 0xe1, 0x4b, 0x64, 0x28, 0x5b, 0xd2, 0xc7, 0x19, 0xdb, 0x00, 0x00, 0x00, 0x3a, 0x50, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x03, 0x03, 0xfc, 0xfe, 0x00, 0x01, 0x01, 0xb8, 0x00, 0x28, 0xb5, 0x2f, 0xfd, 0x00, 0x58, 0x64, 0x05, 0x00, 0xf2, 0x49, 0x23, 0x2a, 0xa0, 0x27, 0x69, 0x0c, 0xff, 0xe8, 0x06, 0xeb, 0xfe, 0xc3, 0xab, 0x8a, 0x7b, 0xc0, 0x36, 0x42, 0x5c, 0x6f, 0x1b, 0x2f, 0xfb, 0x6e, 0xc4, 0x9a, 0xe6, 0x6e, 0x6b, 0xda, 0x08, 0xf1, 0x37, 0x7e, 0xff, 0xb8, 0x6c, 0xbc, 0x27, 0x3c, 0xb7, 0x4f, 0xee, 0x14, 0xff, 0xaf, 0x09, 0x06, 0x69, 0xe3, 0x12, 0x68, 0x4a, 0x6e, 0xc3, 0xe1, 0x28, 0xaf, 0x3f, 0xc8, 0x14, 0x1c, 0xc3, 0x60, 0xce, 0xe3, 0x1e, 0x18, 0x4c, 0x63, 0xa1, 0x35, 0x90, 0x79, 0x04, 0xe8, 0xa9, 0xeb, 0x4a, 0x1b, 0xd7, 0x41, 0x53, 0x72, 0x17, 0xa4, 0x23, 0xa4, 0x47, 0x68, 0x00, 0xa2, 0x37, 0xee, 0xc1, 0xc7, 0x71, 0x30, 0x24, 0x19, 0xfd, 0x78, 0x49, 0x1b, 0x97, 0xd2, 0x94, 0xdc, 0x85, 0xa2, 0x21, 0xc1, 0xb0, 0x63, 0x8d, 0x7b, 0x0f, 0x32, 0x87, 0x07, 0xe2, 0x39, 0xf0, 0x7c, 0x3e, 0x01, 0xfe, 0x13, 0x8f, 0x11, 0xd0, 0x05, 0x9f, 0xbc, 0x18, 0x59, 0x91, 0x36, 0x2e, 0x6d, 0x4a, 0x6e, 0x0b, 0x00, 0x5e, 0x28, 0x10, 0xc0, 0x02, 0x50, 0x77, 0xe0, 0x64, 0x30, 0x02, 0x9e, 0x09, 0x54, 0xec, 0x80, 0x6d, 0x07, 0xa4, 0xc1, 0x7d, 0x60, 0xe4, 0x01, 0x78, 0x01, 0x01, 0x00, 0x00}) + mysql56FormatEvent = NewMysql56BinlogEvent([]byte{0x78, 0x4e, 0x49, 0x55, 0xf, 0x64, 0x0, 0x0, 0x0, 0x74, 0x0, 0x0, 0x0, 0x78, 0x0, 0x0, 0x0, 0x1, 0x0, 0x4, 0x0, 0x35, 0x2e, 0x36, 0x2e, 0x32, 0x34, 0x2d, 0x6c, 0x6f, 0x67, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x78, 0x4e, 0x49, 0x55, 0x13, 0x38, 0xd, 0x0, 0x8, 0x0, 0x12, 0x0, 0x4, 0x4, 0x4, 0x4, 0x12, 0x0, 0x0, 0x5c, 0x0, 0x4, 0x1a, 0x8, 0x0, 0x0, 0x0, 0x8, 0x8, 0x8, 0x2, 0x0, 0x0, 0x0, 0xa, 0xa, 0xa, 0x19, 0x19, 0x0, 0x1, 0x18, 0x4a, 0xf, 0xca}) + mysql56GTIDEvent = NewMysql56BinlogEvent([]byte{0xff, 0x4e, 0x49, 0x55, 0x21, 0x64, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0xf5, 0x2, 0x0, 0x0, 0x0, 0x0, 0x1, 0x43, 0x91, 0x92, 0xbd, 0xf3, 0x7c, 0x11, 0xe4, 0xbb, 0xeb, 0x2, 0x42, 0xac, 0x11, 0x3, 0x5a, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x48, 0x45, 0x82, 0x27}) mysql56QueryEvent = NewMysql56BinlogEvent([]byte{0xff, 0x4e, 0x49, 0x55, 0x2, 0x64, 0x0, 0x0, 0x0, 0x77, 0x0, 0x0, 0x0, 0xdb, 0x3, 0x0, 0x0, 0x0, 0x0, 0x3d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x3, 0x73, 0x74, 0x64, 0x4, 0x8, 0x0, 0x8, 0x0, 0x21, 0x0, 0xc, 0x1, 0x74, 0x65, 0x73, 0x74, 0x0, 0x74, 0x65, 0x73, 0x74, 0x0, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x28, 0x6d, 0x73, 0x67, 0x29, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x20, 0x28, 0x27, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x27, 0x29, 0x92, 0x12, 0x79, 0xc3}) mysql56SemiSyncNoAckQueryEvent = NewMysql56BinlogEvent([]byte{0xef, 0x00, 0xff, 0x4e, 0x49, 0x55, 0x2, 0x64, 0x0, 0x0, 0x0, 0x77, 0x0, 0x0, 0x0, 0xdb, 0x3, 0x0, 0x0, 0x0, 0x0, 0x3d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x3, 0x73, 0x74, 0x64, 0x4, 0x8, 0x0, 0x8, 0x0, 0x21, 0x0, 0xc, 0x1, 0x74, 0x65, 0x73, 0x74, 0x0, 0x74, 0x65, 0x73, 0x74, 0x0, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x28, 0x6d, 0x73, 0x67, 0x29, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x20, 0x28, 0x27, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x27, 0x29, 0x92, 0x12, 0x79, 0xc3}) mysql56SemiSyncAckQueryEvent = NewMysql56BinlogEvent([]byte{0xef, 0x01, 0xff, 0x4e, 0x49, 0x55, 0x2, 0x64, 0x0, 0x0, 0x0, 0x77, 0x0, 0x0, 0x0, 0xdb, 0x3, 0x0, 0x0, 0x0, 0x0, 0x3d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x3, 0x73, 0x74, 0x64, 0x4, 0x8, 0x0, 0x8, 0x0, 0x21, 0x0, 0xc, 0x1, 0x74, 0x65, 0x73, 0x74, 0x0, 0x74, 0x65, 0x73, 0x74, 0x0, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x28, 0x6d, 0x73, 0x67, 0x29, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x20, 0x28, 0x27, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x27, 0x29, 0x92, 0x12, 0x79, 0xc3}) ) +//go:embed large_compressed_trx_payload.bin +var mysql56CompressedLargeTrxPayload []byte + func TestMysql56IsGTID(t *testing.T) { if got, want := mysql56FormatEvent.IsGTID(), false; got != want { t.Errorf("%#v.IsGTID() = %#v, want %#v", mysql56FormatEvent, got, want) @@ -94,46 +98,102 @@ func TestMysql56GTID(t *testing.T) { func TestMysql56DecodeTransactionPayload(t *testing.T) { format := NewMySQL56BinlogFormat() tableMap := &TableMap{} - require.True(t, mysql56TransactionPayloadEvent.IsTransactionPayload()) - - // The generated event is the result of the following SQL being executed in vtgate - // against the commerce keyspace: - // begin; insert into customer values (1, "mlord@planetscale.com"), (2, "sup@planetscale.com"); commit; - // All of these below internal events are encoded in the compressed transaction - // payload event. - want := []string{ - "BEGIN", // Query event - "vt_commerce.customer", // TableMap event - "[1 mlord@planetscale.com]", // WriteRows event - "[2 sup@planetscale.com]", // WriteRows event - "COMMIT", // XID event + + testCases := []struct { + name string + event BinlogEvent + want []string + inMemory bool + }{ + { + name: "Small event done in memory", + event: NewMysql56BinlogEvent([]byte{0xc7, 0xe1, 0x4b, 0x64, 0x28, 0x5b, 0xd2, 0xc7, 0x19, 0xdb, 0x00, 0x00, 0x00, 0x3a, 0x50, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x03, 0x03, 0xfc, 0xfe, 0x00, 0x01, 0x01, 0xb8, 0x00, 0x28, 0xb5, 0x2f, 0xfd, 0x00, 0x58, 0x64, 0x05, 0x00, 0xf2, 0x49, 0x23, 0x2a, 0xa0, 0x27, 0x69, 0x0c, 0xff, 0xe8, 0x06, 0xeb, 0xfe, 0xc3, 0xab, 0x8a, 0x7b, 0xc0, 0x36, 0x42, 0x5c, 0x6f, 0x1b, 0x2f, 0xfb, 0x6e, 0xc4, 0x9a, 0xe6, 0x6e, 0x6b, 0xda, 0x08, 0xf1, 0x37, 0x7e, 0xff, 0xb8, 0x6c, 0xbc, 0x27, 0x3c, 0xb7, 0x4f, 0xee, 0x14, 0xff, 0xaf, 0x09, 0x06, 0x69, 0xe3, 0x12, 0x68, 0x4a, 0x6e, 0xc3, 0xe1, 0x28, 0xaf, 0x3f, 0xc8, 0x14, 0x1c, 0xc3, 0x60, 0xce, 0xe3, 0x1e, 0x18, 0x4c, 0x63, 0xa1, 0x35, 0x90, 0x79, 0x04, 0xe8, 0xa9, 0xeb, 0x4a, 0x1b, 0xd7, 0x41, 0x53, 0x72, 0x17, 0xa4, 0x23, 0xa4, 0x47, 0x68, 0x00, 0xa2, 0x37, 0xee, 0xc1, 0xc7, 0x71, 0x30, 0x24, 0x19, 0xfd, 0x78, 0x49, 0x1b, 0x97, 0xd2, 0x94, 0xdc, 0x85, 0xa2, 0x21, 0xc1, 0xb0, 0x63, 0x8d, 0x7b, 0x0f, 0x32, 0x87, 0x07, 0xe2, 0x39, 0xf0, 0x7c, 0x3e, 0x01, 0xfe, 0x13, 0x8f, 0x11, 0xd0, 0x05, 0x9f, 0xbc, 0x18, 0x59, 0x91, 0x36, 0x2e, 0x6d, 0x4a, 0x6e, 0x0b, 0x00, 0x5e, 0x28, 0x10, 0xc0, 0x02, 0x50, 0x77, 0xe0, 0x64, 0x30, 0x02, 0x9e, 0x09, 0x54, 0xec, 0x80, 0x6d, 0x07, 0xa4, 0xc1, 0x7d, 0x60, 0xe4, 0x01, 0x78, 0x01, 0x01, 0x00, 0x00}), + // The generated event is the result of the following SQL being executed in vtgate + // against the commerce keyspace: + // begin; insert into customer values (1, "mlord@planetscale.com"), (2, "sup@planetscale.com"); commit; + // All of these below internal events are encoded in the compressed transaction + // payload event. + want: []string{ + "BEGIN", // Query event + "vt_commerce.customer", // TableMap event + "[1 mlord@planetscale.com]", // WriteRows event + "[2 sup@planetscale.com]", // WriteRows event + "COMMIT", // XID event + }, + inMemory: true, + }, + { + name: "Large event using streaming", + event: NewMysql56BinlogEvent(mysql56CompressedLargeTrxPayload), + // The generated event is the result of the following SQL being executed against the + // commerce keyspace after having added a LONGTEXT column to the customer + // table (this generates an uncompressed transaction that is over 128MiB): + // insert into customer values (1, "mlord@planetscale.com", repeat("test", 43280000)); + // All of these below internal events are encoded in the compressed transaction + // payload event. + want: []string{ + "BEGIN", // Query event + "vt_commerce.customer", // TableMap event + "[1 mlord@planetscale.com testtesttesttesttesttesttesttest", // WriteRows event + "COMMIT", // XID event + }, + inMemory: false, + }, } - internalEvents, err := mysql56TransactionPayloadEvent.TransactionPayload(format) - require.NoError(t, err) - eventStrs := []string{} - for _, ev := range internalEvents { - switch { - case ev.IsTableMap(): - tableMap, err = ev.TableMap(format) - require.NoError(t, err) - eventStrs = append(eventStrs, fmt.Sprintf("%s.%s", tableMap.Database, tableMap.Name)) - case ev.IsQuery(): - query, err := ev.Query(format) - require.NoError(t, err) - eventStrs = append(eventStrs, query.SQL) - case ev.IsWriteRows(): - rows, err := ev.Rows(format, tableMap) - require.NoError(t, err) - for i := range rows.Rows { - rowStr, err := rows.StringValuesForTests(tableMap, i) + + for _, tc := range testCases { + memDecodingCnt := compressedTrxPayloadsInMem.Get() + streamDecodingCnt := compressedTrxPayloadsUsingStream.Get() + + require.True(t, tc.event.IsTransactionPayload()) + tp, err := tc.event.TransactionPayload(format) + require.NoError(t, err) + defer tp.Close() + eventStrs := []string{} + for { + ev, err := tp.GetNextEvent() + if err != nil { + if err == io.EOF { + break + } + require.Fail(t, fmt.Sprintf("unexpected error: %v", err)) + } + switch { + case ev.IsTableMap(): + tableMap, err = ev.TableMap(format) require.NoError(t, err) - eventStrs = append(eventStrs, fmt.Sprintf("%v", rowStr)) + eventStrs = append(eventStrs, fmt.Sprintf("%s.%s", tableMap.Database, tableMap.Name)) + case ev.IsQuery(): + query, err := ev.Query(format) + require.NoError(t, err) + eventStrs = append(eventStrs, query.SQL) + case ev.IsWriteRows(): + rows, err := ev.Rows(format, tableMap) + require.NoError(t, err) + for i := range rows.Rows { + rowStr, err := rows.StringValuesForTests(tableMap, i) + require.NoError(t, err) + eventStrs = append(eventStrs, fmt.Sprintf("%v", rowStr)) + } + case ev.IsXID(): + eventStrs = append(eventStrs, "COMMIT") + } + } + if tc.inMemory { + require.Equal(t, memDecodingCnt+1, compressedTrxPayloadsInMem.Get()) + require.Equal(t, tc.want, eventStrs) + } else { + require.Equal(t, streamDecodingCnt+1, compressedTrxPayloadsUsingStream.Get()) + require.Len(t, eventStrs, len(tc.want)) + totalSize := 0 + for i, want := range tc.want { + eventStr := eventStrs[i] + totalSize += len(eventStr) + require.True(t, strings.HasPrefix(eventStr, want)) } - case ev.IsXID(): - eventStrs = append(eventStrs, "COMMIT") + require.Greater(t, totalSize, zstdInMemoryDecompressorMaxSize) } } - require.Equal(t, want, eventStrs) } func TestMysql56ParsePosition(t *testing.T) { diff --git a/go/mysql/binlog_event_rbr.go b/go/mysql/binlog_event_rbr.go index 64d17c2b306..d77b7bcb9a0 100644 --- a/go/mysql/binlog_event_rbr.go +++ b/go/mysql/binlog_event_rbr.go @@ -43,6 +43,7 @@ const ( tableMapEnumAndSetDefaultCharset tableMapEnumAndSetColumnCharset tableMapColumnVisibility + tableMapVectorDimensionality ) // This byte in the optional metadata indicates that we should @@ -136,7 +137,7 @@ func metadataLength(typ byte) int { // No data here. return 0 - case binlog.TypeFloat, binlog.TypeDouble, binlog.TypeTimestamp2, binlog.TypeDateTime2, binlog.TypeTime2, binlog.TypeJSON, binlog.TypeTinyBlob, binlog.TypeMediumBlob, binlog.TypeLongBlob, binlog.TypeBlob, binlog.TypeGeometry: + case binlog.TypeFloat, binlog.TypeDouble, binlog.TypeTimestamp2, binlog.TypeDateTime2, binlog.TypeTime2, binlog.TypeJSON, binlog.TypeTinyBlob, binlog.TypeMediumBlob, binlog.TypeLongBlob, binlog.TypeBlob, binlog.TypeGeometry, binlog.TypeVector: // One byte. return 1 @@ -172,7 +173,7 @@ func metadataRead(data []byte, pos int, typ byte) (uint16, int, error) { // No data here. return 0, pos, nil - case binlog.TypeFloat, binlog.TypeDouble, binlog.TypeTimestamp2, binlog.TypeDateTime2, binlog.TypeTime2, binlog.TypeJSON, binlog.TypeTinyBlob, binlog.TypeMediumBlob, binlog.TypeLongBlob, binlog.TypeBlob, binlog.TypeGeometry: + case binlog.TypeFloat, binlog.TypeDouble, binlog.TypeTimestamp2, binlog.TypeDateTime2, binlog.TypeTime2, binlog.TypeJSON, binlog.TypeTinyBlob, binlog.TypeMediumBlob, binlog.TypeLongBlob, binlog.TypeBlob, binlog.TypeGeometry, binlog.TypeVector: // One byte. return uint16(data[pos]), pos + 1, nil @@ -198,7 +199,7 @@ func metadataWrite(data []byte, pos int, typ byte, value uint16) int { // No data here. return pos - case binlog.TypeFloat, binlog.TypeDouble, binlog.TypeTimestamp2, binlog.TypeDateTime2, binlog.TypeTime2, binlog.TypeJSON, binlog.TypeTinyBlob, binlog.TypeMediumBlob, binlog.TypeLongBlob, binlog.TypeBlob, binlog.TypeGeometry: + case binlog.TypeFloat, binlog.TypeDouble, binlog.TypeTimestamp2, binlog.TypeDateTime2, binlog.TypeTime2, binlog.TypeJSON, binlog.TypeTinyBlob, binlog.TypeMediumBlob, binlog.TypeLongBlob, binlog.TypeBlob, binlog.TypeGeometry, binlog.TypeVector: // One byte. data[pos] = byte(value) return pos + 1 diff --git a/go/mysql/capabilities/capability.go b/go/mysql/capabilities/capability.go index 234707538ec..34995081867 100644 --- a/go/mysql/capabilities/capability.go +++ b/go/mysql/capabilities/capability.go @@ -40,7 +40,6 @@ const ( InstantAddDropColumnFlavorCapability // Adding/dropping column in any position/ordinal. InstantChangeColumnDefaultFlavorCapability // InstantExpandEnumCapability // - MySQLJSONFlavorCapability // JSON type supported MySQLUpgradeInServerFlavorCapability // DynamicRedoLogCapacityFlavorCapability // supported in MySQL 8.0.30 and above: https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-30.html DisableRedoLogFlavorCapability // supported in MySQL 8.0.21 and above: https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-21.html @@ -48,6 +47,8 @@ const ( PerformanceSchemaDataLocksTableCapability // supported in MySQL 8.0.1 and above: https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-1.html InstantDDLXtrabackupCapability // Supported in 8.0.32 and above, solving a MySQL-vs-Xtrabackup bug starting 8.0.29 ReplicaTerminologyCapability // Supported in 8.0.26 and above, using SHOW REPLICA STATUS and all variations. + BinaryLogStatus // Supported in 8.2.0 and above, uses SHOW BINARY LOG STATUS + RestrictFKOnNonStandardKey // Supported in 8.4.0 and above, restricts usage of non-standard indexes for foreign keys. ) type CapableOf func(capability FlavorCapability) (bool, error) @@ -87,8 +88,6 @@ func MySQLVersionHasCapability(serverVersion string, capability FlavorCapability } // Capabilities sorted by version. switch capability { - case MySQLJSONFlavorCapability: - return atLeast(5, 7, 0) case InstantDDLFlavorCapability, InstantExpandEnumCapability, InstantAddLastColumnFlavorCapability, @@ -119,6 +118,10 @@ func MySQLVersionHasCapability(serverVersion string, capability FlavorCapability // So be conservative here, and only use the new syntax on newer versions, // so we don't have to have too many different flavors. return atLeast(8, 0, 26) + case BinaryLogStatus: + return atLeast(8, 2, 0) + case RestrictFKOnNonStandardKey: + return atLeast(8, 4, 0) default: return false, nil } diff --git a/go/mysql/capabilities/capability_test.go b/go/mysql/capabilities/capability_test.go index 6e96c3487f5..aeb18bed22e 100644 --- a/go/mysql/capabilities/capability_test.go +++ b/go/mysql/capabilities/capability_test.go @@ -145,7 +145,7 @@ func TestMySQLVersionCapableOf(t *testing.T) { isCapable: false, }, { - version: "5.6.7", + version: "5.7.29", capability: InstantDDLFlavorCapability, isCapable: false, }, @@ -154,16 +154,6 @@ func TestMySQLVersionCapableOf(t *testing.T) { capability: TransactionalGtidExecutedFlavorCapability, isCapable: false, }, - { - version: "5.6.7", - capability: MySQLJSONFlavorCapability, - isCapable: false, - }, - { - version: "5.7.29", - capability: MySQLJSONFlavorCapability, - isCapable: true, - }, { version: "8.0.30", capability: DynamicRedoLogCapacityFlavorCapability, diff --git a/go/mysql/collations/env.go b/go/mysql/collations/env.go index ae5419a5797..77e498562bf 100644 --- a/go/mysql/collations/env.go +++ b/go/mysql/collations/env.go @@ -100,16 +100,11 @@ func fetchCacheEnvironment(version collver) *Environment { // The version string must be in the format that is sent by the server as the version packet // when opening a new MySQL connection func NewEnvironment(serverVersion string) *Environment { - // 5.7 is the oldest version we support today, so use that as - // the default. - // NOTE: this should be changed when we EOL MySQL 5.7 support - var version collver = collverMySQL57 + // 8.0 is the oldest fully supported version, so use that as the default. + // All newer MySQL versions including 9 are so far compatible as well. + var version collver = collverMySQL8 serverVersion = strings.TrimSpace(strings.ToLower(serverVersion)) switch { - case strings.HasSuffix(serverVersion, "-ripple"): - // the ripple binlog server can mask the actual version of mysqld; - // assume we have the highest - version = collverMySQL8 case strings.Contains(serverVersion, "mariadb"): switch { case strings.Contains(serverVersion, "10.0."): @@ -125,8 +120,6 @@ func NewEnvironment(serverVersion string) *Environment { version = collverMySQL56 case strings.HasPrefix(serverVersion, "5.7."): version = collverMySQL57 - case strings.HasPrefix(serverVersion, "8."): - version = collverMySQL8 } return fetchCacheEnvironment(version) } diff --git a/go/mysql/collations/integration/main_test.go b/go/mysql/collations/integration/main_test.go index 23c6f8d2716..665a86ad266 100644 --- a/go/mysql/collations/integration/main_test.go +++ b/go/mysql/collations/integration/main_test.go @@ -47,7 +47,7 @@ func mysqlconn(t *testing.T) *mysql.Conn { if err != nil { t.Fatal(err) } - if !strings.HasPrefix(conn.ServerVersion, "8.") { + if strings.HasPrefix(conn.ServerVersion, "5.7.") { conn.Close() t.Skipf("collation integration tests are only supported in MySQL 8.0+") } diff --git a/go/mysql/conn.go b/go/mysql/conn.go index 925dfbfa8e4..d61549c92ef 100644 --- a/go/mysql/conn.go +++ b/go/mysql/conn.go @@ -787,15 +787,15 @@ func (c *Conn) writeOKPacketWithHeader(packetOk *PacketOK, headerType byte) erro // assuming CapabilityClientProtocol41 length += 4 // status_flags + warnings + hasSessionTrack := c.Capabilities&CapabilityClientSessionTrack == CapabilityClientSessionTrack + hasGtidData := hasSessionTrack && packetOk.statusFlags&ServerSessionStateChanged == ServerSessionStateChanged + var gtidData []byte - if c.Capabilities&CapabilityClientSessionTrack == CapabilityClientSessionTrack { + + if hasSessionTrack { length += lenEncStringSize(packetOk.info) // info - if packetOk.statusFlags&ServerSessionStateChanged == ServerSessionStateChanged { - gtidData = getLenEncString([]byte(packetOk.sessionStateData)) - gtidData = append([]byte{0x00}, gtidData...) - gtidData = getLenEncString(gtidData) - gtidData = append([]byte{0x03}, gtidData...) - gtidData = append(getLenEncInt(uint64(len(gtidData))), gtidData...) + if hasGtidData { + gtidData = encGtidData(packetOk.sessionStateData) length += len(gtidData) } } else { @@ -809,10 +809,10 @@ func (c *Conn) writeOKPacketWithHeader(packetOk *PacketOK, headerType byte) erro data.writeLenEncInt(packetOk.lastInsertID) data.writeUint16(packetOk.statusFlags) data.writeUint16(packetOk.warnings) - if c.Capabilities&CapabilityClientSessionTrack == CapabilityClientSessionTrack { + if hasSessionTrack { data.writeLenEncString(packetOk.info) - if packetOk.statusFlags&ServerSessionStateChanged == ServerSessionStateChanged { - data.writeEOFString(string(gtidData)) + if hasGtidData { + data.writeEOFBytes(gtidData) } } else { data.writeEOFString(packetOk.info) @@ -820,39 +820,6 @@ func (c *Conn) writeOKPacketWithHeader(packetOk *PacketOK, headerType byte) erro return c.writeEphemeralPacket() } -func getLenEncString(value []byte) []byte { - data := getLenEncInt(uint64(len(value))) - return append(data, value...) -} - -func getLenEncInt(i uint64) []byte { - var data []byte - switch { - case i < 251: - data = append(data, byte(i)) - case i < 1<<16: - data = append(data, 0xfc) - data = append(data, byte(i)) - data = append(data, byte(i>>8)) - case i < 1<<24: - data = append(data, 0xfd) - data = append(data, byte(i)) - data = append(data, byte(i>>8)) - data = append(data, byte(i>>16)) - default: - data = append(data, 0xfe) - data = append(data, byte(i)) - data = append(data, byte(i>>8)) - data = append(data, byte(i>>16)) - data = append(data, byte(i>>24)) - data = append(data, byte(i>>32)) - data = append(data, byte(i>>40)) - data = append(data, byte(i>>48)) - data = append(data, byte(i>>56)) - } - return data -} - func (c *Conn) WriteErrorAndLog(format string, args ...interface{}) bool { return c.writeErrorAndLog(sqlerror.ERUnknownComError, sqlerror.SSNetError, format, args...) } @@ -1290,7 +1257,6 @@ func (c *Conn) handleComPrepare(handler Handler, data []byte) (kontinue bool) { c.PrepareData[c.StatementID] = prepare fld, err := handler.ComPrepare(c, queries[0], bindVars) - if err != nil { return c.writeErrorPacketFromErrorAndLog(err) } diff --git a/go/mysql/encoding.go b/go/mysql/encoding.go index c79580acb39..20e09f32fe8 100644 --- a/go/mysql/encoding.go +++ b/go/mysql/encoding.go @@ -47,31 +47,37 @@ func lenEncIntSize(i uint64) int { } func writeLenEncInt(data []byte, pos int, i uint64) int { + // reslice at pos to avoid doing arithmetic below + data = data[pos:] + switch { case i < 251: - data[pos] = byte(i) + data[0] = byte(i) return pos + 1 case i < 1<<16: - data[pos] = 0xfc - data[pos+1] = byte(i) - data[pos+2] = byte(i >> 8) + _ = data[2] // early bounds check + data[0] = 0xfc + data[1] = byte(i) + data[2] = byte(i >> 8) return pos + 3 case i < 1<<24: - data[pos] = 0xfd - data[pos+1] = byte(i) - data[pos+2] = byte(i >> 8) - data[pos+3] = byte(i >> 16) + _ = data[3] // early bounds check + data[0] = 0xfd + data[1] = byte(i) + data[2] = byte(i >> 8) + data[3] = byte(i >> 16) return pos + 4 default: - data[pos] = 0xfe - data[pos+1] = byte(i) - data[pos+2] = byte(i >> 8) - data[pos+3] = byte(i >> 16) - data[pos+4] = byte(i >> 24) - data[pos+5] = byte(i >> 32) - data[pos+6] = byte(i >> 40) - data[pos+7] = byte(i >> 48) - data[pos+8] = byte(i >> 56) + _ = data[8] // early bounds check + data[0] = 0xfe + data[1] = byte(i) + data[2] = byte(i >> 8) + data[3] = byte(i >> 16) + data[4] = byte(i >> 24) + data[5] = byte(i >> 32) + data[6] = byte(i >> 40) + data[7] = byte(i >> 48) + data[8] = byte(i >> 56) return pos + 9 } } @@ -101,28 +107,17 @@ func writeByte(data []byte, pos int, value byte) int { } func writeUint16(data []byte, pos int, value uint16) int { - data[pos] = byte(value) - data[pos+1] = byte(value >> 8) + binary.LittleEndian.PutUint16(data[pos:], value) return pos + 2 } func writeUint32(data []byte, pos int, value uint32) int { - data[pos] = byte(value) - data[pos+1] = byte(value >> 8) - data[pos+2] = byte(value >> 16) - data[pos+3] = byte(value >> 24) + binary.LittleEndian.PutUint32(data[pos:], value) return pos + 4 } func writeUint64(data []byte, pos int, value uint64) int { - data[pos] = byte(value) - data[pos+1] = byte(value >> 8) - data[pos+2] = byte(value >> 16) - data[pos+3] = byte(value >> 24) - data[pos+4] = byte(value >> 32) - data[pos+5] = byte(value >> 40) - data[pos+6] = byte(value >> 48) - data[pos+7] = byte(value >> 56) + binary.LittleEndian.PutUint64(data[pos:], value) return pos + 8 } @@ -137,10 +132,9 @@ func writeLenEncString(data []byte, pos int, value string) int { } func writeZeroes(data []byte, pos int, len int) int { - for i := 0; i < len; i++ { - data[pos+i] = 0 - } - return pos + len + end := pos + len + clear(data[pos:end]) + return end } // @@ -228,6 +222,7 @@ func readFixedLenUint64(data []byte) (uint64, bool) { case 3: // 2 bytes return uint64(binary.LittleEndian.Uint16(data[1:])), true case 4: // 3 bytes + _ = data[3] // early bounds check return uint64(data[1]) | uint64(data[2])<<8 | uint64(data[3])<<16, true @@ -242,37 +237,42 @@ func readLenEncInt(data []byte, pos int) (uint64, int, bool) { if pos >= len(data) { return 0, 0, false } - switch data[pos] { + + // reslice to avoid arithmetic below + data = data[pos:] + + switch data[0] { case 0xfc: // Encoded in the next 2 bytes. - if pos+2 >= len(data) { + if 2 >= len(data) { return 0, 0, false } - return uint64(data[pos+1]) | - uint64(data[pos+2])<<8, pos + 3, true + return uint64(data[1]) | + uint64(data[2])<<8, pos + 3, true case 0xfd: // Encoded in the next 3 bytes. - if pos+3 >= len(data) { + if 3 >= len(data) { return 0, 0, false } - return uint64(data[pos+1]) | - uint64(data[pos+2])<<8 | - uint64(data[pos+3])<<16, pos + 4, true + return uint64(data[1]) | + uint64(data[2])<<8 | + uint64(data[3])<<16, pos + 4, true case 0xfe: // Encoded in the next 8 bytes. - if pos+8 >= len(data) { + if 8 >= len(data) { return 0, 0, false } - return uint64(data[pos+1]) | - uint64(data[pos+2])<<8 | - uint64(data[pos+3])<<16 | - uint64(data[pos+4])<<24 | - uint64(data[pos+5])<<32 | - uint64(data[pos+6])<<40 | - uint64(data[pos+7])<<48 | - uint64(data[pos+8])<<56, pos + 9, true + return uint64(data[1]) | + uint64(data[2])<<8 | + uint64(data[3])<<16 | + uint64(data[4])<<24 | + uint64(data[5])<<32 | + uint64(data[6])<<40 | + uint64(data[7])<<48 | + uint64(data[8])<<56, pos + 9, true + default: + return uint64(data[0]), pos + 1, true } - return uint64(data[pos]), pos + 1, true } func readLenEncString(data []byte, pos int) (string, int, bool) { @@ -325,6 +325,53 @@ func readLenEncStringAsBytesCopy(data []byte, pos int) ([]byte, int, bool) { return result, pos + s, true } +// > encGtidData("xxx") +// +// [07 03 05 00 03 78 78 78] +// | | | | | |------| +// | | | | | ^-------- "xxx" +// | | | | ^------------ length of rest of bytes, 3 +// | | | ^--------------- fixed 0x00 +// | | ^------------------ length of rest of bytes, 5 +// | ^--------------------- fixed 0x03 (SESSION_TRACK_GTIDS) +// ^------------------------ length of rest of bytes, 7 +// +// This is ultimately lenencoded strings of length encoded strings, or: +// > lenenc(0x03 + lenenc(0x00 + lenenc(data))) +func encGtidData(data string) []byte { + const SessionTrackGtids = 0x03 + + // calculate total size up front to do 1 allocation + // encoded layout is: + // lenenc(0x03 + lenenc(0x00 + lenenc(data))) + dataSize := uint64(len(data)) + dataLenEncSize := uint64(lenEncIntSize(dataSize)) + + wrapSize := uint64(dataSize + dataLenEncSize + 1) + wrapLenEncSize := uint64(lenEncIntSize(wrapSize)) + + totalSize := uint64(wrapSize + wrapLenEncSize + 1) + totalLenEncSize := uint64(lenEncIntSize(totalSize)) + + gtidData := make([]byte, int(totalSize+totalLenEncSize)) + + pos := 0 + pos = writeLenEncInt(gtidData, pos, totalSize) + + gtidData[pos] = SessionTrackGtids + pos++ + + pos = writeLenEncInt(gtidData, pos, wrapSize) + + gtidData[pos] = 0x00 + pos++ + + pos = writeLenEncInt(gtidData, pos, dataSize) + writeEOFString(gtidData, pos, data) + + return gtidData +} + type coder struct { data []byte pos int @@ -390,3 +437,7 @@ func (d *coder) writeLenEncString(value string) { func (d *coder) writeEOFString(value string) { d.pos += copy(d.data[d.pos:], value) } + +func (d *coder) writeEOFBytes(value []byte) { + d.pos += copy(d.data[d.pos:], value) +} diff --git a/go/mysql/encoding_test.go b/go/mysql/encoding_test.go index c0081a6455b..c2b7013e2cb 100644 --- a/go/mysql/encoding_test.go +++ b/go/mysql/encoding_test.go @@ -18,6 +18,7 @@ package mysql import ( "bytes" + "strings" "testing" "github.com/stretchr/testify/assert" @@ -72,7 +73,6 @@ func TestEncLenInt(t *testing.T) { // Check failed decoding. _, _, ok = readLenEncInt(test.encoded[:len(test.encoded)-1], 0) assert.False(t, ok, "readLenEncInt returned ok=true for shorter value %x", test.value) - } } @@ -96,7 +96,6 @@ func TestEncUint16(t *testing.T) { _, _, ok = readUint16(data, 9) assert.False(t, ok, "readUint16 returned ok=true for shorter value") - } func TestEncBytes(t *testing.T) { @@ -122,7 +121,6 @@ func TestEncBytes(t *testing.T) { _, _, ok = readBytes(data, 9, 2) assert.False(t, ok, "readBytes returned ok=true for shorter value") - } func TestEncUint32(t *testing.T) { @@ -145,7 +143,6 @@ func TestEncUint32(t *testing.T) { _, _, ok = readUint32(data, 7) assert.False(t, ok, "readUint32 returned ok=true for shorter value") - } func TestEncUint64(t *testing.T) { @@ -169,7 +166,6 @@ func TestEncUint64(t *testing.T) { _, _, ok = readUint64(data, 7) assert.False(t, ok, "readUint64 returned ok=true for shorter value") - } func TestEncString(t *testing.T) { @@ -317,3 +313,169 @@ func TestEncString(t *testing.T) { } } } + +func TestWriteZeroes(t *testing.T) { + buf := make([]byte, 32) + resetBuf := func() { + t.Helper() + for i := range len(buf) { + buf[i] = 'f' + } + } + + allMatch := func(b []byte, c byte) bool { + for i := range b { + if b[i] != c { + return false + } + } + return true + } + + t.Run("0-offset", func(t *testing.T) { + for _, size := range []int{4, 10, 23, 24, 25, 26, 27} { + resetBuf() + pos := writeZeroes(buf, 0, size) + assert.Equal(t, size, pos, "expected to advance pos to %d, got %d", size, pos) + assert.True(t, allMatch(buf[:pos], 0), "buffer should be zeroes, %v", buf[:pos]) + assert.True(t, allMatch(buf[pos:], 'f'), "buffer should be dirty, %v", buf[pos:]) + } + }) + + t.Run("3-offset", func(t *testing.T) { + offset := 3 + for _, size := range []int{4, 10, 23, 24, 25, 26, 27} { + resetBuf() + pos := writeZeroes(buf, offset, size) + assert.Equal(t, offset+size, pos, "expected to advance pos to %d, got %d", offset+size, pos) + assert.True(t, allMatch(buf[:offset], 'f'), "buffer should be dirty, %v", buf[offset:pos]) + assert.True(t, allMatch(buf[offset:pos], 0), "buffer should be zeroes, %v", buf[:pos]) + assert.True(t, allMatch(buf[pos:], 'f'), "buffer should be dirty, %v", buf[pos:]) + } + }) +} + +func TestEncGtidData(t *testing.T) { + tests := []struct { + data string + header []byte + }{ + {"", []byte{0x04, 0x03, 0x02, 0x00, 0x00}}, + {"xxx", []byte{0x07, 0x03, 0x05, 0x00, 0x03}}, + {strings.Repeat("x", 256), []byte{ + /* 264 */ 0xfc, 0x08, 0x01, + /* constant */ 0x03, + /* 260 */ 0xfc, 0x04, 0x01, + /* constant */ 0x00, + /* 256 */ 0xfc, 0x00, 0x01, + }}, + } + for _, test := range tests { + got := encGtidData(test.data) + assert.Equal(t, append(test.header, test.data...), got) + } +} + +func BenchmarkEncWriteInt(b *testing.B) { + buf := make([]byte, 16) + + b.Run("16-bit", func(b *testing.B) { + value := uint16(0x0100) + for range b.N { + _ = writeUint16(buf, 0, value) + } + }) + + b.Run("16-bit-lenencoded", func(b *testing.B) { + value := uint64(0x0100) + for range b.N { + _ = writeLenEncInt(buf, 0, value) + } + }) + + b.Run("24-bit-lenencoded", func(b *testing.B) { + value := uint64(0xabcdef) + for range b.N { + _ = writeLenEncInt(buf, 0, value) + } + }) + + b.Run("32-bit", func(b *testing.B) { + value := uint32(0xabcdef) + for range b.N { + _ = writeUint32(buf, 0, value) + } + }) + + b.Run("64-bit", func(b *testing.B) { + value := uint64(0xa0a1a2a3a4a5a6a7) + for range b.N { + _ = writeUint64(buf, 0, value) + } + }) + + b.Run("64-bit-lenencoded", func(b *testing.B) { + value := uint64(0xa0a1a2a3a4a5a6a7) + for range b.N { + _ = writeLenEncInt(buf, 0, value) + } + }) +} + +func BenchmarkEncWriteZeroes(b *testing.B) { + buf := make([]byte, 128) + + b.Run("4-bytes", func(b *testing.B) { + for range b.N { + _ = writeZeroes(buf, 16, 4) + } + }) + + b.Run("10-bytes", func(b *testing.B) { + for range b.N { + _ = writeZeroes(buf, 16, 10) + } + }) + + b.Run("23-bytes", func(b *testing.B) { + for range b.N { + _ = writeZeroes(buf, 16, 23) + } + }) + + b.Run("55-bytes", func(b *testing.B) { + for range b.N { + _ = writeZeroes(buf, 16, 55) + } + }) +} + +func BenchmarkEncReadInt(b *testing.B) { + b.Run("16-bit", func(b *testing.B) { + data := []byte{0xfc, 0xfb, 0x00} + for range b.N { + _, _, _ = readLenEncInt(data, 0) + } + }) + + b.Run("24-bit", func(b *testing.B) { + data := []byte{0xfd, 0x00, 0x00, 0x01} + for range b.N { + _, _, _ = readLenEncInt(data, 0) + } + }) + + b.Run("64-bit", func(b *testing.B) { + data := []byte{0xfe, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0} + for range b.N { + _, _, _ = readLenEncInt(data, 0) + } + }) +} + +func BenchmarkEncGtidData(b *testing.B) { + b.ReportAllocs() + for range b.N { + _ = encGtidData("xxx") + } +} diff --git a/go/mysql/flavor.go b/go/mysql/flavor.go index f732b1ccb88..a0f9e8cc4b1 100644 --- a/go/mysql/flavor.go +++ b/go/mysql/flavor.go @@ -158,7 +158,7 @@ type flavor interface { // flavorFuncs maps flavor names to their implementation. // Flavors need to register only if they support being specified in the // connection parameters. -var flavorFuncs = make(map[string]func() flavor) +var flavorFuncs = make(map[string]func(serverVersion string) flavor) // GetFlavor fills in c.Flavor. If the params specify the flavor, // that is used. Otherwise, we auto-detect. @@ -172,11 +172,11 @@ var flavorFuncs = make(map[string]func() flavor) // Note on such servers, 'select version()' would return 10.0.21-MariaDB-... // as well (not matching what c.ServerVersion is, but matching after we remove // the prefix). -func GetFlavor(serverVersion string, flavorFunc func() flavor) (f flavor, capableOf capabilities.CapableOf, canonicalVersion string) { +func GetFlavor(serverVersion string, flavorFunc func(serverVersion string) flavor) (f flavor, capableOf capabilities.CapableOf, canonicalVersion string) { canonicalVersion = serverVersion switch { case flavorFunc != nil: - f = flavorFunc() + f = flavorFunc(serverVersion) case strings.HasPrefix(serverVersion, mariaDBReplicationHackPrefix): canonicalVersion = serverVersion[len(mariaDBReplicationHackPrefix):] f = mariadbFlavor101{mariadbFlavor{serverVersion: canonicalVersion}} @@ -282,7 +282,7 @@ func (c *Conn) GetServerUUID() (string, error) { // PrimaryFilePosition returns the current primary's file based replication position. func (c *Conn) PrimaryFilePosition() (replication.Position, error) { - filePosFlavor := filePosFlavor{} + filePosFlavor := filePosFlavor{serverVersion: c.ServerVersion} gtidSet, err := filePosFlavor.primaryGTIDSet(c) if err != nil { return replication.Position{}, err @@ -440,7 +440,7 @@ func (c *Conn) CatchupToGTIDCommands(params *ConnParams, pos replication.Positio // the context expires for the file position flavor. It returns an error if // we did not succeed. func (c *Conn) WaitUntilFilePosition(ctx context.Context, pos replication.Position) error { - filePosFlavor := filePosFlavor{} + filePosFlavor := filePosFlavor{serverVersion: c.ServerVersion} return filePosFlavor.waitUntilPosition(ctx, c, pos) } diff --git a/go/mysql/flavor_filepos.go b/go/mysql/flavor_filepos.go index 5e766e81912..565aa2a807d 100644 --- a/go/mysql/flavor_filepos.go +++ b/go/mysql/flavor_filepos.go @@ -32,19 +32,25 @@ import ( ) type filePosFlavor struct { - format BinlogFormat - file string - savedEvent BinlogEvent + format BinlogFormat + file string + savedEvent BinlogEvent + serverVersion string } // newFilePosFlavor creates a new filePos flavor. -func newFilePosFlavor() flavor { - return &filePosFlavor{} +func newFilePosFlavor(serverVersion string) flavor { + return &filePosFlavor{serverVersion: serverVersion} } // primaryGTIDSet is part of the Flavor interface. func (flv *filePosFlavor) primaryGTIDSet(c *Conn) (replication.GTIDSet, error) { - qr, err := c.ExecuteFetch("SHOW MASTER STATUS", 100, true /* wantfields */) + query := "SHOW MASTER STATUS" + if ok, err := c.SupportsCapability(capabilities.BinaryLogStatus); err == nil && ok { + query = "SHOW BINARY LOG STATUS" + } + + qr, err := c.ExecuteFetch(query, 100, true /* wantfields */) if err != nil { return nil, err } @@ -291,14 +297,21 @@ func (flv *filePosFlavor) waitUntilPosition(ctx context.Context, c *Conn, pos re if !ok { return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "position is not filePos compatible: %#v", pos.GTIDSet) } + queryPos := "SELECT MASTER_POS_WAIT('%s', %d)" + queryPosSub := "SELECT MASTER_POS_WAIT('%s', %d, %.6f)" + + if ok, err := c.SupportsCapability(capabilities.ReplicaTerminologyCapability); err == nil && ok { + queryPos = "SELECT SOURCE_POS_WAIT('%s', %d)" + queryPosSub = "SELECT SOURCE_POS_WAIT('%s', %d, %.6f)" + } - query := fmt.Sprintf("SELECT MASTER_POS_WAIT('%s', %d)", filePosPos.File, filePosPos.Pos) + query := fmt.Sprintf(queryPos, filePosPos.File, filePosPos.Pos) if deadline, ok := ctx.Deadline(); ok { timeout := time.Until(deadline) if timeout <= 0 { return vterrors.Errorf(vtrpcpb.Code_DEADLINE_EXCEEDED, "timed out waiting for position %v", pos) } - query = fmt.Sprintf("SELECT MASTER_POS_WAIT('%s', %d, %.6f)", filePosPos.File, filePosPos.Pos, timeout.Seconds()) + query = fmt.Sprintf(queryPosSub, filePosPos.File, filePosPos.Pos, timeout.Seconds()) } result, err := c.ExecuteFetch(query, 1, false) @@ -354,8 +367,10 @@ func (*filePosFlavor) baseShowTablesWithSizes() string { } // supportsCapability is part of the Flavor interface. -func (*filePosFlavor) supportsCapability(capability capabilities.FlavorCapability) (bool, error) { +func (f *filePosFlavor) supportsCapability(capability capabilities.FlavorCapability) (bool, error) { switch capability { + case capabilities.BinaryLogStatus: + return capabilities.ServerVersionAtLeast(f.serverVersion, 8, 2, 0) default: return false, nil } diff --git a/go/mysql/flavor_mysqlgr.go b/go/mysql/flavor_mysqlgr.go index df3dc060742..98516e9cc9f 100644 --- a/go/mysql/flavor_mysqlgr.go +++ b/go/mysql/flavor_mysqlgr.go @@ -42,8 +42,8 @@ type mysqlGRFlavor struct { } // newMysqlGRFlavor creates a new mysqlGR flavor. -func newMysqlGRFlavor() flavor { - return &mysqlGRFlavor{} +func newMysqlGRFlavor(serverVersion string) flavor { + return &mysqlGRFlavor{mysqlFlavor{serverVersion: serverVersion}} } // startReplicationCommand returns the command to start the replication. diff --git a/go/mysql/flavor_mysqlgr_test.go b/go/mysql/flavor_mysqlgr_test.go index 348aefca934..33c6567b888 100644 --- a/go/mysql/flavor_mysqlgr_test.go +++ b/go/mysql/flavor_mysqlgr_test.go @@ -84,7 +84,7 @@ func TestMysqlGRSupportCapability(t *testing.T) { isCapable: false, }, { - version: "5.6.7", + version: "5.7.29", capability: capabilities.InstantDDLFlavorCapability, isCapable: false, }, @@ -93,16 +93,6 @@ func TestMysqlGRSupportCapability(t *testing.T) { capability: capabilities.TransactionalGtidExecutedFlavorCapability, isCapable: false, }, - { - version: "5.6.7", - capability: capabilities.MySQLJSONFlavorCapability, - isCapable: false, - }, - { - version: "5.7.29", - capability: capabilities.MySQLJSONFlavorCapability, - isCapable: true, - }, { version: "8.0.30", capability: capabilities.DynamicRedoLogCapacityFlavorCapability, diff --git a/go/mysql/flavor_test.go b/go/mysql/flavor_test.go index 172ffa67eb2..3d584b8293b 100644 --- a/go/mysql/flavor_test.go +++ b/go/mysql/flavor_test.go @@ -53,11 +53,6 @@ func TestServerVersionCapableOf(t *testing.T) { capability: capabilities.TransactionalGtidExecutedFlavorCapability, isCapable: false, }, - { - version: "5.7.29", - capability: capabilities.MySQLJSONFlavorCapability, - isCapable: true, - }, { version: "8.0.30", capability: capabilities.DynamicRedoLogCapacityFlavorCapability, diff --git a/go/mysql/large_compressed_trx_payload.bin b/go/mysql/large_compressed_trx_payload.bin new file mode 100644 index 00000000000..8d5d10a0d50 Binary files /dev/null and b/go/mysql/large_compressed_trx_payload.bin differ diff --git a/go/mysql/query.go b/go/mysql/query.go index 22299e5cc80..10f36a09b1d 100644 --- a/go/mysql/query.go +++ b/go/mysql/query.go @@ -685,7 +685,7 @@ func (c *Conn) parseStmtArgs(data []byte, typ querypb.Type, pos int) (sqltypes.V case sqltypes.Uint16: val, pos, ok := readUint16(data, pos) return sqltypes.NewUint64(uint64(val)), pos, ok - case sqltypes.Int16, sqltypes.Year: + case sqltypes.Int16: val, pos, ok := readUint16(data, pos) return sqltypes.NewInt64(int64(int16(val))), pos, ok case sqltypes.Uint24, sqltypes.Uint32: @@ -890,8 +890,8 @@ func (c *Conn) parseStmtArgs(data []byte, typ querypb.Type, pos int) (sqltypes.V default: return sqltypes.NULL, 0, false } - case sqltypes.Decimal, sqltypes.Text, sqltypes.Blob, sqltypes.VarChar, sqltypes.VarBinary, sqltypes.Char, - sqltypes.Bit, sqltypes.Enum, sqltypes.Set, sqltypes.Geometry, sqltypes.Binary, sqltypes.TypeJSON: + case sqltypes.Decimal, sqltypes.Text, sqltypes.Blob, sqltypes.VarChar, sqltypes.VarBinary, sqltypes.Year, sqltypes.Char, + sqltypes.Bit, sqltypes.Enum, sqltypes.Set, sqltypes.Geometry, sqltypes.Binary, sqltypes.TypeJSON, sqltypes.Vector: val, pos, ok := readLenEncStringAsBytesCopy(data, pos) return sqltypes.MakeTrusted(sqltypes.VarBinary, val), pos, ok default: diff --git a/go/mysql/query_test.go b/go/mysql/query_test.go index 0e1f48c1804..6892508ac0c 100644 --- a/go/mysql/query_test.go +++ b/go/mysql/query_test.go @@ -315,10 +315,7 @@ func TestComStmtExecuteUpdStmt(t *testing.T) { assert.EqualValues(t, querypb.Type_DATETIME, prepData.ParamsType[15], "got: %s", querypb.Type(prepData.ParamsType[15])) assert.EqualValues(t, querypb.Type_TIMESTAMP, prepData.ParamsType[16], "got: %s", querypb.Type(prepData.ParamsType[16])) assert.EqualValues(t, querypb.Type_TIME, prepData.ParamsType[17], "got: %s", querypb.Type(prepData.ParamsType[17])) - - // this is year but in binary it is changed to varbinary - assert.EqualValues(t, querypb.Type_VARBINARY, prepData.ParamsType[18], "got: %s", querypb.Type(prepData.ParamsType[18])) - + assert.EqualValues(t, querypb.Type_YEAR, prepData.ParamsType[18], "got: %s", querypb.Type(prepData.ParamsType[18])) assert.EqualValues(t, querypb.Type_CHAR, prepData.ParamsType[19], "got: %s", querypb.Type(prepData.ParamsType[19])) assert.EqualValues(t, querypb.Type_CHAR, prepData.ParamsType[20], "got: %s", querypb.Type(prepData.ParamsType[20])) assert.EqualValues(t, querypb.Type_TEXT, prepData.ParamsType[21], "got: %s", querypb.Type(prepData.ParamsType[21])) @@ -463,6 +460,7 @@ func TestQueries(t *testing.T) { // Skip TUPLE, not possible in Result. {Name: "Type_GEOMETRY ", Type: querypb.Type_GEOMETRY, Charset: collations.CollationBinaryID, Flags: uint32(querypb.MySqlFlag_BINARY_FLAG | querypb.MySqlFlag_BLOB_FLAG)}, {Name: "Type_JSON ", Type: querypb.Type_JSON, Charset: collations.CollationUtf8mb4ID}, + {Name: "Type_VECTOR ", Type: querypb.Type_VECTOR, Charset: collations.CollationBinaryID}, }, Rows: [][]sqltypes.Value{ { @@ -495,6 +493,7 @@ func TestQueries(t *testing.T) { sqltypes.MakeTrusted(querypb.Type_SET, []byte("Type_SET")), sqltypes.MakeTrusted(querypb.Type_GEOMETRY, []byte("Type_GEOMETRY")), sqltypes.MakeTrusted(querypb.Type_JSON, []byte("Type_JSON")), + sqltypes.MakeTrusted(querypb.Type_VECTOR, []byte("Type_VECTOR")), }, { sqltypes.NULL, @@ -526,6 +525,7 @@ func TestQueries(t *testing.T) { sqltypes.NULL, sqltypes.NULL, sqltypes.NULL, + sqltypes.NULL, }, }, }) diff --git a/go/mysql/sqlerror/constants.go b/go/mysql/sqlerror/constants.go index a247ca15aa4..ec5afa5e9c3 100644 --- a/go/mysql/sqlerror/constants.go +++ b/go/mysql/sqlerror/constants.go @@ -125,6 +125,8 @@ const ( ERDupIndex = ErrorCode(1831) ERInnodbReadOnly = ErrorCode(1874) + ERVectorConversion = ErrorCode(6138) + // already exists ERDbCreateExists = ErrorCode(1007) ERTableExists = ErrorCode(1050) diff --git a/go/mysql/sqlerror/sql_error.go b/go/mysql/sqlerror/sql_error.go index 935fd77a12f..eaa49c2c537 100644 --- a/go/mysql/sqlerror/sql_error.go +++ b/go/mysql/sqlerror/sql_error.go @@ -245,6 +245,7 @@ var stateToMysqlCode = map[vterrors.State]mysqlCode{ vterrors.KillDeniedError: {num: ERKillDenied, state: SSUnknownSQLState}, vterrors.BadNullError: {num: ERBadNullError, state: SSConstraintViolation}, vterrors.InvalidGroupFuncUse: {num: ERInvalidGroupFuncUse, state: SSUnknownSQLState}, + vterrors.VectorConversion: {num: ERVectorConversion, state: SSUnknownSQLState}, } func getStateToMySQLState(state vterrors.State) mysqlCode { diff --git a/go/sqltypes/type.go b/go/sqltypes/type.go index 4090dd0107a..8be10986747 100644 --- a/go/sqltypes/type.go +++ b/go/sqltypes/type.go @@ -186,6 +186,7 @@ const ( HexVal = querypb.Type_HEXVAL Tuple = querypb.Type_TUPLE BitNum = querypb.Type_BITNUM + Vector = querypb.Type_VECTOR ) // bit-shift the mysql flags by two byte so we @@ -219,6 +220,7 @@ var mysqlToType = map[byte]querypb.Type{ 17: Timestamp, 18: Datetime, 19: Time, + 242: Vector, 245: TypeJSON, 246: Decimal, 247: Enum, @@ -276,10 +278,6 @@ func modifyType(typ querypb.Type, flags int64) querypb.Type { if flags&mysqlSet != 0 { return Set } - case Year: - if flags&mysqlBinary != 0 { - return VarBinary - } } return typ } @@ -335,6 +333,7 @@ var typeToMySQL = map[querypb.Type]struct { Datetime: {typ: 12, flags: mysqlBinary}, Year: {typ: 13, flags: mysqlUnsigned}, Bit: {typ: 16, flags: mysqlUnsigned}, + Vector: {typ: 242}, TypeJSON: {typ: 245}, Decimal: {typ: 246}, Text: {typ: 252}, diff --git a/go/sqltypes/value.go b/go/sqltypes/value.go index bb4e26d15e3..4dde979066b 100644 --- a/go/sqltypes/value.go +++ b/go/sqltypes/value.go @@ -861,7 +861,25 @@ var SQLEncodeMap [256]byte // SQLDecodeMap is the reverse of SQLEncodeMap var SQLDecodeMap [256]byte +// encodeRef is a map of characters we use for escaping. +// This doesn't include double quotes since we don't need +// to escape that, as we always generate single quoted strings. var encodeRef = map[byte]byte{ + '\x00': '0', + '\'': '\'', + '\b': 'b', + '\n': 'n', + '\r': 'r', + '\t': 't', + 26: 'Z', // ctl-Z + '\\': '\\', +} + +// decodeRef is a map of characters we use for unescaping. +// We do need all characters here, since we do accept +// escaped double quotes in single quote strings and +// double quoted strings. +var decodeRef = map[byte]byte{ '\x00': '0', '\'': '\'', '"': '"', @@ -931,6 +949,11 @@ func init() { for i := range SQLEncodeMap { if to, ok := encodeRef[byte(i)]; ok { SQLEncodeMap[byte(i)] = to + } + } + + for i := range SQLDecodeMap { + if to, ok := decodeRef[byte(i)]; ok { SQLDecodeMap[to] = byte(i) } } diff --git a/go/sqltypes/value_test.go b/go/sqltypes/value_test.go index 36a0f5a5090..c7bdf1234dd 100644 --- a/go/sqltypes/value_test.go +++ b/go/sqltypes/value_test.go @@ -380,7 +380,7 @@ func TestEncode(t *testing.T) { outASCII: "'Zm9v'", }, { in: TestValue(VarChar, "\x00'\"\b\n\r\t\x1A\\"), - outSQL: "'\\0\\'\\\"\\b\\n\\r\\t\\Z\\\\'", + outSQL: "'\\0\\'\"\\b\\n\\r\\t\\Z\\\\'", outASCII: "'ACciCAoNCRpc'", }, { in: TestValue(Bit, "a"), @@ -442,7 +442,7 @@ func TestEncodeStringSQL(t *testing.T) { }, { in: "\x00'\"\b\n\r\t\x1A\\", - out: "'\\0\\'\\\"\\b\\n\\r\\t\\Z\\\\'", + out: "'\\0\\'\"\\b\\n\\r\\t\\Z\\\\'", }, } for _, tcase := range testcases { @@ -632,7 +632,7 @@ func TestEncodeSQLStringBuilder(t *testing.T) { outSQL: "'foo'", }, { in: TestValue(VarChar, "\x00'\"\b\n\r\t\x1A\\"), - outSQL: "'\\0\\'\\\"\\b\\n\\r\\t\\Z\\\\'", + outSQL: "'\\0\\'\"\\b\\n\\r\\t\\Z\\\\'", }, { in: TestValue(Bit, "a"), outSQL: "b'01100001'", @@ -663,7 +663,7 @@ func TestEncodeSQLBytes2(t *testing.T) { outSQL: "'foo'", }, { in: TestValue(VarChar, "\x00'\"\b\n\r\t\x1A\\"), - outSQL: "'\\0\\'\\\"\\b\\n\\r\\t\\Z\\\\'", + outSQL: "'\\0\\'\"\\b\\n\\r\\t\\Z\\\\'", }, { in: TestValue(Bit, "a"), outSQL: "b'01100001'", diff --git a/go/test/endtoend/backup/vtctlbackup/backup_utils.go b/go/test/endtoend/backup/vtctlbackup/backup_utils.go index 9227ce39516..707c9010b0c 100644 --- a/go/test/endtoend/backup/vtctlbackup/backup_utils.go +++ b/go/test/endtoend/backup/vtctlbackup/backup_utils.go @@ -21,7 +21,7 @@ import ( "context" "encoding/json" "fmt" - "math/rand" + "math/rand/v2" "os" "os/exec" "path" @@ -837,7 +837,7 @@ func checkTabletType(t *testing.T, alias string, tabletType topodata.TabletType) output, err := localCluster.VtctldClientProcess.ExecuteCommandWithOutput("GetTablet", alias) require.NoError(t, err) var tabletPB topodata.Tablet - err = json2.Unmarshal([]byte(output), &tabletPB) + err = json2.UnmarshalPB([]byte(output), &tabletPB) require.NoError(t, err) if tabletType == tabletPB.Type { return @@ -1058,7 +1058,7 @@ func terminateBackup(t *testing.T, alias string) { text := scanner.Text() if strings.Contains(text, stopBackupMsg) { tmpProcess.Process.Signal(syscall.SIGTERM) - found = true //nolint + found = true // nolint return } } @@ -1313,7 +1313,7 @@ func TestReplicaRestoreToPos(t *testing.T, replicaIndex int, restoreToPos replic require.False(t, restoreToPos.IsZero()) restoreToPosArg := replication.EncodePosition(restoreToPos) assert.Contains(t, restoreToPosArg, "MySQL56/") - if rand.Intn(2) == 0 { + if rand.IntN(2) == 0 { // Verify that restore works whether or not the MySQL56/ prefix is present. restoreToPosArg = strings.Replace(restoreToPosArg, "MySQL56/", "", 1) assert.NotContains(t, restoreToPosArg, "MySQL56/") diff --git a/go/test/endtoend/cluster/vtctldclient_process.go b/go/test/endtoend/cluster/vtctldclient_process.go index 4ed5acde518..55f04e021c9 100644 --- a/go/test/endtoend/cluster/vtctldclient_process.go +++ b/go/test/endtoend/cluster/vtctldclient_process.go @@ -66,13 +66,13 @@ func (vtctldclient *VtctldClientProcess) ExecuteCommandWithOutput(args ...string pArgs = append(pArgs, "--test.coverprofile="+getCoveragePath("vtctldclient-"+args[0]+".out"), "--test.v") } pArgs = append(pArgs, args...) - for i := 1; i <= retries; i++ { + for i := range retries { tmpProcess := exec.Command( vtctldclient.Binary, filterDoubleDashArgs(pArgs, vtctldclient.VtctldClientMajorVersion)..., ) msg := binlogplayer.LimitString(strings.Join(tmpProcess.Args, " "), 256) // limit log line length - log.Infof("Executing vtctldclient with command: %v (attempt %d of %d)", msg, i, retries) + log.Infof("Executing vtctldclient with command: %v (attempt %d of %d)", msg, i+1, retries) resultByte, err = tmpProcess.CombinedOutput() resultStr = string(resultByte) if err == nil || !shouldRetry(resultStr) { @@ -173,7 +173,7 @@ func (vtctldclient *VtctldClientProcess) GetShardReplication(keyspace string, sh } var resp vtctldatapb.GetShardReplicationResponse - err = json2.Unmarshal([]byte(out), &resp) + err = json2.UnmarshalPB([]byte(out), &resp) return resp.ShardReplicationByCell, err } @@ -252,7 +252,7 @@ func (vtctldclient *VtctldClientProcess) GetKeyspace(keyspace string) (*vtctldat } var ks vtctldatapb.Keyspace - err = json2.Unmarshal([]byte(data), &ks) + err = json2.UnmarshalPB([]byte(data), &ks) if err != nil { return nil, vterrors.Wrapf(err, "failed to parse keyspace output: %s", data) } @@ -267,7 +267,7 @@ func (vtctldclient *VtctldClientProcess) GetShard(keyspace string, shard string) } var si vtctldatapb.Shard - err = json2.Unmarshal([]byte(data), &si) + err = json2.UnmarshalPB([]byte(data), &si) if err != nil { return nil, vterrors.Wrapf(err, "failed to parse shard output: %s", data) } @@ -282,7 +282,7 @@ func (vtctldclient *VtctldClientProcess) GetTablet(alias string) (*topodatapb.Ta } var tablet topodatapb.Tablet - err = json2.Unmarshal([]byte(data), &tablet) + err = json2.UnmarshalPB([]byte(data), &tablet) if err != nil { return nil, vterrors.Wrapf(err, "failed to parse tablet output: %s", data) } diff --git a/go/test/endtoend/cluster/vtgate_process.go b/go/test/endtoend/cluster/vtgate_process.go index d1877fb89bb..5143e9ad8a4 100644 --- a/go/test/endtoend/cluster/vtgate_process.go +++ b/go/test/endtoend/cluster/vtgate_process.go @@ -237,6 +237,19 @@ func (vtgate *VtgateProcess) WaitForStatusOfTabletInShard(name string, endPoints return fmt.Errorf("wait for %s failed", name) } +// IsShutdown checks if the vtgate process is shutdown +func (vtgate *VtgateProcess) IsShutdown() bool { + return !vtgate.WaitForStatus() +} + +// Terminate sends a SIGTERM to vtgate +func (vtgate *VtgateProcess) Terminate() error { + if vtgate.proc == nil { + return nil + } + return vtgate.proc.Process.Signal(syscall.SIGTERM) +} + // TearDown shuts down the running vtgate service func (vtgate *VtgateProcess) TearDown() error { if vtgate.proc == nil || vtgate.exit == nil { diff --git a/go/test/endtoend/onlineddl/flow/onlineddl_flow_test.go b/go/test/endtoend/onlineddl/flow/onlineddl_flow_test.go index aed3efcde2f..58e985296b5 100644 --- a/go/test/endtoend/onlineddl/flow/onlineddl_flow_test.go +++ b/go/test/endtoend/onlineddl/flow/onlineddl_flow_test.go @@ -222,7 +222,7 @@ func TestSchemaChange(t *testing.T) { shards = clusterInstance.Keyspaces[0].Shards require.Equal(t, 1, len(shards)) - throttler.EnableLagThrottlerAndWaitForStatus(t, clusterInstance, time.Second) + throttler.EnableLagThrottlerAndWaitForStatus(t, clusterInstance) t.Run("flow", func(t *testing.T) { t.Run("create schema", func(t *testing.T) { @@ -283,24 +283,18 @@ func TestSchemaChange(t *testing.T) { onlineddl.CheckMigrationStatus(t, &vtParams, shards, uuid, schema.OnlineDDLStatusRunning) }) t.Run("throttle online-ddl", func(t *testing.T) { + onlineddl.CheckThrottledApps(t, &vtParams, throttlerapp.OnlineDDLName, false) onlineddl.ThrottleAllMigrations(t, &vtParams) onlineddl.CheckThrottledApps(t, &vtParams, throttlerapp.OnlineDDLName, true) - - for _, tab := range tablets { - body, err := throttleApp(tab.VttabletProcess, throttlerapp.OnlineDDLName) - assert.NoError(t, err) - assert.Contains(t, body, throttlerapp.OnlineDDLName) - } waitForThrottleCheckStatus(t, throttlerapp.OnlineDDLName, primaryTablet, http.StatusExpectationFailed) }) t.Run("unthrottle online-ddl", func(t *testing.T) { onlineddl.UnthrottleAllMigrations(t, &vtParams) - onlineddl.CheckThrottledApps(t, &vtParams, throttlerapp.OnlineDDLName, false) - - for _, tab := range tablets { - body, err := unthrottleApp(tab.VttabletProcess, throttlerapp.OnlineDDLName) + if !onlineddl.CheckThrottledApps(t, &vtParams, throttlerapp.OnlineDDLName, false) { + status, err := throttler.GetThrottlerStatus(&clusterInstance.VtctldClientProcess, primaryTablet) assert.NoError(t, err) - assert.Contains(t, body, throttlerapp.OnlineDDLName) + + t.Logf("Throttler status: %+v", status) } waitForThrottleCheckStatus(t, throttlerapp.OnlineDDLName, primaryTablet, http.StatusOK) }) @@ -339,18 +333,18 @@ func TestSchemaChange(t *testing.T) { }) isComplete := false t.Run("optimistic wait for migration completion", func(t *testing.T) { - status := onlineddl.WaitForMigrationStatus(t, &vtParams, shards, uuid, migrationWaitTimeout, schema.OnlineDDLStatusRunning, schema.OnlineDDLStatusComplete) + status := onlineddl.WaitForMigrationStatus(t, &vtParams, shards, uuid, migrationWaitTimeout, schema.OnlineDDLStatusComplete) isComplete = (status == schema.OnlineDDLStatusComplete) - fmt.Printf("# Migration status (for debug purposes): <%s>\n", status) + t.Logf("# Migration status (for debug purposes): <%s>", status) }) if !isComplete { t.Run("force complete cut-over", func(t *testing.T) { onlineddl.CheckForceMigrationCutOver(t, &vtParams, shards, uuid, true) }) t.Run("another optimistic wait for migration completion", func(t *testing.T) { - status := onlineddl.WaitForMigrationStatus(t, &vtParams, shards, uuid, migrationWaitTimeout, schema.OnlineDDLStatusRunning, schema.OnlineDDLStatusComplete) + status := onlineddl.WaitForMigrationStatus(t, &vtParams, shards, uuid, migrationWaitTimeout, schema.OnlineDDLStatusComplete) isComplete = (status == schema.OnlineDDLStatusComplete) - fmt.Printf("# Migration status (for debug purposes): <%s>\n", status) + t.Logf("# Migration status (for debug purposes): <%s>", status) }) } if !isComplete { @@ -364,7 +358,7 @@ func TestSchemaChange(t *testing.T) { } t.Run("wait for migration completion", func(t *testing.T) { status := onlineddl.WaitForMigrationStatus(t, &vtParams, shards, uuid, migrationWaitTimeout, schema.OnlineDDLStatusComplete) - fmt.Printf("# Migration status (for debug purposes): <%s>\n", status) + t.Logf("# Migration status (for debug purposes): <%s>", status) onlineddl.CheckMigrationStatus(t, &vtParams, shards, uuid, schema.OnlineDDLStatusComplete) }) t.Run("validate table schema", func(t *testing.T) { @@ -394,15 +388,15 @@ func testOnlineDDLStatement(t *testing.T, alterStatement string, ddlStrategy str uuid = row.AsString("uuid", "") uuid = strings.TrimSpace(uuid) require.NotEmpty(t, uuid) - fmt.Println("# Generated UUID (for debug purposes):") - fmt.Printf("<%s>\n", uuid) + t.Logf("# Generated UUID (for debug purposes):") + t.Logf("<%s>", uuid) strategySetting, err := schema.ParseDDLStrategy(ddlStrategy) assert.NoError(t, err) if !strategySetting.Strategy.IsDirect() && !skipWait && uuid != "" { status := onlineddl.WaitForMigrationStatus(t, &vtParams, shards, uuid, migrationWaitTimeout, schema.OnlineDDLStatusComplete, schema.OnlineDDLStatusFailed) - fmt.Printf("# Migration status (for debug purposes): <%s>\n", status) + t.Logf("# Migration status (for debug purposes): <%s>", status) } if expectHint != "" { diff --git a/go/test/endtoend/onlineddl/revert/onlineddl_revert_test.go b/go/test/endtoend/onlineddl/revert/onlineddl_revert_test.go index 0efed92f440..3a963c85ce2 100644 --- a/go/test/endtoend/onlineddl/revert/onlineddl_revert_test.go +++ b/go/test/endtoend/onlineddl/revert/onlineddl_revert_test.go @@ -21,6 +21,7 @@ import ( "flag" "fmt" "math/rand/v2" + "net/http" "os" "path" "strings" @@ -33,6 +34,7 @@ import ( "vitess.io/vitess/go/mysql/capabilities" "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/schema" + "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/throttlerapp" "vitess.io/vitess/go/test/endtoend/cluster" "vitess.io/vitess/go/test/endtoend/onlineddl" @@ -85,6 +87,7 @@ deletesAttempts=%d, deletesFailures=%d, deletesNoops=%d, deletes=%d, var ( clusterInstance *cluster.LocalProcessCluster + primaryTablet *cluster.Vttablet shards []cluster.Shard vtParams mysql.ConnParams mysqlVersion string @@ -188,7 +191,7 @@ func TestMain(m *testing.M) { Host: clusterInstance.Hostname, Port: clusterInstance.VtgateMySQLPort, } - + primaryTablet = clusterInstance.Keyspaces[0].Shards[0].PrimaryTablet() return m.Run(), nil }() if err != nil { @@ -205,7 +208,8 @@ func TestSchemaChange(t *testing.T) { shards = clusterInstance.Keyspaces[0].Shards require.Equal(t, 1, len(shards)) - throttler.EnableLagThrottlerAndWaitForStatus(t, clusterInstance, time.Second) + throttler.EnableLagThrottlerAndWaitForStatus(t, clusterInstance) + throttler.WaitForCheckThrottlerResult(t, clusterInstance, primaryTablet, throttlerapp.TestingName, nil, http.StatusOK, time.Minute) t.Run("revertible", testRevertible) t.Run("revert", testRevert) @@ -410,7 +414,16 @@ func testRevertible(t *testing.T) { // This is the migration we will test, and see whether it is revertible or not (and why not). toStatement := fmt.Sprintf(createTableWrapper, testcase.toSchema) uuid = testOnlineDDLStatement(t, toStatement, ddlStrategy, "vtgate", tableName, "") - onlineddl.CheckMigrationStatus(t, &vtParams, shards, uuid, schema.OnlineDDLStatusComplete) + if !onlineddl.CheckMigrationStatus(t, &vtParams, shards, uuid, schema.OnlineDDLStatusComplete) { + resp, err := throttler.CheckThrottler(clusterInstance, primaryTablet, throttlerapp.TestingName, nil) + assert.NoError(t, err) + fmt.Println("Throttler check response: ", resp) + + output, err := throttler.GetThrottlerStatusRaw(&clusterInstance.VtctldClientProcess, primaryTablet) + assert.NoError(t, err) + fmt.Println("Throttler status response: ", output) + } + checkTable(t, tableName, true) }) t.Run("check migration", func(t *testing.T) { @@ -557,7 +570,7 @@ func testRevert(t *testing.T) { onlineddl.VtgateExecQuery(t, &vtParams, populatePartitionedTableStatement, "") } - mysqlVersion = onlineddl.GetMySQLVersion(t, clusterInstance.Keyspaces[0].Shards[0].PrimaryTablet()) + mysqlVersion = onlineddl.GetMySQLVersion(t, primaryTablet) require.NotEmpty(t, mysqlVersion) capableOf := mysql.ServerVersionCapableOf(mysqlVersion) diff --git a/go/test/endtoend/onlineddl/scheduler/onlineddl_scheduler_test.go b/go/test/endtoend/onlineddl/scheduler/onlineddl_scheduler_test.go index 5b88b1f8678..a034aa6d65a 100644 --- a/go/test/endtoend/onlineddl/scheduler/onlineddl_scheduler_test.go +++ b/go/test/endtoend/onlineddl/scheduler/onlineddl_scheduler_test.go @@ -71,6 +71,7 @@ type testRevertMigrationParams struct { var ( clusterInstance *cluster.LocalProcessCluster + primaryTablet *cluster.Vttablet shards []cluster.Shard vtParams mysql.ConnParams @@ -208,20 +209,32 @@ func waitForMessage(t *testing.T, uuid string, messageSubstring string) { ticker := time.NewTicker(time.Second) defer ticker.Stop() + + var lastMessage string for { rs := onlineddl.ReadMigrations(t, &vtParams, uuid) require.NotNil(t, rs) for _, row := range rs.Named().Rows { - message := row.AsString("message", "") - if strings.Contains(message, messageSubstring) { + lastMessage = row.AsString("message", "") + if strings.Contains(lastMessage, messageSubstring) { return } } select { case <-ticker.C: case <-ctx.Done(): + { + resp, err := throttler.CheckThrottler(clusterInstance, primaryTablet, throttlerapp.TestingName, nil) + assert.NoError(t, err) + fmt.Println("Throttler check response: ", resp) + + output, err := throttler.GetThrottlerStatusRaw(&clusterInstance.VtctldClientProcess, primaryTablet) + assert.NoError(t, err) + fmt.Println("Throttler status response: ", output) + } + require.Failf(t, "timeout waiting for message", "expected: %s. Last seen: %s", messageSubstring, lastMessage) + return } - require.NoError(t, ctx.Err()) } } @@ -278,6 +291,7 @@ func TestMain(m *testing.M) { Host: clusterInstance.Hostname, Port: clusterInstance.VtgateMySQLPort, } + primaryTablet = clusterInstance.Keyspaces[0].Shards[0].PrimaryTablet() return m.Run(), nil }() @@ -292,7 +306,7 @@ func TestMain(m *testing.M) { func TestSchemaChange(t *testing.T) { - throttler.EnableLagThrottlerAndWaitForStatus(t, clusterInstance, time.Second) + throttler.EnableLagThrottlerAndWaitForStatus(t, clusterInstance) t.Run("scheduler", testScheduler) t.Run("singleton", testSingleton) @@ -334,7 +348,7 @@ func testScheduler(t *testing.T) { } } - mysqlVersion := onlineddl.GetMySQLVersion(t, clusterInstance.Keyspaces[0].Shards[0].PrimaryTablet()) + mysqlVersion := onlineddl.GetMySQLVersion(t, primaryTablet) require.NotEmpty(t, mysqlVersion) capableOf := mysql.ServerVersionCapableOf(mysqlVersion) @@ -558,12 +572,17 @@ func testScheduler(t *testing.T) { } }) }) + t.Run("show vitess_migrations in transaction", func(t *testing.T) { + // The function validates there is no error + rs := onlineddl.VtgateExecQueryInTransaction(t, &vtParams, "show vitess_migrations", "") + assert.NotEmpty(t, rs.Rows) + }) forceCutoverCapable, err := capableOf(capabilities.PerformanceSchemaDataLocksTableCapability) // 8.0 require.NoError(t, err) if forceCutoverCapable { t.Run("force_cutover", func(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), extendedWaitTime*2) + ctx, cancel := context.WithTimeout(context.Background(), extendedWaitTime*5) defer cancel() t.Run("populate t1_test", func(t *testing.T) { @@ -586,7 +605,21 @@ func testScheduler(t *testing.T) { commitTransactionChan := make(chan any) transactionErrorChan := make(chan error) t.Run("locking table rows", func(t *testing.T) { - go runInTransaction(t, ctx, shards[0].Vttablets[0], "select * from t1_test for update", commitTransactionChan, transactionErrorChan) + go runInTransaction(t, ctx, primaryTablet, "select * from t1_test for update", commitTransactionChan, transactionErrorChan) + }) + t.Run("injecting heartbeats asynchronously", func(t *testing.T) { + go func() { + ticker := time.NewTicker(time.Second) + defer ticker.Stop() + for { + throttler.CheckThrottler(clusterInstance, primaryTablet, throttlerapp.OnlineDDLName, nil) + select { + case <-ticker.C: + case <-ctx.Done(): + return + } + } + }() }) t.Run("check no force_cutover", func(t *testing.T) { rs := onlineddl.ReadMigrations(t, &vtParams, t1uuid) @@ -1035,6 +1068,22 @@ func testScheduler(t *testing.T) { }) }) + readCleanupsTimetamps := func(t *testing.T, migrationsLike string) (rows int64, cleanedUp int64, needCleanup int64, artifacts []string) { + rs := onlineddl.ReadMigrations(t, &vtParams, migrationsLike) + require.NotNil(t, rs) + for _, row := range rs.Named().Rows { + rows++ + if row["cleanup_timestamp"].IsNull() { + needCleanup++ + } else { + cleanedUp++ + } + migrationArtifacts := textutil.SplitDelimitedList(row.AsString("artifacts", "")) + artifacts = append(artifacts, migrationArtifacts...) + } + return + } + t.Run("Cleanup artifacts", func(t *testing.T) { // Create a migration with a low --retain-artifacts value. // We will cancel the migration and expect the artifact to be cleaned. @@ -1071,14 +1120,14 @@ func testScheduler(t *testing.T) { defer cancel() for { - rs := onlineddl.ReadMigrations(t, &vtParams, t1uuid) - require.NotNil(t, rs) - row := rs.Named().Row() - require.NotNil(t, row) - if !row["cleanup_timestamp"].IsNull() { + rows, cleanedUp, needCleanup, _ := readCleanupsTimetamps(t, t1uuid) + assert.EqualValues(t, 1, rows) + if cleanedUp == 1 { // This is what we've been waiting for break } + assert.EqualValues(t, 0, cleanedUp) + assert.EqualValues(t, 1, needCleanup) select { case <-ctx.Done(): assert.Fail(t, "timeout waiting for cleanup") @@ -1092,6 +1141,108 @@ func testScheduler(t *testing.T) { }) }) + t.Run("cleanup artifacts with CLEANUP ALL", func(t *testing.T) { + // First, cleanup any existing migrations. We don't have an exact track of how many we've had so far. + t.Run("initial cleanup all", func(t *testing.T) { + t.Run("validate migrations exist that need cleanup", func(t *testing.T) { + _, _, needCleanup, _ := readCleanupsTimetamps(t, "%") + assert.Greater(t, needCleanup, int64(1)) + }) + t.Run("issue cleanup all", func(t *testing.T) { + cleanedUp := onlineddl.CheckCleanupAllMigrations(t, &vtParams, -1) + t.Logf("marked %d migrations for cleanup", cleanedUp) + }) + t.Run("wait for all migrations cleanup", func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), extendedWaitTime) + defer cancel() + + for { + rows, cleanedUp, needCleanup, artifacts := readCleanupsTimetamps(t, "%") + if needCleanup == 0 { + // This is what we've been waiting for + assert.NotZero(t, rows) + assert.Equal(t, rows, cleanedUp) + assert.Empty(t, artifacts) + t.Logf("rows needing cleanup: %v", needCleanup) + return + } + select { + case <-ctx.Done(): + assert.Fail(t, "timeout waiting for cleanup", "rows needing cleanup: %v. artifacts: %v", needCleanup, artifacts) + return + case <-time.After(time.Second): + } + t.Logf("rows needing cleanup: %v. artifacts: %v", needCleanup, artifacts) + } + }) + }) + // Create a migration with a low --retain-artifacts value. + // We will cancel the migration and expect the artifact to be cleaned. + t.Run("start migration", func(t *testing.T) { + // Intentionally set `--retain-artifacts=1h` which is a long time. Then we will issue + // `ALTER VITESS_MIGRATION CLEANUP ALL` and expect the artifact to be cleaned. + t1uuid = testOnlineDDLStatement(t, createParams(trivialAlterT1Statement, ddlStrategy+" --postpone-completion --retain-artifacts=1h", "vtctl", "", "", true)) // skip wait + onlineddl.WaitForMigrationStatus(t, &vtParams, shards, t1uuid, normalWaitTime, schema.OnlineDDLStatusRunning) + }) + t.Run("wait for ready_to_complete", func(t *testing.T) { + waitForReadyToComplete(t, t1uuid, true) + }) + var artifacts []string + t.Run("validate artifact exists", func(t *testing.T) { + rs := onlineddl.ReadMigrations(t, &vtParams, t1uuid) + require.NotNil(t, rs) + row := rs.Named().Row() + require.NotNil(t, row) + + artifacts = textutil.SplitDelimitedList(row.AsString("artifacts", "")) + require.Len(t, artifacts, 1) + checkTable(t, artifacts[0], true) + + retainArtifactsSeconds := row.AsInt64("retain_artifacts_seconds", 0) + assert.EqualValues(t, 3600, retainArtifactsSeconds) // due to --retain-artifacts=1h + }) + t.Run("check needs cleanup", func(t *testing.T) { + _, _, needCleanup, _ := readCleanupsTimetamps(t, "%") + assert.EqualValues(t, 1, needCleanup) + }) + t.Run("complete migration", func(t *testing.T) { + onlineddl.CheckCompleteMigration(t, &vtParams, shards, t1uuid, true) + status := onlineddl.WaitForMigrationStatus(t, &vtParams, shards, t1uuid, normalWaitTime, schema.OnlineDDLStatusComplete, schema.OnlineDDLStatusFailed, schema.OnlineDDLStatusCancelled) + fmt.Printf("# Migration status (for debug purposes): <%s>\n", status) + onlineddl.CheckMigrationStatus(t, &vtParams, shards, t1uuid, schema.OnlineDDLStatusComplete) + }) + t.Run("cleanup all", func(t *testing.T) { + onlineddl.CheckCleanupAllMigrations(t, &vtParams, 1) + }) + t.Run("wait for migration cleanup", func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), extendedWaitTime) + defer cancel() + + for { + rows, cleanedUp, needCleanup, artifacts := readCleanupsTimetamps(t, "%") + if needCleanup == 0 { + // This is what we've been waiting for + assert.NotZero(t, rows) + assert.Equal(t, rows, cleanedUp) + assert.Empty(t, artifacts) + t.Logf("rows needing cleanup: %v", needCleanup) + return + } + select { + case <-ctx.Done(): + assert.Fail(t, "timeout waiting for cleanup", "rows needing cleanup: %v. artifacts: %v", needCleanup, artifacts) + return + case <-time.After(time.Second): + } + t.Logf("rows needing cleanup: %v. artifacts: %v", needCleanup, artifacts) + } + }) + + t.Run("validate artifact does not exist", func(t *testing.T) { + checkTable(t, artifacts[0], false) + }) + }) + checkConstraintCapable, err := capableOf(capabilities.CheckConstraintsCapability) // 8.0.16 and above require.NoError(t, err) if checkConstraintCapable { @@ -1105,7 +1256,7 @@ func testScheduler(t *testing.T) { // name it `with_constraint_chk_1`. But we expect Online DDL to explicitly // modify the constraint name, specifically to get rid of the prefix, // so that we don't get into https://bugs.mysql.com/bug.php?id=107772 situation. - createStatement := getCreateTableStatement(t, shards[0].Vttablets[0], "with_constraint") + createStatement := getCreateTableStatement(t, primaryTablet, "with_constraint") assert.NotContains(t, createStatement, "with_constraint_chk") }) }) @@ -1463,6 +1614,7 @@ DROP TABLE IF EXISTS stress_test checkTable(t, tableName, true) }) t.Run("revert CREATE TABLE", func(t *testing.T) { + require.NotEmpty(t, uuids) // The table existed, so it will now be dropped (renamed) uuid := testRevertMigration(t, createRevertParams(uuids[len(uuids)-1], onlineSingletonDDLStrategy, "vtgate", "", "", false)) uuids = append(uuids, uuid) @@ -2433,7 +2585,7 @@ func testForeignKeys(t *testing.T) { // // In this stress test, we enable Online DDL if the variable 'rename_table_preserve_foreign_key' is present. The Online DDL mechanism will in turn // query for this variable, and manipulate it, when starting the migration and when cutting over. - rs, err := shards[0].Vttablets[0].VttabletProcess.QueryTablet("show global variables like 'rename_table_preserve_foreign_key'", keyspaceName, false) + rs, err := primaryTablet.VttabletProcess.QueryTablet("show global variables like 'rename_table_preserve_foreign_key'", keyspaceName, false) require.NoError(t, err) fkOnlineDDLPossible = len(rs.Rows) > 0 t.Logf("MySQL support for 'rename_table_preserve_foreign_key': %v", fkOnlineDDLPossible) diff --git a/go/test/endtoend/onlineddl/vrepl/onlineddl_vrepl_test.go b/go/test/endtoend/onlineddl/vrepl/onlineddl_vrepl_test.go index e5df3051612..83fe6bea988 100644 --- a/go/test/endtoend/onlineddl/vrepl/onlineddl_vrepl_test.go +++ b/go/test/endtoend/onlineddl/vrepl/onlineddl_vrepl_test.go @@ -38,6 +38,7 @@ import ( "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/throttlerapp" binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" + vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" ) var ( @@ -177,7 +178,6 @@ func TestMain(m *testing.M) { clusterInstance.VtTabletExtraArgs = []string{ "--heartbeat_interval", "250ms", - "--heartbeat_on_demand_duration", "5s", "--migration_check_interval", "5s", "--watch_replication_stream", } @@ -247,7 +247,8 @@ func TestSchemaChange(t *testing.T) { } }) t.Run("updating throttler config", func(t *testing.T) { - _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, true, false, customThreshold, noCustomQuery, nil) + req := &vtctldatapb.UpdateThrottlerConfigRequest{Enable: true, Threshold: customThreshold} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, nil, nil) require.NoError(t, err) }) @@ -258,7 +259,7 @@ func TestSchemaChange(t *testing.T) { t.Run(shard.Name, func(t *testing.T) { for _, tablet := range shard.Vttablets { t.Run(tablet.Alias, func(t *testing.T) { - throttler.WaitForThrottlerStatusEnabled(t, tablet, true, &throttler.Config{Query: throttler.DefaultQuery, Threshold: customThreshold}, throttlerEnabledTimeout) + throttler.WaitForThrottlerStatusEnabled(t, &clusterInstance.VtctldClientProcess, tablet, true, &throttler.Config{Query: throttler.DefaultQuery, Threshold: customThreshold}, throttlerEnabledTimeout) }) } }) diff --git a/go/test/endtoend/onlineddl/vrepl_stress/onlineddl_vrepl_mini_stress_test.go b/go/test/endtoend/onlineddl/vrepl_stress/onlineddl_vrepl_mini_stress_test.go index 770f7f3ee93..93d66ad7ccb 100644 --- a/go/test/endtoend/onlineddl/vrepl_stress/onlineddl_vrepl_mini_stress_test.go +++ b/go/test/endtoend/onlineddl/vrepl_stress/onlineddl_vrepl_mini_stress_test.go @@ -237,7 +237,7 @@ func TestSchemaChange(t *testing.T) { shards = clusterInstance.Keyspaces[0].Shards require.Equal(t, 1, len(shards)) - throttler.EnableLagThrottlerAndWaitForStatus(t, clusterInstance, time.Second) + throttler.EnableLagThrottlerAndWaitForStatus(t, clusterInstance) t.Run("create schema", func(t *testing.T) { assert.Equal(t, 1, len(clusterInstance.Keyspaces[0].Shards)) diff --git a/go/test/endtoend/onlineddl/vrepl_stress_suite/onlineddl_vrepl_stress_suite_test.go b/go/test/endtoend/onlineddl/vrepl_stress_suite/onlineddl_vrepl_stress_suite_test.go index a3fa676d40b..2492d30788d 100644 --- a/go/test/endtoend/onlineddl/vrepl_stress_suite/onlineddl_vrepl_stress_suite_test.go +++ b/go/test/endtoend/onlineddl/vrepl_stress_suite/onlineddl_vrepl_stress_suite_test.go @@ -73,6 +73,7 @@ type testcase struct { var ( clusterInstance *cluster.LocalProcessCluster + primaryTablet *cluster.Vttablet vtParams mysql.ConnParams evaluatedMysqlParams *mysql.ConnParams @@ -368,6 +369,9 @@ var ( truncateStatement = ` TRUNCATE TABLE stress_test ` + setSqlMode = ` + set @@global.sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' + ` ) const ( @@ -391,17 +395,13 @@ func nextOpOrder() int64 { return opOrder } -func getTablet() *cluster.Vttablet { - return clusterInstance.Keyspaces[0].Shards[0].Vttablets[0] -} - func mysqlParams() *mysql.ConnParams { if evaluatedMysqlParams != nil { return evaluatedMysqlParams } evaluatedMysqlParams = &mysql.ConnParams{ Uname: "vt_dba", - UnixSocket: path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("/vt_%010d", getTablet().TabletUID), "/mysql.sock"), + UnixSocket: path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("/vt_%010d", primaryTablet.TabletUID), "/mysql.sock"), DbName: fmt.Sprintf("vt_%s", keyspaceName), } return evaluatedMysqlParams @@ -486,8 +486,12 @@ func TestSchemaChange(t *testing.T) { shards = clusterInstance.Keyspaces[0].Shards require.Equal(t, 1, len(shards)) + require.Equal(t, 1, len(shards[0].Vttablets)) + primaryTablet = shards[0].Vttablets[0] - throttler.EnableLagThrottlerAndWaitForStatus(t, clusterInstance, time.Second) + _, err := primaryTablet.VttabletProcess.QueryTablet(setSqlMode, keyspaceName, true) + require.NoError(t, err) + throttler.EnableLagThrottlerAndWaitForStatus(t, clusterInstance) for _, testcase := range testCases { require.NotEmpty(t, testcase.name) @@ -500,7 +504,7 @@ func TestSchemaChange(t *testing.T) { } }) t.Run("create schema", func(t *testing.T) { - assert.Equal(t, 1, len(clusterInstance.Keyspaces[0].Shards)) + assert.Len(t, shards, 1) testWithInitialSchema(t) }) t.Run("prepare table", func(t *testing.T) { @@ -596,8 +600,8 @@ func testOnlineDDLStatement(t *testing.T, alterStatement string, ddlStrategy str // checkTable checks the number of tables in the first two shards. func checkTable(t *testing.T, showTableName string) { - for i := range clusterInstance.Keyspaces[0].Shards { - checkTablesCount(t, clusterInstance.Keyspaces[0].Shards[i].Vttablets[0], showTableName, 1) + for i := range shards { + checkTablesCount(t, shards[i].Vttablets[0], showTableName, 1) } } @@ -626,8 +630,8 @@ func checkTablesCount(t *testing.T, tablet *cluster.Vttablet, showTableName stri // checkMigratedTables checks the CREATE STATEMENT of a table after migration func checkMigratedTable(t *testing.T, tableName, expectHint string) { - for i := range clusterInstance.Keyspaces[0].Shards { - createStatement := getCreateTableStatement(t, clusterInstance.Keyspaces[0].Shards[i].Vttablets[0], tableName) + for i := range shards { + createStatement := getCreateTableStatement(t, shards[i].Vttablets[0], tableName) assert.Contains(t, createStatement, expectHint) } } diff --git a/go/test/endtoend/onlineddl/vrepl_suite/onlineddl_vrepl_suite_test.go b/go/test/endtoend/onlineddl/vrepl_suite/onlineddl_vrepl_suite_test.go index 6122a71aa44..57397ec64dd 100644 --- a/go/test/endtoend/onlineddl/vrepl_suite/onlineddl_vrepl_suite_test.go +++ b/go/test/endtoend/onlineddl/vrepl_suite/onlineddl_vrepl_suite_test.go @@ -56,16 +56,21 @@ var ( beforeTableName = `onlineddl_test_before` afterTableName = `onlineddl_test_after` eventName = `onlineddl_test` + + testsFilter = "" ) const ( - testDataPath = "testdata" + testDataPath = "testdata" + testFilterEnvVar = "ONLINEDDL_SUITE_TEST_FILTER" ) func TestMain(m *testing.M) { defer cluster.PanicHandler(nil) flag.Parse() + testsFilter = os.Getenv(testFilterEnvVar) + exitcode, err := func() (int, error) { clusterInstance = cluster.NewCluster(cell, hostname) schemaChangeDirectory = path.Join("/tmp", fmt.Sprintf("schema_change_dir_%d", clusterInstance.GetAndReserveTabletUID())) @@ -132,7 +137,7 @@ func TestSchemaChange(t *testing.T) { shards := clusterInstance.Keyspaces[0].Shards require.Equal(t, 1, len(shards)) - throttler.EnableLagThrottlerAndWaitForStatus(t, clusterInstance, time.Second) + throttler.EnableLagThrottlerAndWaitForStatus(t, clusterInstance) fkOnlineDDLPossible := false t.Run("check 'rename_table_preserve_foreign_key' variable", func(t *testing.T) { @@ -183,6 +188,10 @@ func readTestFile(t *testing.T, testName string, fileName string) (content strin // testSingle is the main testing function for a single test in the suite. // It prepares the grounds, creates the test data, runs a migration, expects results/error, cleans up. func testSingle(t *testing.T, testName string, fkOnlineDDLPossible bool) { + if !strings.Contains(testName, testsFilter) { + t.Skipf("Skipping test %s due to filter: %s=%s", testName, testFilterEnvVar, testsFilter) + return + } if _, exists := readTestFile(t, testName, "require_rename_table_preserve_foreign_key"); exists { if !fkOnlineDDLPossible { t.Skipf("Skipping test due to require_rename_table_preserve_foreign_key") diff --git a/go/test/endtoend/onlineddl/vtgate_util.go b/go/test/endtoend/onlineddl/vtgate_util.go index f2272fcd73e..6c26320b472 100644 --- a/go/test/endtoend/onlineddl/vtgate_util.go +++ b/go/test/endtoend/onlineddl/vtgate_util.go @@ -66,6 +66,29 @@ func VtgateExecQuery(t *testing.T, vtParams *mysql.ConnParams, query string, exp return qr } +// VtgateExecQueryInTransaction runs a query on VTGate using given query params, inside a transaction +func VtgateExecQueryInTransaction(t *testing.T, vtParams *mysql.ConnParams, query string, expectError string) *sqltypes.Result { + t.Helper() + + ctx := context.Background() + conn, err := mysql.Connect(ctx, vtParams) + require.Nil(t, err) + defer conn.Close() + + _, err = conn.ExecuteFetch("begin", -1, true) + require.NoError(t, err) + qr, err := conn.ExecuteFetch(query, -1, true) + if expectError == "" { + require.NoError(t, err) + } else { + require.Error(t, err, "error should not be nil") + assert.Contains(t, err.Error(), expectError, "Unexpected error") + } + _, err = conn.ExecuteFetch("commit", -1, true) + require.NoError(t, err) + return qr +} + // VtgateExecDDL executes a DDL query with given strategy func VtgateExecDDL(t *testing.T, vtParams *mysql.ConnParams, ddlStrategy string, query string, expectError string) *sqltypes.Result { t.Helper() @@ -194,6 +217,18 @@ func CheckCancelAllMigrations(t *testing.T, vtParams *mysql.ConnParams, expectCo } } +// CheckCleanupAllMigrations cleans up all applicable migrations and expect number of affected rows +// A negative value for expectCount indicates "don't care, no need to check" +func CheckCleanupAllMigrations(t *testing.T, vtParams *mysql.ConnParams, expectCount int) uint64 { + cleanupQuery := "alter vitess_migration cleanup all" + r := VtgateExecQuery(t, vtParams, cleanupQuery, "") + + if expectCount >= 0 { + assert.Equal(t, expectCount, int(r.RowsAffected)) + } + return r.RowsAffected +} + // CheckLaunchAllMigrations launches all queued posponed migrations and expect number of affected rows // A negative value for expectCount indicates "don't care, no need to check" func CheckLaunchAllMigrations(t *testing.T, vtParams *mysql.ConnParams, expectCount int) { @@ -341,7 +376,7 @@ func UnthrottleAllMigrations(t *testing.T, vtParams *mysql.ConnParams) { } // CheckThrottledApps checks for existence or non-existence of an app in the throttled apps list -func CheckThrottledApps(t *testing.T, vtParams *mysql.ConnParams, throttlerApp throttlerapp.Name, expectFind bool) { +func CheckThrottledApps(t *testing.T, vtParams *mysql.ConnParams, throttlerApp throttlerapp.Name, expectFind bool) bool { ctx, cancel := context.WithTimeout(context.Background(), ThrottledAppsTimeout) defer cancel() @@ -361,13 +396,13 @@ func CheckThrottledApps(t *testing.T, vtParams *mysql.ConnParams, throttlerApp t } if appFound == expectFind { // we're all good - return + return true } select { case <-ctx.Done(): - assert.Failf(t, "CheckThrottledApps timed out waiting for %v to be in throttled status '%v'", throttlerApp.String(), expectFind) - return + assert.Fail(t, "CheckThrottledApps timed out", "waiting for '%v' to be in throttled status '%v'", throttlerApp.String(), expectFind) + return false case <-ticker.C: } } diff --git a/go/test/endtoend/recovery/pitr/shardedpitr_test.go b/go/test/endtoend/recovery/pitr/shardedpitr_test.go index 03fcf76b07c..f2a76662918 100644 --- a/go/test/endtoend/recovery/pitr/shardedpitr_test.go +++ b/go/test/endtoend/recovery/pitr/shardedpitr_test.go @@ -130,7 +130,7 @@ func TestPITRRecovery(t *testing.T) { initializeCluster(t) defer clusterInstance.Teardown() - //start the binlog server and point it to primary + // start the binlog server and point it to primary bs := startBinlogServer(t, primary) defer bs.stop() @@ -167,11 +167,11 @@ func TestPITRRecovery(t *testing.T) { // starting resharding process performResharding(t) - //start the binlog server and point it to shard0Primary + // start the binlog server and point it to shard0Primary bs0 := startBinlogServer(t, shard0Primary) defer bs0.stop() - //start the binlog server and point it to shard1Primary + // start the binlog server and point it to shard1Primary bs1 := startBinlogServer(t, shard1Primary) defer bs1.stop() @@ -585,7 +585,7 @@ func waitForNoWorkflowLag(t *testing.T, vc *cluster.LocalProcessCluster, ks stri require.NoError(t, err) var resp vtctldatapb.GetWorkflowsResponse - err = json2.Unmarshal([]byte(output), &resp) + err = json2.UnmarshalPB([]byte(output), &resp) require.NoError(t, err) require.GreaterOrEqual(t, len(resp.Workflows), 1, "responce should have at least one workflow") lag = resp.Workflows[0].MaxVReplicationTransactionLag diff --git a/go/test/endtoend/reparent/plannedreparent/reparent_test.go b/go/test/endtoend/reparent/plannedreparent/reparent_test.go index ae9bd6bbc9b..ccfd2eee239 100644 --- a/go/test/endtoend/reparent/plannedreparent/reparent_test.go +++ b/go/test/endtoend/reparent/plannedreparent/reparent_test.go @@ -297,17 +297,14 @@ func TestReparentWithDownReplica(t *testing.T) { // Perform a graceful reparent operation. It will fail as one tablet is down. out, err := utils.Prs(t, clusterInstance, tablets[1]) require.Error(t, err) - var insertVal int // Assert that PRS failed - if clusterInstance.VtctlMajorVersion <= 17 { - assert.True(t, utils.SetReplicationSourceFailed(tablets[2], out)) - // insert data into the new primary, check the connected replica work - insertVal = utils.ConfirmReplication(t, tablets[1], []*cluster.Vttablet{tablets[0], tablets[3]}) - } else { + if clusterInstance.VtctlMajorVersion <= 20 { assert.Contains(t, out, fmt.Sprintf("TabletManager.PrimaryStatus on %s", tablets[2].Alias)) - // insert data into the old primary, check the connected replica works. The primary tablet shouldn't have changed. - insertVal = utils.ConfirmReplication(t, tablets[0], []*cluster.Vttablet{tablets[1], tablets[3]}) + } else { + assert.Contains(t, out, fmt.Sprintf("TabletManager.GetGlobalStatusVars on %s", tablets[2].Alias)) } + // insert data into the old primary, check the connected replica works. The primary tablet shouldn't have changed. + insertVal := utils.ConfirmReplication(t, tablets[0], []*cluster.Vttablet{tablets[1], tablets[3]}) // restart mysql on the old replica, should still be connecting to the old primary tablets[2].MysqlctlProcess.InitMysql = false diff --git a/go/test/endtoend/reparent/prssettingspool/main_test.go b/go/test/endtoend/reparent/prssettingspool/main_test.go index 872f1867c77..4364836841b 100644 --- a/go/test/endtoend/reparent/prssettingspool/main_test.go +++ b/go/test/endtoend/reparent/prssettingspool/main_test.go @@ -61,8 +61,6 @@ func TestMain(m *testing.M) { Name: keyspaceName, SchemaSQL: schemaSQL, } - clusterInstance.VtTabletExtraArgs = append(clusterInstance.VtTabletExtraArgs, - "--queryserver-enable-settings-pool") err = clusterInstance.StartUnshardedKeyspace(*keyspace, 2, false) if err != nil { return 1 diff --git a/go/test/endtoend/reparent/semisync/semi_sync_test.go b/go/test/endtoend/reparent/semisync/semi_sync_test.go new file mode 100644 index 00000000000..07cf4a7abc8 --- /dev/null +++ b/go/test/endtoend/reparent/semisync/semi_sync_test.go @@ -0,0 +1,102 @@ +/* +Copyright 2024 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 semisync + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/test/endtoend/cluster" + "vitess.io/vitess/go/test/endtoend/reparent/utils" +) + +func TestSemiSyncUpgradeDowngrade(t *testing.T) { + ver, err := cluster.GetMajorVersion("vtgate") + require.NoError(t, err) + if ver != 21 { + t.Skip("We only want to run this test for v21 release") + } + defer cluster.PanicHandler(t) + clusterInstance := utils.SetupReparentCluster(t, "semi_sync") + defer utils.TeardownCluster(clusterInstance) + tablets := clusterInstance.Keyspaces[0].Shards[0].Vttablets + + // Verify that replication is running as intended. + utils.ConfirmReplication(t, tablets[0], []*cluster.Vttablet{tablets[1], tablets[2], tablets[3]}) + + replica := tablets[1] + // Verify we are using the correct vttablet version. + verifyVttabletVersion(t, replica, 21) + // Check the plugin loaded in vttablet. + require.EqualValues(t, mysql.SemiSyncTypeSource, semiSyncExtensionLoaded(t, replica)) + + t.Run("Downgrade to previous release", func(t *testing.T) { + // change vttablet binary and downgrade it. + changeVttabletBinary(t, replica, "vttabletold") + // Verify we are using the older vttablet version. + verifyVttabletVersion(t, replica, 20) + // Verify that replication is running as intended. + utils.ConfirmReplication(t, tablets[0], []*cluster.Vttablet{tablets[1], tablets[2], tablets[3]}) + // Check the plugin loaded in vttablet. + require.EqualValues(t, mysql.SemiSyncTypeSource, semiSyncExtensionLoaded(t, replica)) + }) + + t.Run("Upgrade to current release", func(t *testing.T) { + // change vttablet binary and downgrade it. + changeVttabletBinary(t, replica, "vttablet") + // Verify we are using the older vttablet version. + verifyVttabletVersion(t, replica, 21) + // Verify that replication is running as intended. + utils.ConfirmReplication(t, tablets[0], []*cluster.Vttablet{tablets[1], tablets[2], tablets[3]}) + // Check the plugin loaded in vttablet. + require.EqualValues(t, mysql.SemiSyncTypeSource, semiSyncExtensionLoaded(t, replica)) + }) +} + +// semiSyncExtensionLoaded checks if the semisync extension has been loaded. +// It should work for both MariaDB and MySQL. +func semiSyncExtensionLoaded(t *testing.T, replica *cluster.Vttablet) mysql.SemiSyncType { + qr := utils.RunSQL(context.Background(), t, `SHOW VARIABLES LIKE 'rpl_semi_sync_%_enabled'`, replica) + for _, row := range qr.Rows { + if row[0].ToString() == "rpl_semi_sync_source_enabled" { + return mysql.SemiSyncTypeSource + } + if row[0].ToString() == "rpl_semi_sync_master_enabled" { + return mysql.SemiSyncTypeMaster + } + } + return mysql.SemiSyncTypeOff +} + +func changeVttabletBinary(t *testing.T, replica *cluster.Vttablet, binary string) { + t.Helper() + err := replica.VttabletProcess.TearDown() + require.NoError(t, err) + replica.VttabletProcess.Binary = binary + err = replica.VttabletProcess.Setup() + require.NoError(t, err) +} + +func verifyVttabletVersion(t *testing.T, replica *cluster.Vttablet, version int) { + t.Helper() + verGot, err := cluster.GetMajorVersion(replica.VttabletProcess.Binary) + require.NoError(t, err) + require.EqualValues(t, version, verGot) +} diff --git a/go/test/endtoend/schemadiff/vrepl/schemadiff_vrepl_suite_test.go b/go/test/endtoend/schemadiff/vrepl/schemadiff_vrepl_suite_test.go index 79cb4a0174e..496956f2838 100644 --- a/go/test/endtoend/schemadiff/vrepl/schemadiff_vrepl_suite_test.go +++ b/go/test/endtoend/schemadiff/vrepl/schemadiff_vrepl_suite_test.go @@ -25,7 +25,6 @@ import ( "regexp" "strings" "testing" - "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -138,7 +137,7 @@ func TestSchemaChange(t *testing.T) { shards := clusterInstance.Keyspaces[0].Shards require.Equal(t, 1, len(shards)) - throttler.EnableLagThrottlerAndWaitForStatus(t, clusterInstance, time.Second) + throttler.EnableLagThrottlerAndWaitForStatus(t, clusterInstance) files, err := os.ReadDir(testDataPath) require.NoError(t, err) diff --git a/go/test/endtoend/tabletgateway/buffer/reshard/sharded_buffer_test.go b/go/test/endtoend/tabletgateway/buffer/reshard/sharded_buffer_test.go index 5e439cc9fff..39b7cbb7266 100644 --- a/go/test/endtoend/tabletgateway/buffer/reshard/sharded_buffer_test.go +++ b/go/test/endtoend/tabletgateway/buffer/reshard/sharded_buffer_test.go @@ -46,7 +46,7 @@ func waitForLowLag(t *testing.T, clusterInstance *cluster.LocalProcessCluster, k require.NoError(t, err) var resp vtctldatapb.GetWorkflowsResponse - err = json2.Unmarshal([]byte(output), &resp) + err = json2.UnmarshalPB([]byte(output), &resp) require.NoError(t, err) require.GreaterOrEqual(t, len(resp.Workflows), 1, "responce should have at least one workflow") lagSeconds := resp.Workflows[0].MaxVReplicationTransactionLag diff --git a/go/test/endtoend/tabletmanager/commands_test.go b/go/test/endtoend/tabletmanager/commands_test.go index 970e89c7037..e89a471b1e4 100644 --- a/go/test/endtoend/tabletmanager/commands_test.go +++ b/go/test/endtoend/tabletmanager/commands_test.go @@ -197,7 +197,7 @@ func runHookAndAssert(t *testing.T, params []string, expectedStatus int64, expec require.Nil(t, err) var resp vtctldatapb.ExecuteHookResponse - err = json2.Unmarshal([]byte(hr), &resp) + err = json2.UnmarshalPB([]byte(hr), &resp) require.Nil(t, err) assert.Equal(t, expectedStatus, resp.HookResult.ExitStatus) diff --git a/go/test/endtoend/tabletmanager/throttler_topo/throttler_test.go b/go/test/endtoend/tabletmanager/throttler_topo/throttler_test.go index c8251846fe6..89649f2ce4c 100644 --- a/go/test/endtoend/tabletmanager/throttler_topo/throttler_test.go +++ b/go/test/endtoend/tabletmanager/throttler_topo/throttler_test.go @@ -26,17 +26,20 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/protoutil" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/test/endtoend/cluster" "vitess.io/vitess/go/test/endtoend/throttler" - topodatapb "vitess.io/vitess/go/vt/proto/topodata" + "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/throttlerapp" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" + vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" ) const ( @@ -47,7 +50,7 @@ const ( onDemandHeartbeatDuration = 5 * time.Second throttlerEnabledTimeout = 60 * time.Second useDefaultQuery = "" - testAppName = "test" + testAppName = throttlerapp.TestingName ) var ( @@ -88,8 +91,6 @@ var ( httpClient = base.SetupHTTPClient(time.Second) throttledAppsAPIPath = "throttler/throttled-apps" - checkAPIPath = "throttler/check" - checkSelfAPIPath = "throttler/check-self" statusAPIPath = "throttler/status" getResponseBody = func(resp *http.Response) string { body, _ := io.ReadAll(resp.Body) @@ -173,13 +174,23 @@ func throttledApps(tablet *cluster.Vttablet) (resp *http.Response, respBody stri return resp, respBody, err } -func throttleCheck(tablet *cluster.Vttablet, skipRequestHeartbeats bool) (*http.Response, error) { - resp, err := httpClient.Get(fmt.Sprintf("http://localhost:%d/%s?app=%s&s=%t", tablet.HTTPPort, checkAPIPath, testAppName, skipRequestHeartbeats)) +func throttleCheck(tablet *cluster.Vttablet, skipRequestHeartbeats bool) (*vtctldatapb.CheckThrottlerResponse, error) { + flags := &throttle.CheckFlags{ + Scope: base.ShardScope, + SkipRequestHeartbeats: skipRequestHeartbeats, + MultiMetricsEnabled: true, + } + resp, err := throttler.CheckThrottler(clusterInstance, tablet, testAppName, flags) return resp, err } -func throttleCheckSelf(tablet *cluster.Vttablet) (*http.Response, error) { - return httpClient.Get(fmt.Sprintf("http://localhost:%d/%s?app=%s", tablet.HTTPPort, checkSelfAPIPath, testAppName)) +func throttleCheckSelf(tablet *cluster.Vttablet) (*vtctldatapb.CheckThrottlerResponse, error) { + flags := &throttle.CheckFlags{ + Scope: base.SelfScope, + MultiMetricsEnabled: true, + } + resp, err := throttler.CheckThrottler(clusterInstance, tablet, testAppName, flags) + return resp, err } func throttleStatus(t *testing.T, tablet *cluster.Vttablet) string { @@ -197,39 +208,32 @@ func warmUpHeartbeat(t *testing.T) (respStatus int) { // Let's warm it up. resp, err := throttleCheck(primaryTablet, false) require.NoError(t, err) - defer resp.Body.Close() time.Sleep(time.Second) - return resp.StatusCode + return int(resp.Check.StatusCode) } // waitForThrottleCheckStatus waits for the tablet to return the provided HTTP code in a throttle check -func waitForThrottleCheckStatus(t *testing.T, tablet *cluster.Vttablet, wantCode int) { +func waitForThrottleCheckStatus(t *testing.T, tablet *cluster.Vttablet, wantCode int) bool { _ = warmUpHeartbeat(t) ctx, cancel := context.WithTimeout(context.Background(), onDemandHeartbeatDuration*4) defer cancel() + ticker := time.NewTicker(time.Second) + defer ticker.Stop() for { resp, err := throttleCheck(tablet, true) require.NoError(t, err) - if wantCode == resp.StatusCode { + if wantCode == int(resp.Check.StatusCode) { // Wait for any cached check values to be cleared and the new // status value to be in effect everywhere before returning. - resp.Body.Close() - return + return true } select { case <-ctx.Done(): - b, err := io.ReadAll(resp.Body) - require.NoError(t, err) - resp.Body.Close() - - assert.Equalf(t, wantCode, resp.StatusCode, "body: %s", string(b)) - return - default: - resp.Body.Close() - time.Sleep(time.Second) + return assert.EqualValues(t, wantCode, resp.Check.StatusCode, "response: %+v", resp) + case <-ticker.C: } } } @@ -259,24 +263,26 @@ func TestInitialThrottler(t *testing.T) { waitForThrottleCheckStatus(t, primaryTablet, http.StatusOK) }) t.Run("enabling throttler with very low threshold", func(t *testing.T) { - _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, true, false, unreasonablyLowThreshold.Seconds(), useDefaultQuery, nil) + req := &vtctldatapb.UpdateThrottlerConfigRequest{Enable: true, Threshold: unreasonablyLowThreshold.Seconds()} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, nil, nil) assert.NoError(t, err) // Wait for the throttler to be enabled everywhere with the new config. for _, tablet := range clusterInstance.Keyspaces[0].Shards[0].Vttablets { - throttler.WaitForThrottlerStatusEnabled(t, tablet, true, &throttler.Config{Query: throttler.DefaultQuery, Threshold: unreasonablyLowThreshold.Seconds()}, throttlerEnabledTimeout) + throttler.WaitForThrottlerStatusEnabled(t, &clusterInstance.VtctldClientProcess, tablet, true, &throttler.Config{Query: throttler.DefaultQuery, Threshold: unreasonablyLowThreshold.Seconds()}, throttlerEnabledTimeout) } }) t.Run("validating pushback response from throttler", func(t *testing.T) { waitForThrottleCheckStatus(t, primaryTablet, http.StatusTooManyRequests) }) t.Run("disabling throttler", func(t *testing.T) { - _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, false, true, unreasonablyLowThreshold.Seconds(), useDefaultQuery, nil) + req := &vtctldatapb.UpdateThrottlerConfigRequest{Disable: true, Threshold: unreasonablyLowThreshold.Seconds()} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, nil, nil) assert.NoError(t, err) // Wait for the throttler to be disabled everywhere. for _, tablet := range clusterInstance.Keyspaces[0].Shards[0].Vttablets { - throttler.WaitForThrottlerStatusEnabled(t, tablet, false, nil, throttlerEnabledTimeout) + throttler.WaitForThrottlerStatusEnabled(t, &clusterInstance.VtctldClientProcess, tablet, false, nil, throttlerEnabledTimeout) } }) t.Run("validating OK response from disabled throttler, again", func(t *testing.T) { @@ -285,36 +291,39 @@ func TestInitialThrottler(t *testing.T) { t.Run("enabling throttler, again", func(t *testing.T) { // Enable the throttler again with the default query which also moves us back // to the default threshold. - _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, true, false, 0, useDefaultQuery, nil) + req := &vtctldatapb.UpdateThrottlerConfigRequest{Enable: true} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, nil, nil) assert.NoError(t, err) // Wait for the throttler to be enabled everywhere again with the default config. for _, tablet := range clusterInstance.Keyspaces[0].Shards[0].Vttablets { - throttler.WaitForThrottlerStatusEnabled(t, tablet, true, throttler.DefaultConfig, throttlerEnabledTimeout) + throttler.WaitForThrottlerStatusEnabled(t, &clusterInstance.VtctldClientProcess, tablet, true, throttler.DefaultConfig, throttlerEnabledTimeout) } }) t.Run("validating pushback response from throttler, again", func(t *testing.T) { waitForThrottleCheckStatus(t, primaryTablet, http.StatusTooManyRequests) }) t.Run("setting high threshold", func(t *testing.T) { - _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, false, false, extremelyHighThreshold.Seconds(), useDefaultQuery, nil) + req := &vtctldatapb.UpdateThrottlerConfigRequest{Threshold: extremelyHighThreshold.Seconds()} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, nil, nil) assert.NoError(t, err) // Wait for the throttler to be enabled everywhere with new config. for _, tablet := range []cluster.Vttablet{*primaryTablet, *replicaTablet} { - throttler.WaitForThrottlerStatusEnabled(t, &tablet, true, &throttler.Config{Query: throttler.DefaultQuery, Threshold: extremelyHighThreshold.Seconds()}, throttlerEnabledTimeout) + throttler.WaitForThrottlerStatusEnabled(t, &clusterInstance.VtctldClientProcess, &tablet, true, &throttler.Config{Query: throttler.DefaultQuery, Threshold: extremelyHighThreshold.Seconds()}, throttlerEnabledTimeout) } }) t.Run("validating OK response from throttler with high threshold", func(t *testing.T) { waitForThrottleCheckStatus(t, primaryTablet, http.StatusOK) }) t.Run("setting low threshold", func(t *testing.T) { - _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, false, false, throttler.DefaultThreshold.Seconds(), useDefaultQuery, nil) + req := &vtctldatapb.UpdateThrottlerConfigRequest{Threshold: throttler.DefaultThreshold.Seconds()} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, nil, nil) assert.NoError(t, err) // Wait for the throttler to be enabled everywhere with new config. for _, tablet := range clusterInstance.Keyspaces[0].Shards[0].Vttablets { - throttler.WaitForThrottlerStatusEnabled(t, tablet, true, throttler.DefaultConfig, throttlerEnabledTimeout) + throttler.WaitForThrottlerStatusEnabled(t, &clusterInstance.VtctldClientProcess, tablet, true, throttler.DefaultConfig, throttlerEnabledTimeout) } }) t.Run("validating pushback response from throttler on low threshold", func(t *testing.T) { @@ -329,8 +338,12 @@ func TestInitialThrottler(t *testing.T) { cluster.ValidateReplicationIsHealthy(t, replicaTablet) resp, err := throttleCheck(primaryTablet, false) require.NoError(t, err) - defer resp.Body.Close() - if !assert.Equalf(t, http.StatusOK, resp.StatusCode, "Unexpected response from throttler: %s", getResponseBody(resp)) { + require.NotNil(t, resp) + for _, metrics := range resp.Check.Metrics { + assert.Equal(t, base.ShardScope.String(), metrics.Scope) + } + + if !assert.EqualValues(t, http.StatusOK, resp.Check.StatusCode, "Unexpected response from throttler: %+v", resp) { rs, err := replicaTablet.VttabletProcess.QueryTablet("show replica status", keyspaceName, false) assert.NoError(t, err) t.Logf("Seconds_Behind_Source: %s", rs.Named().Row()["Seconds_Behind_Source"].ToString()) @@ -344,8 +357,11 @@ func TestInitialThrottler(t *testing.T) { cluster.ValidateReplicationIsHealthy(t, replicaTablet) resp, err := throttleCheck(primaryTablet, false) require.NoError(t, err) - defer resp.Body.Close() - if !assert.Equalf(t, http.StatusOK, resp.StatusCode, "Unexpected response from throttler: %s", getResponseBody(resp)) { + require.NotNil(t, resp) + for _, metrics := range resp.Check.Metrics { + assert.Equal(t, base.ShardScope.String(), metrics.Scope) + } + if !assert.EqualValues(t, http.StatusOK, resp.Check.StatusCode, "Unexpected response from throttler: %+v", resp) { rs, err := replicaTablet.VttabletProcess.QueryTablet("show replica status", keyspaceName, false) assert.NoError(t, err) t.Logf("Seconds_Behind_Source: %s", rs.Named().Row()["Seconds_Behind_Source"].ToString()) @@ -373,6 +389,7 @@ func TestThrottleViaApplySchema(t *testing.T) { require.NoError(t, err) require.NotNil(t, keyspace) require.NotNil(t, keyspace.Keyspace.ThrottlerConfig) + require.NotNil(t, keyspace.Keyspace.ThrottlerConfig.ThrottledApps) require.NotEmpty(t, keyspace.Keyspace.ThrottlerConfig.ThrottledApps, "throttler config: %+v", keyspace.Keyspace.ThrottlerConfig) appRule, ok := keyspace.Keyspace.ThrottlerConfig.ThrottledApps[throttlerapp.OnlineDDLName.String()] require.True(t, ok, "throttled apps: %v", keyspace.Keyspace.ThrottlerConfig.ThrottledApps) @@ -394,14 +411,10 @@ func TestThrottleViaApplySchema(t *testing.T) { require.NoError(t, err) require.NotNil(t, keyspace) require.NotNil(t, keyspace.Keyspace.ThrottlerConfig) - require.NotEmpty(t, keyspace.Keyspace.ThrottlerConfig.ThrottledApps, "throttler config: %+v", keyspace.Keyspace.ThrottlerConfig) + require.NotNil(t, keyspace.Keyspace.ThrottlerConfig.ThrottledApps) + // ThrottledApps will actually be empty at this point, but more specifically we want to see that "online-ddl" is not there. appRule, ok := keyspace.Keyspace.ThrottlerConfig.ThrottledApps[throttlerapp.OnlineDDLName.String()] - require.True(t, ok, "throttled apps: %v", keyspace.Keyspace.ThrottlerConfig.ThrottledApps) - require.NotNil(t, appRule) - assert.Equal(t, throttlerapp.OnlineDDLName.String(), appRule.Name) - assert.EqualValues(t, 1.0, appRule.Ratio) - expireAt := time.Unix(appRule.ExpiresAt.Seconds, int64(appRule.ExpiresAt.Nanoseconds)) - assert.True(t, expireAt.Before(time.Now()), "expected rule to have expired, but it has not: %v", expireAt) + assert.True(t, ok, "app rule: %v", appRule) }) } @@ -418,19 +431,17 @@ func TestThrottlerAfterMetricsCollected(t *testing.T) { require.NoError(t, err) defer resp.Body.Close() assert.Equalf(t, http.StatusOK, resp.StatusCode, "Unexpected response from throttler: %s", getResponseBody(resp)) - assert.Contains(t, body, "always-throttled-app") + assert.Contains(t, body, throttlerapp.TestingAlwaysThrottlerName) }) t.Run("validating primary check self", func(t *testing.T) { resp, err := throttleCheckSelf(primaryTablet) require.NoError(t, err) - defer resp.Body.Close() - assert.Equalf(t, http.StatusOK, resp.StatusCode, "Unexpected response from throttler: %s", getResponseBody(resp)) + assert.EqualValues(t, http.StatusOK, resp.Check.StatusCode, "Unexpected response from throttler: %+v", resp) }) t.Run("validating replica check self", func(t *testing.T) { resp, err := throttleCheckSelf(replicaTablet) require.NoError(t, err) - defer resp.Body.Close() - assert.Equalf(t, http.StatusOK, resp.StatusCode, "Unexpected response from throttler: %s", getResponseBody(resp)) + assert.EqualValues(t, http.StatusOK, resp.Check.StatusCode, "Unexpected response from throttler: %+v", resp) }) } @@ -457,15 +468,17 @@ func TestLag(t *testing.T) { t.Run("expecting throttler push back", func(t *testing.T) { resp, err := throttleCheck(primaryTablet, false) require.NoError(t, err) - defer resp.Body.Close() - assert.Equalf(t, http.StatusTooManyRequests, resp.StatusCode, "Unexpected response from throttler: %s", getResponseBody(resp)) + assert.EqualValues(t, http.StatusTooManyRequests, resp.Check.StatusCode, "Unexpected response from throttler: %+v", resp) }) t.Run("primary self-check should still be fine", func(t *testing.T) { resp, err := throttleCheckSelf(primaryTablet) require.NoError(t, err) - defer resp.Body.Close() + require.NotNil(t, resp) + for _, metrics := range resp.Check.Metrics { + assert.Equal(t, base.SelfScope.String(), metrics.Scope) + } // self (on primary) is unaffected by replication lag - if !assert.Equalf(t, http.StatusOK, resp.StatusCode, "Unexpected response from throttler: %s", getResponseBody(resp)) { + if !assert.EqualValues(t, http.StatusOK, resp.Check.StatusCode, "Unexpected response from throttler: %+v", resp) { t.Logf("throttler primary status: %+v", throttleStatus(t, primaryTablet)) t.Logf("throttler replica status: %+v", throttleStatus(t, replicaTablet)) } @@ -473,25 +486,72 @@ func TestLag(t *testing.T) { t.Run("replica self-check should show error", func(t *testing.T) { resp, err := throttleCheckSelf(replicaTablet) require.NoError(t, err) - defer resp.Body.Close() - assert.Equalf(t, http.StatusTooManyRequests, resp.StatusCode, "Unexpected response from throttler: %s", getResponseBody(resp)) + require.NotNil(t, resp) + for _, metrics := range resp.Check.Metrics { + assert.Equal(t, base.SelfScope.String(), metrics.Scope) + } + assert.EqualValues(t, http.StatusTooManyRequests, resp.Check.StatusCode, "Unexpected response from throttler: %+v", resp) }) t.Run("exempting test app", func(t *testing.T) { appRule := &topodatapb.ThrottledAppRule{ - Name: testAppName, + Name: testAppName.String(), ExpiresAt: protoutil.TimeToProto(time.Now().Add(time.Hour)), Exempt: true, } - _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, false, false, throttler.DefaultThreshold.Seconds(), useDefaultQuery, appRule) + req := &vtctldatapb.UpdateThrottlerConfigRequest{Threshold: throttler.DefaultThreshold.Seconds()} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, appRule, nil) assert.NoError(t, err) waitForThrottleCheckStatus(t, primaryTablet, http.StatusOK) }) t.Run("unexempting test app", func(t *testing.T) { appRule := &topodatapb.ThrottledAppRule{ - Name: testAppName, + Name: testAppName.String(), + ExpiresAt: protoutil.TimeToProto(time.Now()), + } + req := &vtctldatapb.UpdateThrottlerConfigRequest{Threshold: throttler.DefaultThreshold.Seconds()} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, appRule, nil) + assert.NoError(t, err) + waitForThrottleCheckStatus(t, primaryTablet, http.StatusTooManyRequests) + }) + t.Run("exempting all apps", func(t *testing.T) { + appRule := &topodatapb.ThrottledAppRule{ + Name: throttlerapp.AllName.String(), + ExpiresAt: protoutil.TimeToProto(time.Now().Add(time.Hour)), + Exempt: true, + } + req := &vtctldatapb.UpdateThrottlerConfigRequest{Threshold: throttler.DefaultThreshold.Seconds()} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, appRule, nil) + assert.NoError(t, err) + waitForThrottleCheckStatus(t, primaryTablet, http.StatusOK) + }) + t.Run("throttling test app", func(t *testing.T) { + appRule := &topodatapb.ThrottledAppRule{ + Name: testAppName.String(), + Ratio: throttle.DefaultThrottleRatio, + ExpiresAt: protoutil.TimeToProto(time.Now().Add(time.Hour)), + } + req := &vtctldatapb.UpdateThrottlerConfigRequest{Threshold: throttler.DefaultThreshold.Seconds()} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, appRule, nil) + assert.NoError(t, err) + waitForThrottleCheckStatus(t, primaryTablet, http.StatusExpectationFailed) + }) + t.Run("unthrottling test app", func(t *testing.T) { + appRule := &topodatapb.ThrottledAppRule{ + Name: testAppName.String(), ExpiresAt: protoutil.TimeToProto(time.Now()), } - _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, false, false, throttler.DefaultThreshold.Seconds(), useDefaultQuery, appRule) + req := &vtctldatapb.UpdateThrottlerConfigRequest{Threshold: throttler.DefaultThreshold.Seconds()} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, appRule, nil) + assert.NoError(t, err) + waitForThrottleCheckStatus(t, primaryTablet, http.StatusOK) + }) + t.Run("unexempting all apps", func(t *testing.T) { + appRule := &topodatapb.ThrottledAppRule{ + Name: throttlerapp.AllName.String(), + ExpiresAt: protoutil.TimeToProto(time.Now()), + } + req := &vtctldatapb.UpdateThrottlerConfigRequest{Threshold: throttler.DefaultThreshold.Seconds()} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, appRule, nil) assert.NoError(t, err) waitForThrottleCheckStatus(t, primaryTablet, http.StatusTooManyRequests) }) @@ -506,15 +566,13 @@ func TestLag(t *testing.T) { t.Run("primary self-check should be fine", func(t *testing.T) { resp, err := throttleCheckSelf(primaryTablet) require.NoError(t, err) - defer resp.Body.Close() // self (on primary) is unaffected by replication lag - assert.Equalf(t, http.StatusOK, resp.StatusCode, "Unexpected response from throttler: %s", getResponseBody(resp)) + assert.EqualValues(t, http.StatusOK, resp.Check.StatusCode, "Unexpected response from throttler: %+v", resp) }) t.Run("replica self-check should be fine", func(t *testing.T) { resp, err := throttleCheckSelf(replicaTablet) require.NoError(t, err) - defer resp.Body.Close() - assert.Equalf(t, http.StatusOK, resp.StatusCode, "Unexpected response from throttler: %s", getResponseBody(resp)) + assert.EqualValues(t, http.StatusOK, resp.Check.StatusCode, "Unexpected response from throttler: %+v", resp) }) } @@ -540,7 +598,8 @@ func TestCustomQuery(t *testing.T) { defer cluster.PanicHandler(t) t.Run("enabling throttler with custom query and threshold", func(t *testing.T) { - _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, true, false, customThreshold, customQuery, nil) + req := &vtctldatapb.UpdateThrottlerConfigRequest{Enable: true, Threshold: customThreshold, CustomQuery: customQuery} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, nil, nil) assert.NoError(t, err) // Wait for the throttler to be enabled everywhere with new custom config. @@ -548,7 +607,7 @@ func TestCustomQuery(t *testing.T) { for _, ks := range clusterInstance.Keyspaces { for _, shard := range ks.Shards { for _, tablet := range shard.Vttablets { - throttler.WaitForThrottlerStatusEnabled(t, tablet, true, expectConfig, throttlerEnabledTimeout) + throttler.WaitForThrottlerStatusEnabled(t, &clusterInstance.VtctldClientProcess, tablet, true, expectConfig, throttlerEnabledTimeout) } } } @@ -557,8 +616,7 @@ func TestCustomQuery(t *testing.T) { throttler.WaitForValidData(t, primaryTablet, throttlerEnabledTimeout) resp, err := throttleCheck(primaryTablet, false) require.NoError(t, err) - defer resp.Body.Close() - assert.Equalf(t, http.StatusOK, resp.StatusCode, "Unexpected response from throttler: %s", getResponseBody(resp)) + assert.EqualValues(t, http.StatusOK, resp.Check.StatusCode, "Unexpected response from throttler: %+v", resp) }) t.Run("test threads running", func(t *testing.T) { sleepDuration := 20 * time.Second @@ -584,8 +642,7 @@ func TestCustomQuery(t *testing.T) { { resp, err := throttleCheckSelf(primaryTablet) require.NoError(t, err) - defer resp.Body.Close() - assert.Equalf(t, http.StatusTooManyRequests, resp.StatusCode, "Unexpected response from throttler: %s", getResponseBody(resp)) + assert.EqualValues(t, http.StatusTooManyRequests, resp.Check.StatusCode, "Unexpected response from throttler: %+v", resp) } }) t.Run("wait for queries to terminate", func(t *testing.T) { @@ -596,8 +653,7 @@ func TestCustomQuery(t *testing.T) { { resp, err := throttleCheckSelf(primaryTablet) require.NoError(t, err) - defer resp.Body.Close() - assert.Equalf(t, http.StatusOK, resp.StatusCode, "Unexpected response from throttler: %s", getResponseBody(resp)) + assert.EqualValues(t, http.StatusOK, resp.Check.StatusCode, "Unexpected response from throttler: %+v", resp) } }) }) @@ -608,22 +664,169 @@ func TestRestoreDefaultQuery(t *testing.T) { // Validate going back from custom-query to default-query (replication lag) still works. t.Run("enabling throttler with default query and threshold", func(t *testing.T) { - _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, true, false, throttler.DefaultThreshold.Seconds(), useDefaultQuery, nil) + req := &vtctldatapb.UpdateThrottlerConfigRequest{Enable: true, Threshold: throttler.DefaultThreshold.Seconds()} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, nil, nil) assert.NoError(t, err) // Wait for the throttler to be up and running everywhere again with the default config. for _, tablet := range clusterInstance.Keyspaces[0].Shards[0].Vttablets { - throttler.WaitForThrottlerStatusEnabled(t, tablet, true, throttler.DefaultConfig, throttlerEnabledTimeout) + throttler.WaitForThrottlerStatusEnabled(t, &clusterInstance.VtctldClientProcess, tablet, true, throttler.DefaultConfig, throttlerEnabledTimeout) } }) t.Run("validating OK response from throttler with default threshold, heartbeats running", func(t *testing.T) { resp, err := throttleCheck(primaryTablet, false) require.NoError(t, err) - defer resp.Body.Close() - assert.Equalf(t, http.StatusOK, resp.StatusCode, "Unexpected response from throttler: %s", getResponseBody(resp)) + assert.EqualValues(t, http.StatusOK, resp.Check.StatusCode, "Unexpected response from throttler: %+v", resp) }) t.Run("validating pushback response from throttler on default threshold once heartbeats go stale", func(t *testing.T) { time.Sleep(2 * onDemandHeartbeatDuration) // just... really wait long enough, make sure on-demand stops waitForThrottleCheckStatus(t, primaryTablet, http.StatusTooManyRequests) }) } + +func TestUpdateMetricThresholds(t *testing.T) { + t.Run("validating pushback from throttler", func(t *testing.T) { + req := &vtctldatapb.UpdateThrottlerConfigRequest{Threshold: throttler.DefaultThreshold.Seconds()} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, nil, nil) + assert.NoError(t, err) + // Wait for the throttler to be enabled everywhere with new config. + for _, tablet := range []cluster.Vttablet{*primaryTablet, *replicaTablet} { + throttler.WaitForThrottlerStatusEnabled(t, &clusterInstance.VtctldClientProcess, &tablet, true, &throttler.Config{Query: throttler.DefaultQuery, Threshold: throttler.DefaultThreshold.Seconds()}, throttlerEnabledTimeout) + } + waitForThrottleCheckStatus(t, primaryTablet, http.StatusTooManyRequests) + }) + t.Run("setting low general threshold, and high threshold for 'lag' metric", func(t *testing.T) { + { + req := &vtctldatapb.UpdateThrottlerConfigRequest{MetricName: "lag", Threshold: extremelyHighThreshold.Seconds()} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, nil, nil) + assert.NoError(t, err) + } + { + req := &vtctldatapb.UpdateThrottlerConfigRequest{Threshold: unreasonablyLowThreshold.Seconds()} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, nil, nil) + assert.NoError(t, err) + } + // Wait for the throttler to be enabled everywhere with new config. + for _, tablet := range []cluster.Vttablet{*primaryTablet, *replicaTablet} { + throttler.WaitForThrottlerStatusEnabled(t, &clusterInstance.VtctldClientProcess, &tablet, true, &throttler.Config{Query: throttler.DefaultQuery, Threshold: unreasonablyLowThreshold.Seconds()}, throttlerEnabledTimeout) + } + }) + t.Run("validating OK response from throttler thanks to high 'lag' threshold", func(t *testing.T) { + // Note that the default threshold is extremely low, but gets overriden. + waitForThrottleCheckStatus(t, primaryTablet, http.StatusOK) + }) + t.Run("removing explicit 'lag' threshold", func(t *testing.T) { + req := &vtctldatapb.UpdateThrottlerConfigRequest{MetricName: "lag", Threshold: 0} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, nil, nil) + assert.NoError(t, err) + }) + t.Run("validating pushback from throttler again", func(t *testing.T) { + waitForThrottleCheckStatus(t, primaryTablet, http.StatusTooManyRequests) + }) + t.Run("restoring standard threshold", func(t *testing.T) { + req := &vtctldatapb.UpdateThrottlerConfigRequest{Threshold: throttler.DefaultThreshold.Seconds()} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, nil, nil) + assert.NoError(t, err) + // Wait for the throttler to be enabled everywhere with new config. + for _, tablet := range []cluster.Vttablet{*primaryTablet, *replicaTablet} { + throttler.WaitForThrottlerStatusEnabled(t, &clusterInstance.VtctldClientProcess, &tablet, true, &throttler.Config{Query: throttler.DefaultQuery, Threshold: throttler.DefaultThreshold.Seconds()}, throttlerEnabledTimeout) + } + waitForThrottleCheckStatus(t, primaryTablet, http.StatusTooManyRequests) + }) +} + +func TestUpdateAppCheckedMetrics(t *testing.T) { + t.Run("ensure replica is not dormant", func(t *testing.T) { + _, err := throttleCheck(replicaTablet, false) + require.NoError(t, err) + }) + t.Run("validating pushback from throttler", func(t *testing.T) { + req := &vtctldatapb.UpdateThrottlerConfigRequest{Threshold: throttler.DefaultThreshold.Seconds()} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, nil, nil) + assert.NoError(t, err) + // Wait for the throttler to be enabled everywhere with new config. + for _, tablet := range []cluster.Vttablet{*primaryTablet, *replicaTablet} { + throttler.WaitForThrottlerStatusEnabled(t, &clusterInstance.VtctldClientProcess, &tablet, true, &throttler.Config{Query: throttler.DefaultQuery, Threshold: throttler.DefaultThreshold.Seconds()}, throttlerEnabledTimeout) + } + waitForThrottleCheckStatus(t, primaryTablet, http.StatusTooManyRequests) + }) + t.Run("assigning 'loadavg' metrics to 'test' app", func(t *testing.T) { + { + req := &vtctldatapb.UpdateThrottlerConfigRequest{MetricName: "loadavg", Threshold: 7777} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, nil, nil) + assert.NoError(t, err) + } + { + req := &vtctldatapb.UpdateThrottlerConfigRequest{} + appCheckedMetrics := map[string]*topodatapb.ThrottlerConfig_MetricNames{ + testAppName.String(): {Names: []string{"loadavg"}}, + } + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, nil, appCheckedMetrics) + assert.NoError(t, err) + } + { + req := &vtctldatapb.UpdateThrottlerConfigRequest{Threshold: unreasonablyLowThreshold.Seconds()} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, nil, nil) + assert.NoError(t, err) + } + // Wait for the throttler to be enabled everywhere with new config. + for _, tablet := range []cluster.Vttablet{*primaryTablet, *replicaTablet} { + throttler.WaitForThrottlerStatusEnabled(t, &clusterInstance.VtctldClientProcess, &tablet, true, &throttler.Config{Query: throttler.DefaultQuery, Threshold: unreasonablyLowThreshold.Seconds()}, throttlerEnabledTimeout) + } + t.Run("validating OK response from throttler since it's checking loadavg", func(t *testing.T) { + if !waitForThrottleCheckStatus(t, primaryTablet, http.StatusOK) { + t.Logf("throttler primary status: %+v", throttleStatus(t, primaryTablet)) + t.Logf("throttler replica status: %+v", throttleStatus(t, replicaTablet)) + } + }) + }) + t.Run("assigning 'loadavg,lag' metrics to 'test' app", func(t *testing.T) { + { + req := &vtctldatapb.UpdateThrottlerConfigRequest{} + appCheckedMetrics := map[string]*topodatapb.ThrottlerConfig_MetricNames{ + testAppName.String(): {Names: []string{"loadavg,lag"}}, + } + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, nil, appCheckedMetrics) + assert.NoError(t, err) + } + { + req := &vtctldatapb.UpdateThrottlerConfigRequest{Threshold: unreasonablyLowThreshold.Seconds()} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, nil, nil) + assert.NoError(t, err) + } + // Wait for the throttler to be enabled everywhere with new config. + for _, tablet := range []cluster.Vttablet{*primaryTablet, *replicaTablet} { + throttler.WaitForThrottlerStatusEnabled(t, &clusterInstance.VtctldClientProcess, &tablet, true, &throttler.Config{Query: throttler.DefaultQuery, Threshold: unreasonablyLowThreshold.Seconds()}, throttlerEnabledTimeout) + } + t.Run("validating pushback from throttler since lag is above threshold", func(t *testing.T) { + waitForThrottleCheckStatus(t, primaryTablet, http.StatusTooManyRequests) + }) + }) + t.Run("removing assignment from 'test' app and restoring defaults", func(t *testing.T) { + { + req := &vtctldatapb.UpdateThrottlerConfigRequest{MetricName: "loadavg", Threshold: 0} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, nil, nil) + assert.NoError(t, err) + } + { + req := &vtctldatapb.UpdateThrottlerConfigRequest{} + appCheckedMetrics := map[string]*topodatapb.ThrottlerConfig_MetricNames{ + testAppName.String(): {Names: []string{}}, + } + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, nil, appCheckedMetrics) + assert.NoError(t, err) + } + { + req := &vtctldatapb.UpdateThrottlerConfigRequest{Threshold: throttler.DefaultThreshold.Seconds()} + _, err := throttler.UpdateThrottlerTopoConfig(clusterInstance, req, nil, nil) + assert.NoError(t, err) + } + // Wait for the throttler to be enabled everywhere with new config. + for _, tablet := range []cluster.Vttablet{*primaryTablet, *replicaTablet} { + throttler.WaitForThrottlerStatusEnabled(t, &clusterInstance.VtctldClientProcess, &tablet, true, &throttler.Config{Query: throttler.DefaultQuery, Threshold: throttler.DefaultThreshold.Seconds()}, throttlerEnabledTimeout) + } + t.Run("validating error response from throttler since lag is still high", func(t *testing.T) { + waitForThrottleCheckStatus(t, primaryTablet, http.StatusTooManyRequests) + }) + }) +} diff --git a/go/test/endtoend/throttler/util.go b/go/test/endtoend/throttler/util.go index 602f8622a3b..fccad19c324 100644 --- a/go/test/endtoend/throttler/util.go +++ b/go/test/endtoend/throttler/util.go @@ -29,15 +29,19 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tidwall/gjson" + "google.golang.org/protobuf/encoding/protojson" "vitess.io/vitess/go/protoutil" "vitess.io/vitess/go/test/endtoend/cluster" "vitess.io/vitess/go/vt/concurrency" "vitess.io/vitess/go/vt/log" + "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/throttlerapp" + tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" topodatapb "vitess.io/vitess/go/vt/proto/topodata" + vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" ) type Config struct { @@ -56,24 +60,71 @@ var DefaultConfig = &Config{ Threshold: DefaultThreshold.Seconds(), } +// CheckThrottlerRaw runs vtctldclient CheckThrottler +func CheckThrottlerRaw(vtctldProcess *cluster.VtctldClientProcess, tablet *cluster.Vttablet, appName throttlerapp.Name, flags *throttle.CheckFlags) (result string, err error) { + args := []string{} + args = append(args, "CheckThrottler") + if flags == nil { + flags = &throttle.CheckFlags{ + Scope: base.SelfScope, + MultiMetricsEnabled: true, + } + } + if appName != "" { + args = append(args, "--app-name", appName.String()) + } + if flags.Scope != base.UndefinedScope { + args = append(args, "--scope", flags.Scope.String()) + } + if flags.OKIfNotExists { + args = append(args, "--ok-if-not-exists") + } + if !flags.SkipRequestHeartbeats { + args = append(args, "--request-heartbeats") + } + args = append(args, tablet.Alias) + + result, err = vtctldProcess.ExecuteCommandWithOutput(args...) + return result, err +} + +// GetThrottlerStatusRaw runs vtctldclient GetThrottlerStatus +func GetThrottlerStatusRaw(vtctldProcess *cluster.VtctldClientProcess, tablet *cluster.Vttablet) (result string, err error) { + args := []string{} + args = append(args, "GetThrottlerStatus") + args = append(args, tablet.Alias) + + result, err = vtctldProcess.ExecuteCommandWithOutput(args...) + return result, err +} + // UpdateThrottlerTopoConfig runs vtctlclient UpdateThrottlerConfig. // This retries the command until it succeeds or times out as the // SrvKeyspace record may not yet exist for a newly created // Keyspace that is still initializing before it becomes serving. -func UpdateThrottlerTopoConfigRaw(vtctldProcess *cluster.VtctldClientProcess, keyspaceName string, enable bool, disable bool, threshold float64, metricsQuery string, appRule *topodatapb.ThrottledAppRule) (result string, err error) { +func UpdateThrottlerTopoConfigRaw( + vtctldProcess *cluster.VtctldClientProcess, + keyspaceName string, + opts *vtctldatapb.UpdateThrottlerConfigRequest, + appRule *topodatapb.ThrottledAppRule, + appCheckedMetrics map[string]*topodatapb.ThrottlerConfig_MetricNames, +) (result string, err error) { args := []string{} args = append(args, "UpdateThrottlerConfig") - if enable { + if opts.Enable { args = append(args, "--enable") } - if disable { + if opts.Disable { args = append(args, "--disable") } - if threshold > 0 { - args = append(args, "--threshold", fmt.Sprintf("%f", threshold)) + if opts.MetricName != "" { + args = append(args, "--metric-name", opts.MetricName) } - args = append(args, "--custom-query", metricsQuery) - if metricsQuery != "" { + if opts.Threshold > 0 || opts.MetricName != "" { + args = append(args, "--threshold", fmt.Sprintf("%f", opts.Threshold)) + } + args = append(args, "--custom-query", opts.CustomQuery) + if opts.CustomQuery != "" { args = append(args, "--check-as-check-self") } else { args = append(args, "--check-as-check-shard") @@ -86,6 +137,15 @@ func UpdateThrottlerTopoConfigRaw(vtctldProcess *cluster.VtctldClientProcess, ke args = append(args, "--throttle-app-exempt") } } + if appCheckedMetrics != nil { + if len(appCheckedMetrics) != 1 { + return "", fmt.Errorf("appCheckedMetrics must either be nil or have exactly one entry") + } + for app, metrics := range appCheckedMetrics { + args = append(args, "--app-name", app) + args = append(args, "--app-metrics", strings.Join(metrics.Names, ",")) + } + } args = append(args, keyspaceName) ctx, cancel := context.WithTimeout(context.Background(), ConfigTimeout) @@ -107,18 +167,74 @@ func UpdateThrottlerTopoConfigRaw(vtctldProcess *cluster.VtctldClientProcess, ke } } +// CheckThrottler runs vtctldclient CheckThrottler. +func CheckThrottler(clusterInstance *cluster.LocalProcessCluster, tablet *cluster.Vttablet, appName throttlerapp.Name, flags *throttle.CheckFlags) (*vtctldatapb.CheckThrottlerResponse, error) { + output, err := CheckThrottlerRaw(&clusterInstance.VtctldClientProcess, tablet, appName, flags) + if err != nil { + return nil, err + } + var resp vtctldatapb.CheckThrottlerResponse + if err := protojson.Unmarshal([]byte(output), &resp); err != nil { + return nil, err + } + return &resp, err +} + +// GetThrottlerStatus runs vtctldclient CheckThrottler. +func GetThrottlerStatus(vtctldProcess *cluster.VtctldClientProcess, tablet *cluster.Vttablet) (*tabletmanagerdatapb.GetThrottlerStatusResponse, error) { + output, err := GetThrottlerStatusRaw(vtctldProcess, tablet) + if err != nil && strings.HasSuffix(tablet.VttabletProcess.Binary, "-last") { + // TODO(shlomi): Remove in v22! + // GetThrottlerStatus gRPC was added in v21. Upgrade-downgrade tests which run a + // v20 tablet for cross-version compatibility check will fail this command because the + // tablet server will not serve this gRPC call. + // We therefore resort to checking the /throttler/status endpoint + throttlerURL := fmt.Sprintf("http://localhost:%d/throttler/status", tablet.HTTPPort) + throttlerBody := getHTTPBody(throttlerURL) + if throttlerBody == "" { + return nil, fmt.Errorf("failed to get throttler status from %s. Empty result via /status endpoint, and GetThrottlerStatus error: %v", tablet.Alias, err) + } + resp := vtctldatapb.GetThrottlerStatusResponse{ + Status: &tabletmanagerdatapb.GetThrottlerStatusResponse{}, + } + resp.Status.IsEnabled = gjson.Get(throttlerBody, "IsEnabled").Bool() + resp.Status.LagMetricQuery = gjson.Get(throttlerBody, "Query").String() + resp.Status.DefaultThreshold = gjson.Get(throttlerBody, "Threshold").Float() + resp.Status.MetricsHealth = make(map[string]*tabletmanagerdatapb.GetThrottlerStatusResponse_MetricHealth) + gjson.Get(throttlerBody, "MetricsHealth").ForEach(func(key, value gjson.Result) bool { + // We just need to know that metrics health is non-empty. We don't need to parse the actual values. + resp.Status.MetricsHealth[key.String()] = &tabletmanagerdatapb.GetThrottlerStatusResponse_MetricHealth{} + return true + }) + return resp.Status, nil + } + if err != nil { + return nil, err + } + var resp vtctldatapb.GetThrottlerStatusResponse + if err := protojson.Unmarshal([]byte(output), &resp); err != nil { + return nil, err + } + return resp.Status, err +} + // UpdateThrottlerTopoConfig runs vtctlclient UpdateThrottlerConfig. // This retries the command until it succeeds or times out as the // SrvKeyspace record may not yet exist for a newly created // Keyspace that is still initializing before it becomes serving. -func UpdateThrottlerTopoConfig(clusterInstance *cluster.LocalProcessCluster, enable bool, disable bool, threshold float64, metricsQuery string, appRule *topodatapb.ThrottledAppRule) (string, error) { +func UpdateThrottlerTopoConfig( + clusterInstance *cluster.LocalProcessCluster, + opts *vtctldatapb.UpdateThrottlerConfigRequest, + appRule *topodatapb.ThrottledAppRule, + appCheckedMetrics map[string]*topodatapb.ThrottlerConfig_MetricNames, +) (string, error) { rec := concurrency.AllErrorRecorder{} var ( err error res strings.Builder ) for _, ks := range clusterInstance.Keyspaces { - ires, err := UpdateThrottlerTopoConfigRaw(&clusterInstance.VtctldClientProcess, ks.Name, enable, disable, threshold, metricsQuery, appRule) + ires, err := UpdateThrottlerTopoConfigRaw(&clusterInstance.VtctldClientProcess, ks.Name, opts, appRule, appCheckedMetrics) if err != nil { rec.RecordError(err) } @@ -252,30 +368,15 @@ func UnthrottleAppAndWaitUntilTabletsConfirm(t *testing.T, clusterInstance *clus // WaitForThrottlerStatusEnabled waits for a tablet to report its throttler status as // enabled/disabled and have the provided config (if any) until the specified timeout. -func WaitForThrottlerStatusEnabled(t *testing.T, tablet *cluster.Vttablet, enabled bool, config *Config, timeout time.Duration) { - enabledJSONPath := "IsEnabled" - queryJSONPath := "Query" - thresholdJSONPath := "Threshold" - throttlerURL := fmt.Sprintf("http://localhost:%d/throttler/status", tablet.HTTPPort) - tabletURL := fmt.Sprintf("http://localhost:%d/debug/status_details", tablet.HTTPPort) +func WaitForThrottlerStatusEnabled(t *testing.T, vtctldProcess *cluster.VtctldClientProcess, tablet *cluster.Vttablet, enabled bool, config *Config, timeout time.Duration) { ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() ticker := time.NewTicker(time.Second) defer ticker.Stop() + tabletURL := fmt.Sprintf("http://localhost:%d/debug/status_details", tablet.HTTPPort) + for { - throttlerBody := getHTTPBody(throttlerURL) - isEnabled := gjson.Get(throttlerBody, enabledJSONPath).Bool() - if isEnabled == enabled { - if config == nil { - return - } - query := gjson.Get(throttlerBody, queryJSONPath).String() - threshold := gjson.Get(throttlerBody, thresholdJSONPath).Float() - if query == config.Query && threshold == config.Threshold { - return - } - } // If the tablet is Not Serving due to e.g. being involved in a // Reshard where its QueryService is explicitly disabled, then // we should not fail the test as the throttler will not be Open. @@ -286,10 +387,35 @@ func WaitForThrottlerStatusEnabled(t *testing.T, tablet *cluster.Vttablet, enabl log.Infof("tablet %s is Not Serving, so ignoring throttler status as the throttler will not be Opened", tablet.Alias) return } + + status, err := GetThrottlerStatus(vtctldProcess, tablet) + good := func() bool { + if err != nil { + log.Errorf("GetThrottlerStatus failed: %v", err) + return false + } + if status.IsEnabled != enabled { + return false + } + if status.IsEnabled && len(status.MetricsHealth) == 0 { + // throttler is enabled, but no metrics collected yet. Wait for something to be collected. + return false + } + if config == nil { + return true + } + if status.LagMetricQuery == config.Query && status.DefaultThreshold == config.Threshold { + return true + } + return false + } + if good() { + return + } select { case <-ctx.Done(): - t.Errorf("timed out waiting for the %s tablet's throttler status enabled to be %t with the correct config after %v; last seen value: %s", - tablet.Alias, enabled, timeout, throttlerBody) + assert.Fail(t, "timeout", "waiting for the %s tablet's throttler status enabled to be %t with the correct config after %v; last seen status: %+v", + tablet.Alias, enabled, timeout, status) return case <-ticker.C: } @@ -334,7 +460,7 @@ func WaitForThrottledApp(t *testing.T, tablet *cluster.Vttablet, throttlerApp th } select { case <-ctx.Done(): - t.Errorf("timed out waiting for the %s tablet's throttled apps with the correct config (expecting %s to be %v) after %v; last seen value: %s", + assert.Fail(t, "timeout", "waiting for the %s tablet's throttled apps with the correct config (expecting %s to be %v) after %v; last seen value: %s", tablet.Alias, throttlerApp.String(), expectThrottled, timeout, throttledAppsBody) return case <-ticker.C: @@ -345,19 +471,39 @@ func WaitForThrottledApp(t *testing.T, tablet *cluster.Vttablet, throttlerApp th // EnableLagThrottlerAndWaitForStatus is a utility function to enable the throttler at the beginning of an endtoend test. // The throttler is configued to use the standard replication lag metric. The function waits until the throttler is confirmed // to be running on all tablets. -func EnableLagThrottlerAndWaitForStatus(t *testing.T, clusterInstance *cluster.LocalProcessCluster, lag time.Duration) { - _, err := UpdateThrottlerTopoConfig(clusterInstance, true, false, lag.Seconds(), "", nil) +func EnableLagThrottlerAndWaitForStatus(t *testing.T, clusterInstance *cluster.LocalProcessCluster) { + req := &vtctldatapb.UpdateThrottlerConfigRequest{Enable: true} + _, err := UpdateThrottlerTopoConfig(clusterInstance, req, nil, nil) require.NoError(t, err) for _, ks := range clusterInstance.Keyspaces { for _, shard := range ks.Shards { for _, tablet := range shard.Vttablets { - WaitForThrottlerStatusEnabled(t, tablet, true, nil, time.Minute) + WaitForThrottlerStatusEnabled(t, &clusterInstance.VtctldClientProcess, tablet, true, nil, time.Minute) } } } } +func WaitForCheckThrottlerResult(t *testing.T, clusterInstance *cluster.LocalProcessCluster, tablet *cluster.Vttablet, appName throttlerapp.Name, flags *throttle.CheckFlags, expect int32, timeout time.Duration) (*vtctldatapb.CheckThrottlerResponse, error) { + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + ticker := time.NewTicker(time.Second) + defer ticker.Stop() + for { + resp, err := CheckThrottler(clusterInstance, tablet, appName, flags) + require.NoError(t, err) + if resp.Check.StatusCode == expect { + return resp, nil + } + select { + case <-ctx.Done(): + return nil, fmt.Errorf("timed out waiting for %s tablet's throttler to return a valid result after %v", tablet.Alias, timeout) + case <-ticker.C: + } + } +} + func getHTTPBody(url string) string { resp, err := http.Get(url) if err != nil { diff --git a/go/test/endtoend/topotest/etcd2/main_test.go b/go/test/endtoend/topotest/etcd2/main_test.go index 747f2721cdc..67b0dbbc8f7 100644 --- a/go/test/endtoend/topotest/etcd2/main_test.go +++ b/go/test/endtoend/topotest/etcd2/main_test.go @@ -19,6 +19,7 @@ package ectd2 import ( "context" "flag" + "fmt" "os" "testing" "time" @@ -201,6 +202,74 @@ func TestKeyspaceLocking(t *testing.T) { topoutils.WaitForBoolValue(t, &secondThreadLockAcquired, true) } +// TestLockingWithTTL tests that locking with the TTL override works as intended. +func TestLockingWithTTL(t *testing.T) { + // Create the topo server connection. + ts, err := topo.OpenServer(*clusterInstance.TopoFlavorString(), clusterInstance.VtctlProcess.TopoGlobalAddress, clusterInstance.VtctlProcess.TopoGlobalRoot) + require.NoError(t, err) + + ctx := context.Background() + + // Acquire a keyspace lock with a short custom TTL. + ttl := 1 * time.Second + ctx, unlock, err := ts.LockKeyspace(ctx, KeyspaceName, "TestLockingWithTTL", topo.WithTTL(ttl)) + require.NoError(t, err) + defer unlock(&err) + + // Check that CheckKeyspaceLocked DOES return an error after waiting more than + // the specified TTL as we should have lost our lock. + time.Sleep(ttl * 2) + err = topo.CheckKeyspaceLocked(ctx, KeyspaceName) + require.Error(t, err) +} + +// TestNamedLocking tests that named locking works as intended. +func TestNamedLocking(t *testing.T) { + // Create topo server connection. + ts, err := topo.OpenServer(*clusterInstance.TopoFlavorString(), clusterInstance.VtctlProcess.TopoGlobalAddress, clusterInstance.VtctlProcess.TopoGlobalRoot) + require.NoError(t, err) + + ctx := context.Background() + lockName := "TestNamedLocking" + action := "Testing" + + // Acquire a named lock. + ctx, unlock, err := ts.LockName(ctx, lockName, action) + require.NoError(t, err) + + // Check that we can't reacquire it from the same context. + _, _, err = ts.LockName(ctx, lockName, action) + require.ErrorContains(t, err, fmt.Sprintf("lock for named %s is already held", lockName)) + + // Check that CheckNameLocked doesn't return an error as we should still be + // holding the lock. + err = topo.CheckNameLocked(ctx, lockName) + require.NoError(t, err) + + // We'll now try to acquire the lock from a different goroutine. + secondCallerAcquired := false + go func() { + _, unlock, err := ts.LockName(context.Background(), lockName, action) + defer unlock(&err) + require.NoError(t, err) + secondCallerAcquired = true + }() + + // Wait for some time and ensure that the second attempt at acquiring the lock + // is blocked. + time.Sleep(100 * time.Millisecond) + require.False(t, secondCallerAcquired) + + // Unlock the name. + unlock(&err) + // Check that we no longer have the named lock. + err = topo.CheckNameLocked(ctx, lockName) + require.ErrorContains(t, err, fmt.Sprintf("named %s is not locked (no lockInfo in map)", lockName)) + + // Wait to see that the second goroutine WAS now able to acquire the named lock. + topoutils.WaitForBoolValue(t, &secondCallerAcquired, true) +} + func execMulti(t *testing.T, conn *mysql.Conn, query string) []*sqltypes.Result { t.Helper() var res []*sqltypes.Result diff --git a/go/test/endtoend/vtgate/transaction/restart/main_test.go b/go/test/endtoend/transaction/restart/main_test.go similarity index 100% rename from go/test/endtoend/vtgate/transaction/restart/main_test.go rename to go/test/endtoend/transaction/restart/main_test.go diff --git a/go/test/endtoend/vtgate/transaction/restart/schema.sql b/go/test/endtoend/transaction/restart/schema.sql similarity index 100% rename from go/test/endtoend/vtgate/transaction/restart/schema.sql rename to go/test/endtoend/transaction/restart/schema.sql diff --git a/go/test/endtoend/vtgate/transaction/rollback/txn_rollback_shutdown_test.go b/go/test/endtoend/transaction/rollback/txn_rollback_shutdown_test.go similarity index 100% rename from go/test/endtoend/vtgate/transaction/rollback/txn_rollback_shutdown_test.go rename to go/test/endtoend/transaction/rollback/txn_rollback_shutdown_test.go diff --git a/go/test/endtoend/vtgate/transaction/schema.sql b/go/test/endtoend/transaction/schema.sql similarity index 100% rename from go/test/endtoend/vtgate/transaction/schema.sql rename to go/test/endtoend/transaction/schema.sql diff --git a/go/test/endtoend/vtgate/transaction/single/main_test.go b/go/test/endtoend/transaction/single/main_test.go similarity index 100% rename from go/test/endtoend/vtgate/transaction/single/main_test.go rename to go/test/endtoend/transaction/single/main_test.go diff --git a/go/test/endtoend/vtgate/transaction/single/schema.sql b/go/test/endtoend/transaction/single/schema.sql similarity index 100% rename from go/test/endtoend/vtgate/transaction/single/schema.sql rename to go/test/endtoend/transaction/single/schema.sql diff --git a/go/test/endtoend/vtgate/transaction/single/vschema.json b/go/test/endtoend/transaction/single/vschema.json similarity index 100% rename from go/test/endtoend/vtgate/transaction/single/vschema.json rename to go/test/endtoend/transaction/single/vschema.json diff --git a/go/test/endtoend/vtgate/transaction/twopc/main_test.go b/go/test/endtoend/transaction/twopc/main_test.go similarity index 90% rename from go/test/endtoend/vtgate/transaction/twopc/main_test.go rename to go/test/endtoend/transaction/twopc/main_test.go index 102235d672a..8ac7cfc1f21 100644 --- a/go/test/endtoend/vtgate/transaction/twopc/main_test.go +++ b/go/test/endtoend/transaction/twopc/main_test.go @@ -75,11 +75,11 @@ func TestMain(m *testing.M) { // Set extra args for twopc clusterInstance.VtGateExtraArgs = append(clusterInstance.VtGateExtraArgs, "--transaction_mode", "TWOPC", + "--grpc_use_effective_callerid", ) clusterInstance.VtTabletExtraArgs = append(clusterInstance.VtTabletExtraArgs, "--twopc_enable", - "--twopc_coordinator_address", fmt.Sprintf("localhost:%d", clusterInstance.VtgateGrpcPort), - "--twopc_abandon_age", "3600", + "--twopc_abandon_age", "1", "--queryserver-config-transaction-cap", "3", ) @@ -90,7 +90,7 @@ func TestMain(m *testing.M) { VSchema: VSchema, SidecarDBName: sidecarDBName, } - if err := clusterInstance.StartKeyspace(*keyspace, []string{"-80", "80-"}, 1, false); err != nil { + if err := clusterInstance.StartKeyspace(*keyspace, []string{"-40", "40-80", "80-"}, 0, false); err != nil { return 1 } @@ -111,22 +111,23 @@ func start(t *testing.T) (*mysql.Conn, func()) { conn, err := mysql.Connect(ctx, &vtParams) require.NoError(t, err) - deleteAll := func() { - tables := []string{"twopc_user"} - for _, table := range tables { - _, _ = utils.ExecAllowError(t, conn, "delete from "+table) - } - } - - deleteAll() - return conn, func() { - deleteAll() conn.Close() - cluster.PanicHandler(t) + cleanup(t) } } +func cleanup(t *testing.T) { + cluster.PanicHandler(t) + + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.NoError(t, err) + defer conn.Close() + + _, _ = utils.ExecAllowError(t, conn, "delete from twopc_user") +} + type extractInterestingValues func(dtidMap map[string]string, vals []sqltypes.Value) []sqltypes.Value var tables = map[string]extractInterestingValues{ @@ -172,7 +173,8 @@ func getDTID(dtidMap map[string]string, dtKey string) string { func runVStream(t *testing.T, ctx context.Context, ch chan *binlogdatapb.VEvent, vtgateConn *vtgateconn.VTGateConn) { vgtid := &binlogdatapb.VGtid{ ShardGtids: []*binlogdatapb.ShardGtid{ - {Keyspace: keyspaceName, Shard: "-80", Gtid: "current"}, + {Keyspace: keyspaceName, Shard: "-40", Gtid: "current"}, + {Keyspace: keyspaceName, Shard: "40-80", Gtid: "current"}, {Keyspace: keyspaceName, Shard: "80-", Gtid: "current"}, }} filter := &binlogdatapb.Filter{ @@ -212,6 +214,10 @@ func runVStream(t *testing.T, ctx context.Context, ch chan *binlogdatapb.VEvent, } func retrieveTransitions(t *testing.T, ch chan *binlogdatapb.VEvent, tableMap map[string][]*querypb.Field, dtMap map[string]string) map[string][]string { + return retrieveTransitionsWithTimeout(t, ch, tableMap, dtMap, 1*time.Second) +} + +func retrieveTransitionsWithTimeout(t *testing.T, ch chan *binlogdatapb.VEvent, tableMap map[string][]*querypb.Field, dtMap map[string]string, timeout time.Duration) map[string][]string { logTable := make(map[string][]string) keepWaiting := true @@ -230,7 +236,7 @@ func retrieveTransitions(t *testing.T, ch chan *binlogdatapb.VEvent, tableMap ma if re.FieldEvent != nil { tableMap[re.FieldEvent.TableName] = re.FieldEvent.Fields } - case <-time.After(1 * time.Second): + case <-time.After(timeout): keepWaiting = false } } diff --git a/go/test/endtoend/vtgate/transaction/twopc/schema.sql b/go/test/endtoend/transaction/twopc/schema.sql similarity index 100% rename from go/test/endtoend/vtgate/transaction/twopc/schema.sql rename to go/test/endtoend/transaction/twopc/schema.sql diff --git a/go/test/endtoend/vtgate/transaction/twopc/twopc_test.go b/go/test/endtoend/transaction/twopc/twopc_test.go similarity index 53% rename from go/test/endtoend/vtgate/transaction/twopc/twopc_test.go rename to go/test/endtoend/transaction/twopc/twopc_test.go index f18073c5827..dc2aba61b1b 100644 --- a/go/test/endtoend/vtgate/transaction/twopc/twopc_test.go +++ b/go/test/endtoend/transaction/twopc/twopc_test.go @@ -19,10 +19,13 @@ package transaction import ( "context" _ "embed" + "fmt" "reflect" "sort" + "strings" "sync" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -30,6 +33,7 @@ import ( "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/test/endtoend/cluster" "vitess.io/vitess/go/test/endtoend/utils" + "vitess.io/vitess/go/vt/callerid" binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" querypb "vitess.io/vitess/go/vt/proto/query" ) @@ -68,23 +72,33 @@ func TestDTCommit(t *testing.T) { "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"COMMIT\")]", }, "ks.dt_participant:80-": { - "insert:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"-80\")]", - "delete:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"-80\")]", + "insert:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", + "insert:[VARCHAR(\"dtid-1\") INT64(2) VARCHAR(\"ks\") VARCHAR(\"-40\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(2) VARCHAR(\"ks\") VARCHAR(\"-40\")]", }, - "ks.redo_state:-80": { + "ks.redo_state:-40": { "insert:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", }, - "ks.redo_statement:-80": { + "ks.redo_state:40-80": { + "insert:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + }, + "ks.redo_statement:-40": { + "insert:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (10, 'apa')\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (10, 'apa')\")]", + }, + "ks.redo_statement:40-80": { "insert:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (8, 'bar')\")]", - "insert:[VARCHAR(\"dtid-1\") INT64(2) BLOB(\"insert into twopc_user(id, `name`) values (10, 'apa')\")]", "delete:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (8, 'bar')\")]", - "delete:[VARCHAR(\"dtid-1\") INT64(2) BLOB(\"insert into twopc_user(id, `name`) values (10, 'apa')\")]", }, - "ks.twopc_user:-80": { - `insert:[INT64(8) VARCHAR("bar")]`, + "ks.twopc_user:-40": { `insert:[INT64(10) VARCHAR("apa")]`, }, + "ks.twopc_user:40-80": { + `insert:[INT64(8) VARCHAR("bar")]`, + }, "ks.twopc_user:80-": { `insert:[INT64(7) VARCHAR("foo")]`, `insert:[INT64(9) VARCHAR("baz")]`, @@ -107,19 +121,19 @@ func TestDTCommit(t *testing.T) { "delete:[VARCHAR(\"dtid-2\") VARCHAR(\"COMMIT\")]", }, "ks.dt_participant:80-": { - "insert:[VARCHAR(\"dtid-2\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"-80\")]", - "delete:[VARCHAR(\"dtid-2\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"-80\")]", + "insert:[VARCHAR(\"dtid-2\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", + "delete:[VARCHAR(\"dtid-2\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", }, - "ks.redo_state:-80": { + "ks.redo_state:40-80": { "insert:[VARCHAR(\"dtid-2\") VARCHAR(\"PREPARE\")]", "delete:[VARCHAR(\"dtid-2\") VARCHAR(\"PREPARE\")]", }, - "ks.redo_statement:-80": { + "ks.redo_statement:40-80": { "insert:[VARCHAR(\"dtid-2\") INT64(1) BLOB(\"update twopc_user set `name` = 'newfoo' where id = 8 limit 10001 /* INT64 */\")]", "delete:[VARCHAR(\"dtid-2\") INT64(1) BLOB(\"update twopc_user set `name` = 'newfoo' where id = 8 limit 10001 /* INT64 */\")]", }, - "ks.twopc_user:-80": {"update:[INT64(8) VARCHAR(\"newfoo\")]"}, - "ks.twopc_user:80-": {"update:[INT64(7) VARCHAR(\"newfoo\")]"}, + "ks.twopc_user:40-80": {"update:[INT64(8) VARCHAR(\"newfoo\")]"}, + "ks.twopc_user:80-": {"update:[INT64(7) VARCHAR(\"newfoo\")]"}, } assert.Equal(t, expectations, logTable, "mismatch expected: \n got: %s, want: %s", prettyPrint(logTable), prettyPrint(expectations)) @@ -138,18 +152,18 @@ func TestDTCommit(t *testing.T) { "delete:[VARCHAR(\"dtid-3\") VARCHAR(\"COMMIT\")]", }, "ks.dt_participant:80-": { - "insert:[VARCHAR(\"dtid-3\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"-80\")]", - "delete:[VARCHAR(\"dtid-3\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"-80\")]", + "insert:[VARCHAR(\"dtid-3\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"-40\")]", + "delete:[VARCHAR(\"dtid-3\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"-40\")]", }, - "ks.redo_state:-80": { + "ks.redo_state:-40": { "insert:[VARCHAR(\"dtid-3\") VARCHAR(\"PREPARE\")]", "delete:[VARCHAR(\"dtid-3\") VARCHAR(\"PREPARE\")]", }, - "ks.redo_statement:-80": { + "ks.redo_statement:-40": { "insert:[VARCHAR(\"dtid-3\") INT64(1) BLOB(\"delete from twopc_user where id = 10 limit 10001 /* INT64 */\")]", "delete:[VARCHAR(\"dtid-3\") INT64(1) BLOB(\"delete from twopc_user where id = 10 limit 10001 /* INT64 */\")]", }, - "ks.twopc_user:-80": {"delete:[INT64(10) VARCHAR(\"apa\")]"}, + "ks.twopc_user:-40": {"delete:[INT64(10) VARCHAR(\"apa\")]"}, "ks.twopc_user:80-": {"delete:[INT64(9) VARCHAR(\"baz\")]"}, } assert.Equal(t, expectations, logTable, @@ -228,7 +242,8 @@ func TestDTCommitDMLOnlyOnMM(t *testing.T) { // Insert into multiple shards utils.Exec(t, conn, "begin") utils.Exec(t, conn, "insert into twopc_user(id, name) values(7,'foo')") - utils.Exec(t, conn, "select * from twopc_user") + utils.Exec(t, conn, "select * from twopc_user where id = 8") + utils.Exec(t, conn, "select * from twopc_user where id = 10") utils.Exec(t, conn, "commit") tableMap := make(map[string][]*querypb.Field) @@ -241,8 +256,10 @@ func TestDTCommitDMLOnlyOnMM(t *testing.T) { "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"COMMIT\")]", }, "ks.dt_participant:80-": { - "insert:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"-80\")]", - "delete:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"-80\")]", + "insert:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", + "insert:[VARCHAR(\"dtid-1\") INT64(2) VARCHAR(\"ks\") VARCHAR(\"-40\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(2) VARCHAR(\"ks\") VARCHAR(\"-40\")]", }, "ks.twopc_user:80-": {"insert:[INT64(7) VARCHAR(\"foo\")]"}, } @@ -252,7 +269,8 @@ func TestDTCommitDMLOnlyOnMM(t *testing.T) { // Update from multiple shard utils.Exec(t, conn, "begin") utils.Exec(t, conn, "update twopc_user set name='newfoo' where id = 7") - utils.Exec(t, conn, "select * from twopc_user") + utils.Exec(t, conn, "select * from twopc_user where id = 8") + utils.Exec(t, conn, "select * from twopc_user where id = 10") utils.Exec(t, conn, "commit") logTable = retrieveTransitions(t, ch, tableMap, dtMap) @@ -263,8 +281,10 @@ func TestDTCommitDMLOnlyOnMM(t *testing.T) { "delete:[VARCHAR(\"dtid-2\") VARCHAR(\"COMMIT\")]", }, "ks.dt_participant:80-": { - "insert:[VARCHAR(\"dtid-2\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"-80\")]", - "delete:[VARCHAR(\"dtid-2\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"-80\")]", + "insert:[VARCHAR(\"dtid-2\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", + "insert:[VARCHAR(\"dtid-2\") INT64(2) VARCHAR(\"ks\") VARCHAR(\"-40\")]", + "delete:[VARCHAR(\"dtid-2\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", + "delete:[VARCHAR(\"dtid-2\") INT64(2) VARCHAR(\"ks\") VARCHAR(\"-40\")]", }, "ks.twopc_user:80-": {"update:[INT64(7) VARCHAR(\"newfoo\")]"}, } @@ -274,7 +294,8 @@ func TestDTCommitDMLOnlyOnMM(t *testing.T) { // DELETE from multiple shard utils.Exec(t, conn, "begin") utils.Exec(t, conn, "delete from twopc_user where id = 7") - utils.Exec(t, conn, "select * from twopc_user") + utils.Exec(t, conn, "select * from twopc_user where id = 8") + utils.Exec(t, conn, "select * from twopc_user where id = 10") utils.Exec(t, conn, "commit") logTable = retrieveTransitions(t, ch, tableMap, dtMap) @@ -285,8 +306,10 @@ func TestDTCommitDMLOnlyOnMM(t *testing.T) { "delete:[VARCHAR(\"dtid-3\") VARCHAR(\"COMMIT\")]", }, "ks.dt_participant:80-": { - "insert:[VARCHAR(\"dtid-3\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"-80\")]", - "delete:[VARCHAR(\"dtid-3\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"-80\")]", + "insert:[VARCHAR(\"dtid-3\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", + "insert:[VARCHAR(\"dtid-3\") INT64(2) VARCHAR(\"ks\") VARCHAR(\"-40\")]", + "delete:[VARCHAR(\"dtid-3\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", + "delete:[VARCHAR(\"dtid-3\") INT64(2) VARCHAR(\"ks\") VARCHAR(\"-40\")]", }, "ks.twopc_user:80-": {"delete:[INT64(7) VARCHAR(\"newfoo\")]"}, } @@ -321,12 +344,12 @@ func TestDTCommitDMLOnlyOnRM(t *testing.T) { dtMap := make(map[string]string) logTable := retrieveTransitions(t, ch, tableMap, dtMap) expectations := map[string][]string{ - "ks.dt_state:-80": { + "ks.dt_state:40-80": { "insert:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", "update:[VARCHAR(\"dtid-1\") VARCHAR(\"COMMIT\")]", "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"COMMIT\")]", }, - "ks.dt_participant:-80": { + "ks.dt_participant:40-80": { "insert:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"80-\")]", "delete:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"80-\")]", }, @@ -351,12 +374,12 @@ func TestDTCommitDMLOnlyOnRM(t *testing.T) { logTable = retrieveTransitions(t, ch, tableMap, dtMap) expectations = map[string][]string{ - "ks.dt_state:-80": { + "ks.dt_state:40-80": { "insert:[VARCHAR(\"dtid-2\") VARCHAR(\"PREPARE\")]", "update:[VARCHAR(\"dtid-2\") VARCHAR(\"COMMIT\")]", "delete:[VARCHAR(\"dtid-2\") VARCHAR(\"COMMIT\")]", }, - "ks.dt_participant:-80": { + "ks.dt_participant:40-80": { "insert:[VARCHAR(\"dtid-2\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"80-\")]", "delete:[VARCHAR(\"dtid-2\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"80-\")]", }, @@ -381,12 +404,12 @@ func TestDTCommitDMLOnlyOnRM(t *testing.T) { logTable = retrieveTransitions(t, ch, tableMap, dtMap) expectations = map[string][]string{ - "ks.dt_state:-80": { + "ks.dt_state:40-80": { "insert:[VARCHAR(\"dtid-3\") VARCHAR(\"PREPARE\")]", "update:[VARCHAR(\"dtid-3\") VARCHAR(\"COMMIT\")]", "delete:[VARCHAR(\"dtid-3\") VARCHAR(\"COMMIT\")]", }, - "ks.dt_participant:-80": { + "ks.dt_participant:40-80": { "insert:[VARCHAR(\"dtid-3\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"80-\")]", "delete:[VARCHAR(\"dtid-3\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"80-\")]", }, @@ -430,7 +453,7 @@ func TestDTPrepareFailOnRM(t *testing.T) { utils.Exec(t, conn2, "begin") utils.Exec(t, conn2, "insert into twopc_user(id, name) values(9,'baz')") - utils.Exec(t, conn2, "insert into twopc_user(id, name) values(10,'apa')") + utils.Exec(t, conn2, "insert into twopc_user(id, name) values(18,'apa')") var wg sync.WaitGroup wg.Add(2) @@ -465,31 +488,31 @@ func TestDTPrepareFailOnRM(t *testing.T) { "delete:[VARCHAR(\"dtid-2\") VARCHAR(\"ROLLBACK\")]", }, "ks.dt_participant:80-": { - "insert:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"-80\")]", - "insert:[VARCHAR(\"dtid-2\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"-80\")]", - "delete:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"-80\")]", - "delete:[VARCHAR(\"dtid-2\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"-80\")]", + "insert:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", + "insert:[VARCHAR(\"dtid-2\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", + "delete:[VARCHAR(\"dtid-2\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", }, - "ks.redo_state:-80": { + "ks.redo_state:40-80": { "insert:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", }, - "ks.redo_statement:-80": { /* flexi Expectation */ }, - "ks.twopc_user:-80": { /* flexi Expectation */ }, - "ks.twopc_user:80-": { /* flexi Expectation */ }, + "ks.redo_statement:40-80": { /* flexi Expectation */ }, + "ks.twopc_user:40-80": { /* flexi Expectation */ }, + "ks.twopc_user:80-": { /* flexi Expectation */ }, } flexiExpectations := map[string][2][]string{ - "ks.redo_statement:-80": {{ + "ks.redo_statement:40-80": {{ "insert:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (8, 'bar')\")]", "delete:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (8, 'bar')\")]", }, { - "insert:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (10, 'apa')\")]", - "delete:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (10, 'apa')\")]", + "insert:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (18, 'apa')\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (18, 'apa')\")]", }}, - "ks.twopc_user:-80": {{ + "ks.twopc_user:40-80": {{ "insert:[INT64(8) VARCHAR(\"bar\")]", }, { - "insert:[INT64(10) VARCHAR(\"apa\")]", + "insert:[INT64(18) VARCHAR(\"apa\")]", }}, "ks.twopc_user:80-": {{ "insert:[INT64(7) VARCHAR(\"foo\")]", @@ -521,3 +544,341 @@ func compareMaps(t *testing.T, expected, actual map[string][]string, flexibleExp } } } + +// TestDTResolveAfterMMCommit tests that transaction is committed on recovery +// failure after MM commit. +func TestDTResolveAfterMMCommit(t *testing.T) { + defer cleanup(t) + + vtgateConn, err := cluster.DialVTGate(context.Background(), t.Name(), vtgateGrpcAddress, "dt_user", "") + require.NoError(t, err) + defer vtgateConn.Close() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + ch := make(chan *binlogdatapb.VEvent) + runVStream(t, ctx, ch, vtgateConn) + + conn := vtgateConn.Session("", nil) + qCtx, cancel := context.WithCancel(context.Background()) + defer cancel() + // Insert into multiple shards + _, err = conn.Execute(qCtx, "begin", nil) + require.NoError(t, err) + _, err = conn.Execute(qCtx, "insert into twopc_user(id, name) values(7,'foo')", nil) + require.NoError(t, err) + _, err = conn.Execute(qCtx, "insert into twopc_user(id, name) values(8,'bar')", nil) + require.NoError(t, err) + _, err = conn.Execute(qCtx, "insert into twopc_user(id, name) values(9,'baz')", nil) + require.NoError(t, err) + _, err = conn.Execute(qCtx, "insert into twopc_user(id, name) values(10,'apa')", nil) + require.NoError(t, err) + + // The caller ID is used to simulate the failure at the desired point. + newCtx := callerid.NewContext(qCtx, callerid.NewEffectiveCallerID("MMCommitted_FailNow", "", ""), nil) + _, err = conn.Execute(newCtx, "commit", nil) + require.ErrorContains(t, err, "Fail After MM commit") + + // Below check ensures that the transaction is resolved by the resolver on receiving unresolved transaction signal from MM. + tableMap := make(map[string][]*querypb.Field) + dtMap := make(map[string]string) + logTable := retrieveTransitionsWithTimeout(t, ch, tableMap, dtMap, 2*time.Second) + expectations := map[string][]string{ + "ks.dt_state:80-": { + "insert:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + "update:[VARCHAR(\"dtid-1\") VARCHAR(\"COMMIT\")]", + "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"COMMIT\")]", + }, + "ks.dt_participant:80-": { + "insert:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", + "insert:[VARCHAR(\"dtid-1\") INT64(2) VARCHAR(\"ks\") VARCHAR(\"-40\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(2) VARCHAR(\"ks\") VARCHAR(\"-40\")]", + }, + "ks.redo_state:-40": { + "insert:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + }, + "ks.redo_state:40-80": { + "insert:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + }, + "ks.redo_statement:-40": { + "insert:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (10, 'apa')\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (10, 'apa')\")]", + }, + "ks.redo_statement:40-80": { + "insert:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (8, 'bar')\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (8, 'bar')\")]", + }, + "ks.twopc_user:-40": { + `insert:[INT64(10) VARCHAR("apa")]`, + }, + "ks.twopc_user:40-80": { + `insert:[INT64(8) VARCHAR("bar")]`, + }, + "ks.twopc_user:80-": { + `insert:[INT64(7) VARCHAR("foo")]`, + `insert:[INT64(9) VARCHAR("baz")]`, + }, + } + assert.Equal(t, expectations, logTable, + "mismatch expected: \n got: %s, want: %s", prettyPrint(logTable), prettyPrint(expectations)) +} + +// TestDTResolveAfterRMPrepare tests that transaction is rolled back on recovery +// failure after RM prepare and before MM commit. +func TestDTResolveAfterRMPrepare(t *testing.T) { + vtgateConn, err := cluster.DialVTGate(context.Background(), t.Name(), vtgateGrpcAddress, "dt_user", "") + require.NoError(t, err) + defer vtgateConn.Close() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + ch := make(chan *binlogdatapb.VEvent) + runVStream(t, ctx, ch, vtgateConn) + + conn := vtgateConn.Session("", nil) + qCtx, cancel := context.WithCancel(context.Background()) + defer cancel() + // Insert into multiple shards + _, err = conn.Execute(qCtx, "begin", nil) + require.NoError(t, err) + _, err = conn.Execute(qCtx, "insert into twopc_user(id, name) values(7,'foo')", nil) + require.NoError(t, err) + _, err = conn.Execute(qCtx, "insert into twopc_user(id, name) values(8,'bar')", nil) + require.NoError(t, err) + + // The caller ID is used to simulate the failure at the desired point. + newCtx := callerid.NewContext(qCtx, callerid.NewEffectiveCallerID("RMPrepared_FailNow", "", ""), nil) + _, err = conn.Execute(newCtx, "commit", nil) + require.ErrorContains(t, err, "Fail After RM prepared") + + // Below check ensures that the transaction is resolved by the resolver on receiving unresolved transaction signal from MM. + tableMap := make(map[string][]*querypb.Field) + dtMap := make(map[string]string) + logTable := retrieveTransitionsWithTimeout(t, ch, tableMap, dtMap, 2*time.Second) + expectations := map[string][]string{ + "ks.dt_state:80-": { + "insert:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + "update:[VARCHAR(\"dtid-1\") VARCHAR(\"ROLLBACK\")]", + "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"ROLLBACK\")]", + }, + "ks.dt_participant:80-": { + "insert:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", + }, + "ks.redo_state:40-80": { + "insert:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + }, + "ks.redo_statement:40-80": { + "insert:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (8, 'bar')\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (8, 'bar')\")]", + }, + } + assert.Equal(t, expectations, logTable, + "mismatch expected: \n got: %s, want: %s", prettyPrint(logTable), prettyPrint(expectations)) +} + +// TestDTResolveDuringRMPrepare tests that transaction is rolled back on recovery +// failure after semi RM prepare. +func TestDTResolveDuringRMPrepare(t *testing.T) { + vtgateConn, err := cluster.DialVTGate(context.Background(), t.Name(), vtgateGrpcAddress, "dt_user", "") + require.NoError(t, err) + defer vtgateConn.Close() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + ch := make(chan *binlogdatapb.VEvent) + runVStream(t, ctx, ch, vtgateConn) + + conn := vtgateConn.Session("", nil) + qCtx, cancel := context.WithCancel(context.Background()) + defer cancel() + // Insert into multiple shards + _, err = conn.Execute(qCtx, "begin", nil) + require.NoError(t, err) + _, err = conn.Execute(qCtx, "insert into twopc_user(id, name) values(7,'foo')", nil) + require.NoError(t, err) + _, err = conn.Execute(qCtx, "insert into twopc_user(id, name) values(8,'bar')", nil) + require.NoError(t, err) + _, err = conn.Execute(qCtx, "insert into twopc_user(id, name) values(10,'bar')", nil) + require.NoError(t, err) + + // The caller ID is used to simulate the failure at the desired point. + newCtx := callerid.NewContext(qCtx, callerid.NewEffectiveCallerID("RMPrepare_-40_FailNow", "", ""), nil) + _, err = conn.Execute(newCtx, "commit", nil) + require.ErrorContains(t, err, "Fail During RM prepare") + + // Below check ensures that the transaction is resolved by the resolver on receiving unresolved transaction signal from MM. + tableMap := make(map[string][]*querypb.Field) + dtMap := make(map[string]string) + logTable := retrieveTransitionsWithTimeout(t, ch, tableMap, dtMap, 2*time.Second) + expectations := map[string][]string{ + "ks.dt_state:80-": { + "insert:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + "update:[VARCHAR(\"dtid-1\") VARCHAR(\"ROLLBACK\")]", + "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"ROLLBACK\")]", + }, + "ks.dt_participant:80-": { + "insert:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", + "insert:[VARCHAR(\"dtid-1\") INT64(2) VARCHAR(\"ks\") VARCHAR(\"-40\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(2) VARCHAR(\"ks\") VARCHAR(\"-40\")]", + }, + "ks.redo_state:40-80": { + "insert:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + }, + "ks.redo_statement:40-80": { + "insert:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (8, 'bar')\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (8, 'bar')\")]", + }, + } + assert.Equal(t, expectations, logTable, + "mismatch expected: \n got: %s, want: %s", prettyPrint(logTable), prettyPrint(expectations)) +} + +// TestDTResolveDuringRMCommit tests that transaction is committed on recovery +// failure after semi RM commit. +func TestDTResolveDuringRMCommit(t *testing.T) { + defer cleanup(t) + + vtgateConn, err := cluster.DialVTGate(context.Background(), t.Name(), vtgateGrpcAddress, "dt_user", "") + require.NoError(t, err) + defer vtgateConn.Close() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + ch := make(chan *binlogdatapb.VEvent) + runVStream(t, ctx, ch, vtgateConn) + + conn := vtgateConn.Session("", nil) + qCtx, cancel := context.WithCancel(context.Background()) + defer cancel() + // Insert into multiple shards + _, err = conn.Execute(qCtx, "begin", nil) + require.NoError(t, err) + _, err = conn.Execute(qCtx, "insert into twopc_user(id, name) values(7,'foo')", nil) + require.NoError(t, err) + _, err = conn.Execute(qCtx, "insert into twopc_user(id, name) values(8,'bar')", nil) + require.NoError(t, err) + _, err = conn.Execute(qCtx, "insert into twopc_user(id, name) values(10,'apa')", nil) + require.NoError(t, err) + + // The caller ID is used to simulate the failure at the desired point. + newCtx := callerid.NewContext(qCtx, callerid.NewEffectiveCallerID("RMCommit_-40_FailNow", "", ""), nil) + _, err = conn.Execute(newCtx, "commit", nil) + require.ErrorContains(t, err, "Fail During RM commit") + + // Below check ensures that the transaction is resolved by the resolver on receiving unresolved transaction signal from MM. + tableMap := make(map[string][]*querypb.Field) + dtMap := make(map[string]string) + logTable := retrieveTransitionsWithTimeout(t, ch, tableMap, dtMap, 2*time.Second) + expectations := map[string][]string{ + "ks.dt_state:80-": { + "insert:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + "update:[VARCHAR(\"dtid-1\") VARCHAR(\"COMMIT\")]", + "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"COMMIT\")]", + }, + "ks.dt_participant:80-": { + "insert:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", + "insert:[VARCHAR(\"dtid-1\") INT64(2) VARCHAR(\"ks\") VARCHAR(\"-40\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(2) VARCHAR(\"ks\") VARCHAR(\"-40\")]", + }, + "ks.redo_state:-40": { + "insert:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + }, + "ks.redo_state:40-80": { + "insert:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + }, + "ks.redo_statement:-40": { + "insert:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (10, 'apa')\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (10, 'apa')\")]", + }, + "ks.redo_statement:40-80": { + "insert:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (8, 'bar')\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(1) BLOB(\"insert into twopc_user(id, `name`) values (8, 'bar')\")]", + }, + "ks.twopc_user:-40": { + `insert:[INT64(10) VARCHAR("apa")]`, + }, + "ks.twopc_user:40-80": { + `insert:[INT64(8) VARCHAR("bar")]`, + }, + "ks.twopc_user:80-": { + `insert:[INT64(7) VARCHAR("foo")]`, + }, + } + assert.Equal(t, expectations, logTable, + "mismatch expected: \n got: %s, want: %s", prettyPrint(logTable), prettyPrint(expectations)) +} + +// TestDTResolveAfterTransactionRecord tests that transaction is rolled back on recovery +// failure after TR created and before RM prepare. +func TestDTResolveAfterTransactionRecord(t *testing.T) { + vtgateConn, err := cluster.DialVTGate(context.Background(), t.Name(), vtgateGrpcAddress, "dt_user", "") + require.NoError(t, err) + defer vtgateConn.Close() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + ch := make(chan *binlogdatapb.VEvent) + runVStream(t, ctx, ch, vtgateConn) + + conn := vtgateConn.Session("", nil) + qCtx, cancel := context.WithCancel(context.Background()) + defer cancel() + // Insert into multiple shards + _, err = conn.Execute(qCtx, "begin", nil) + require.NoError(t, err) + _, err = conn.Execute(qCtx, "insert into twopc_user(id, name) values(7,'foo')", nil) + require.NoError(t, err) + _, err = conn.Execute(qCtx, "insert into twopc_user(id, name) values(8,'bar')", nil) + require.NoError(t, err) + + // The caller ID is used to simulate the failure at the desired point. + newCtx := callerid.NewContext(qCtx, callerid.NewEffectiveCallerID("TRCreated_FailNow", "", ""), nil) + _, err = conn.Execute(newCtx, "commit", nil) + require.ErrorContains(t, err, "Fail After TR created") + + t.Run("ReadTransactionState", func(t *testing.T) { + errStr := err.Error() + indx := strings.Index(errStr, "Fail") + require.Greater(t, indx, 0) + dtid := errStr[0 : indx-2] + res, err := conn.Execute(context.Background(), fmt.Sprintf(`show transaction status for '%v'`, dtid), nil) + require.NoError(t, err) + resStr := fmt.Sprintf("%v", res.Rows) + require.Contains(t, resStr, `[[VARCHAR("ks:80-`) + require.Contains(t, resStr, `VARCHAR("PREPARE") DATETIME("`) + require.Contains(t, resStr, `+0000 UTC") VARCHAR("ks:40-80")]]`) + }) + + // Below check ensures that the transaction is resolved by the resolver on receiving unresolved transaction signal from MM. + tableMap := make(map[string][]*querypb.Field) + dtMap := make(map[string]string) + logTable := retrieveTransitionsWithTimeout(t, ch, tableMap, dtMap, 2*time.Second) + expectations := map[string][]string{ + "ks.dt_state:80-": { + "insert:[VARCHAR(\"dtid-1\") VARCHAR(\"PREPARE\")]", + "update:[VARCHAR(\"dtid-1\") VARCHAR(\"ROLLBACK\")]", + "delete:[VARCHAR(\"dtid-1\") VARCHAR(\"ROLLBACK\")]", + }, + "ks.dt_participant:80-": { + "insert:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", + "delete:[VARCHAR(\"dtid-1\") INT64(1) VARCHAR(\"ks\") VARCHAR(\"40-80\")]", + }, + } + assert.Equal(t, expectations, logTable, + "mismatch expected: \n got: %s, want: %s", prettyPrint(logTable), prettyPrint(expectations)) +} diff --git a/go/test/endtoend/vtgate/transaction/twopc/vschema.json b/go/test/endtoend/transaction/twopc/vschema.json similarity index 100% rename from go/test/endtoend/vtgate/transaction/twopc/vschema.json rename to go/test/endtoend/transaction/twopc/vschema.json diff --git a/go/test/endtoend/vtgate/transaction/tx_test.go b/go/test/endtoend/transaction/tx_test.go similarity index 98% rename from go/test/endtoend/vtgate/transaction/tx_test.go rename to go/test/endtoend/transaction/tx_test.go index 8a004277b89..40621a1d84b 100644 --- a/go/test/endtoend/vtgate/transaction/tx_test.go +++ b/go/test/endtoend/transaction/tx_test.go @@ -59,7 +59,6 @@ func TestMain(m *testing.M) { // Set extra tablet args for twopc clusterInstance.VtTabletExtraArgs = []string{ "--twopc_enable", - "--twopc_coordinator_address", fmt.Sprintf("localhost:%d", clusterInstance.VtgateGrpcPort), "--twopc_abandon_age", "3600", } diff --git a/go/test/endtoend/vtgate/transaction/vschema.json b/go/test/endtoend/transaction/vschema.json similarity index 100% rename from go/test/endtoend/vtgate/transaction/vschema.json rename to go/test/endtoend/transaction/vschema.json diff --git a/go/test/endtoend/vreplication/cluster_test.go b/go/test/endtoend/vreplication/cluster_test.go index a758944d3d9..218fc2b768a 100644 --- a/go/test/endtoend/vreplication/cluster_test.go +++ b/go/test/endtoend/vreplication/cluster_test.go @@ -30,19 +30,18 @@ import ( "testing" "time" - "vitess.io/vitess/go/vt/vttablet" - "vitess.io/vitess/go/mysql" - + "vitess.io/vitess/go/test/endtoend/cluster" + "vitess.io/vitess/go/test/endtoend/throttler" + "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/mysqlctl" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" + "vitess.io/vitess/go/vt/vttablet" - "github.com/stretchr/testify/require" + vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" - "vitess.io/vitess/go/test/endtoend/cluster" - "vitess.io/vitess/go/test/endtoend/throttler" - "vitess.io/vitess/go/vt/log" + "github.com/stretchr/testify/require" ) var ( @@ -477,7 +476,8 @@ func (vc *VitessCluster) AddKeyspace(t *testing.T, cells []*Cell, ksName string, } log.Infof("Applying throttler config for keyspace %s", keyspace.Name) - res, err := throttler.UpdateThrottlerTopoConfigRaw(vc.VtctldClient, keyspace.Name, true, false, throttlerConfig.Threshold, throttlerConfig.Query, nil) + req := &vtctldatapb.UpdateThrottlerConfigRequest{Enable: true, Threshold: throttlerConfig.Threshold, CustomQuery: throttlerConfig.Query} + res, err := throttler.UpdateThrottlerTopoConfigRaw(vc.VtctldClient, keyspace.Name, req, nil, nil) require.NoError(t, err, res) cellsToWatch := "" @@ -743,7 +743,7 @@ func (vc *VitessCluster) AddShards(t *testing.T, cells []*Cell, keyspace *Keyspa HTTPPort: tablet.Vttablet.Port, } log.Infof("+ Waiting for throttler config to be applied on %s, type=%v", tablet.Name, tablet.Vttablet.TabletType) - throttler.WaitForThrottlerStatusEnabled(t, clusterTablet, true, nil, time.Minute) + throttler.WaitForThrottlerStatusEnabled(t, vc.VtctldClient, clusterTablet, true, nil, time.Minute) } } log.Infof("Throttler config applied on all shards") diff --git a/go/test/endtoend/vreplication/helper_test.go b/go/test/endtoend/vreplication/helper_test.go index eca4c312ae7..b45c09837c9 100644 --- a/go/test/endtoend/vreplication/helper_test.go +++ b/go/test/endtoend/vreplication/helper_test.go @@ -18,11 +18,12 @@ package vreplication import ( "context" + crand "crypto/rand" "encoding/hex" "encoding/json" "fmt" "io" - "math/rand" + "math/rand/v2" "net/http" "os" "os/exec" @@ -752,7 +753,7 @@ func verifyCopyStateIsOptimized(t *testing.T, tablet *cluster.VttabletProcess) { // be used to generate and insert test data. func randHex(n int) (string, error) { bytes := make([]byte, n) - if _, err := rand.Read(bytes); err != nil { + if _, err := crand.Read(bytes); err != nil { return "", err } return hex.EncodeToString(bytes), nil diff --git a/go/test/endtoend/vreplication/movetables_mirrortraffic_test.go b/go/test/endtoend/vreplication/movetables_mirrortraffic_test.go new file mode 100644 index 00000000000..54e648de6b4 --- /dev/null +++ b/go/test/endtoend/vreplication/movetables_mirrortraffic_test.go @@ -0,0 +1,114 @@ +/* +Copyright 2024 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 vreplication + +import ( + "testing" + + binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" +) + +func testMoveTablesMirrorTraffic(t *testing.T, flavor workflowFlavor) { + setSidecarDBName("_vt") + vc = setupMinimalCluster(t) + defer vc.TearDown() + + sourceKeyspace := "product" + targetKeyspace := "customer" + workflowName := "wf1" + tables := []string{"customer", "loadtest", "customer2"} + + _ = setupMinimalCustomerKeyspace(t) + + mtwf := &moveTablesWorkflow{ + workflowInfo: &workflowInfo{ + vc: vc, + workflowName: workflowName, + targetKeyspace: targetKeyspace, + }, + sourceKeyspace: sourceKeyspace, + tables: "customer,loadtest,customer2", + mirrorFlags: []string{"--percent", "25"}, + } + mt := newMoveTables(vc, mtwf, flavor) + + // Mirror rules do not exist by default. + mt.Create() + confirmNoMirrorRules(t) + + waitForWorkflowState(t, vc, ksWorkflow, binlogdatapb.VReplicationWorkflowState_Running.String()) + + // Mirror rules can be created after a MoveTables workflow is created. + mt.MirrorTraffic() + confirmMirrorRulesExist(t) + expectMirrorRules(t, sourceKeyspace, targetKeyspace, tables, []topodatapb.TabletType{ + topodatapb.TabletType_PRIMARY, + topodatapb.TabletType_REPLICA, + topodatapb.TabletType_RDONLY, + }, 25) + + // Mirror rules can be adjusted after mirror rules are in place. + mtwf.mirrorFlags[1] = "50" + mt.MirrorTraffic() + confirmMirrorRulesExist(t) + expectMirrorRules(t, sourceKeyspace, targetKeyspace, tables, []topodatapb.TabletType{ + topodatapb.TabletType_PRIMARY, + topodatapb.TabletType_REPLICA, + topodatapb.TabletType_RDONLY, + }, 50) + + // Mirror rules can be adjusted multiple times after mirror rules are in + // place. + mtwf.mirrorFlags[1] = "75" + mt.MirrorTraffic() + confirmMirrorRulesExist(t) + expectMirrorRules(t, sourceKeyspace, targetKeyspace, tables, []topodatapb.TabletType{ + topodatapb.TabletType_PRIMARY, + topodatapb.TabletType_REPLICA, + topodatapb.TabletType_RDONLY, + }, 75) + + lg := newLoadGenerator(t, vc) + go func() { + lg.start() + }() + lg.waitForCount(1000) + + mt.SwitchReads() + confirmMirrorRulesExist(t) + + // Mirror rules can be adjusted for writes after reads have been switched. + mtwf.mirrorFlags[1] = "100" + mtwf.mirrorFlags = append(mtwf.mirrorFlags, "--tablet-types", "primary") + mt.MirrorTraffic() + confirmMirrorRulesExist(t) + expectMirrorRules(t, sourceKeyspace, targetKeyspace, tables, []topodatapb.TabletType{ + topodatapb.TabletType_PRIMARY, + }, 100) + + // Mirror rules are removed after writes are switched. + mt.SwitchWrites() + confirmNoMirrorRules(t) +} + +func TestMoveTablesMirrorTraffic(t *testing.T) { + currentWorkflowType = binlogdatapb.VReplicationWorkflowType_MoveTables + t.Run(workflowFlavorNames[workflowFlavorVtctld], func(t *testing.T) { + testMoveTablesMirrorTraffic(t, workflowFlavorVtctld) + }) +} diff --git a/go/test/endtoend/vreplication/resharding_workflows_v2_test.go b/go/test/endtoend/vreplication/resharding_workflows_v2_test.go index 82c859acb40..1e93a54b850 100644 --- a/go/test/endtoend/vreplication/resharding_workflows_v2_test.go +++ b/go/test/endtoend/vreplication/resharding_workflows_v2_test.go @@ -52,6 +52,7 @@ const ( const ( workflowActionCreate = "Create" + workflowActionMirrorTraffic = "Mirror" workflowActionSwitchTraffic = "SwitchTraffic" workflowActionReverseTraffic = "ReverseTraffic" workflowActionComplete = "Complete" @@ -70,6 +71,7 @@ type workflowExecOptions struct { deferSecondaryKeys bool atomicCopy bool shardSubset string + percent float32 } var defaultWorkflowExecOptions = &workflowExecOptions{ @@ -222,6 +224,8 @@ func tstWorkflowExecVtctl(t *testing.T, cells, workflow, sourceKs, targetKs, tab } args = append(args, "--initialize-target-sequences") // Only used for MoveTables } + case workflowActionMirrorTraffic: + args = append(args, "--percent", strconv.FormatFloat(float64(options.percent), byte('f'), -1, 32)) default: if options.shardSubset != "" { args = append(args, "--shards", options.shardSubset) @@ -746,7 +750,12 @@ func testPartialSwitches(t *testing.T) { func testRestOfWorkflow(t *testing.T) { // Relax the throttler so that it does not cause switches to fail because it can block // the catchup for the intra-keyspace materialization. - res, err := throttler.UpdateThrottlerTopoConfigRaw(vc.VtctldClient, "customer", true, false, throttlerConfig.Threshold*5, throttlerConfig.Query, nil) + req := &vtctldatapb.UpdateThrottlerConfigRequest{ + Enable: true, + Threshold: throttlerConfig.Threshold * 5, + CustomQuery: throttlerConfig.Query, + } + res, err := throttler.UpdateThrottlerTopoConfigRaw(vc.VtctldClient, "customer", req, nil, nil) require.NoError(t, err, res) testPartialSwitches(t) diff --git a/go/test/endtoend/vreplication/vreplication_test_env.go b/go/test/endtoend/vreplication/vreplication_test_env.go index 6073cfac6ab..c62d871380d 100644 --- a/go/test/endtoend/vreplication/vreplication_test_env.go +++ b/go/test/endtoend/vreplication/vreplication_test_env.go @@ -19,6 +19,7 @@ package vreplication var dryRunResultsSwitchWritesCustomerShard = []string{ "Lock keyspace product", "Lock keyspace customer", + "Mirroring 0.00 percent of traffic from keyspace product to keyspace customer for tablet types [PRIMARY]", "/Stop writes on keyspace product for tables [Lead,Lead-1,blüb_tbl,customer,db_order_test,geom_tbl,json_tbl,loadtest,reftable,vdiff_order]: [keyspace:product;shard:0;position:", "Wait for vreplication on stopped streams to catchup for up to 30s", "Create reverse vreplication workflow p2c_reverse", @@ -36,6 +37,7 @@ var dryRunResultsSwitchWritesCustomerShard = []string{ var dryRunResultsReadCustomerShard = []string{ "Lock keyspace product", + "Mirroring 0.00 percent of traffic from keyspace product to keyspace customer for tablet types [RDONLY,REPLICA]", "Switch reads for tables [Lead,Lead-1,blüb_tbl,customer,db_order_test,geom_tbl,json_tbl,loadtest,reftable,vdiff_order] to keyspace customer for tablet types [RDONLY,REPLICA]", "Routing rules for tables [Lead,Lead-1,blüb_tbl,customer,db_order_test,geom_tbl,json_tbl,loadtest,reftable,vdiff_order] will be updated", "Serving VSchema will be rebuilt for the customer keyspace", diff --git a/go/test/endtoend/vreplication/vreplication_vtctldclient_cli_test.go b/go/test/endtoend/vreplication/vreplication_vtctldclient_cli_test.go index 4a3f16a1cc9..a69d55c3417 100644 --- a/go/test/endtoend/vreplication/vreplication_vtctldclient_cli_test.go +++ b/go/test/endtoend/vreplication/vreplication_vtctldclient_cli_test.go @@ -36,6 +36,7 @@ import ( topodatapb "vitess.io/vitess/go/vt/proto/topodata" vschemapb "vitess.io/vitess/go/vt/proto/vschema" vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" + "vitess.io/vitess/go/vt/topo/topoproto" ) // TestVtctldclientCLI tests the vreplication vtctldclient CLI commands, primarily to check that non-standard flags @@ -395,6 +396,48 @@ func checkTablesExist(t *testing.T, tabletAlias string, tables []string) bool { return true } +func getMirrorRules(t *testing.T) *vschemapb.MirrorRules { + mirrorRules, err := vc.VtctldClient.ExecuteCommandWithOutput("GetMirrorRules") + require.NoError(t, err) + var mirrorRulesResponse vschemapb.MirrorRules + err = protojson.Unmarshal([]byte(mirrorRules), &mirrorRulesResponse) + require.NoError(t, err) + return &mirrorRulesResponse +} + +func confirmNoMirrorRules(t *testing.T) { + mirrorRulesResponse := getMirrorRules(t) + require.Zero(t, len(mirrorRulesResponse.Rules)) +} + +func confirmMirrorRulesExist(t *testing.T) { + mirrorRulesResponse := getMirrorRules(t) + require.NotZero(t, len(mirrorRulesResponse.Rules)) +} + +func expectMirrorRules(t *testing.T, sourceKeyspace, targetKeyspace string, tables []string, tabletTypes []topodatapb.TabletType, percent float32) { + t.Helper() + + // Each table should have a mirror rule for each serving type. + mirrorRules := getMirrorRules(t) + require.Len(t, mirrorRules.Rules, len(tables)*len(tabletTypes)) + fromTableToRule := make(map[string]*vschemapb.MirrorRule) + for _, rule := range mirrorRules.Rules { + fromTableToRule[rule.FromTable] = rule + } + for _, table := range tables { + for _, tabletType := range tabletTypes { + fromTable := fmt.Sprintf("%s.%s", sourceKeyspace, table) + if tabletType != topodatapb.TabletType_PRIMARY { + fromTable = fmt.Sprintf("%s@%s", fromTable, topoproto.TabletTypeLString(tabletType)) + } + require.Contains(t, fromTableToRule, fromTable) + require.Equal(t, fmt.Sprintf("%s.%s", targetKeyspace, table), fromTableToRule[fromTable].ToTable) + require.Equal(t, percent, fromTableToRule[fromTable].Percent) + } + } +} + func getRoutingRules(t *testing.T) *vschemapb.RoutingRules { routingRules, err := vc.VtctldClient.ExecuteCommandWithOutput("GetRoutingRules") require.NoError(t, err) diff --git a/go/test/endtoend/vreplication/wrappers_test.go b/go/test/endtoend/vreplication/wrappers_test.go index e1028fafa9f..96c54b89fe8 100644 --- a/go/test/endtoend/vreplication/wrappers_test.go +++ b/go/test/endtoend/vreplication/wrappers_test.go @@ -29,6 +29,7 @@ import ( type iWorkflow interface { Create() Show() + MirrorTraffic() SwitchReads() SwitchWrites() SwitchReadsAndWrites() @@ -79,6 +80,7 @@ type moveTablesWorkflow struct { lastOutput string createFlags []string completeFlags []string + mirrorFlags []string switchFlags []string showFlags []string } @@ -122,6 +124,11 @@ func (vmt *VtctlMoveTables) Create() { vmt.exec(workflowActionCreate) } +func (vmt *VtctlMoveTables) MirrorTraffic() { + // TODO implement me + panic("implement me") +} + func (vmt *VtctlMoveTables) SwitchReadsAndWrites() { err := tstWorkflowExecVtctl(vmt.vc.t, "", vmt.workflowName, vmt.sourceKeyspace, vmt.targetKeyspace, vmt.tables, workflowActionSwitchTraffic, "", "", "", defaultWorkflowExecOptions) @@ -218,6 +225,12 @@ func (v VtctldMoveTables) Create() { v.exec(args...) } +func (v VtctldMoveTables) MirrorTraffic() { + args := []string{"MirrorTraffic"} + args = append(args, v.mirrorFlags...) + v.exec(args...) +} + func (v VtctldMoveTables) SwitchReadsAndWrites() { args := []string{"SwitchTraffic"} args = append(args, v.switchFlags...) @@ -323,6 +336,11 @@ func (vrs *VtctlReshard) Create() { vrs.exec(workflowActionCreate) } +func (vrs *VtctlReshard) MirrorTraffic() { + // TODO implement me + panic("implement me") +} + func (vrs *VtctlReshard) SwitchReadsAndWrites() { vrs.exec(workflowActionSwitchTraffic) } @@ -411,6 +429,11 @@ func (v VtctldReshard) Create() { v.exec(args...) } +func (v VtctldReshard) MirrorTraffic() { + // TODO implement me + panic("implement me") +} + func (v VtctldReshard) SwitchReadsAndWrites() { args := []string{"SwitchTraffic"} args = append(args, v.switchFlags...) diff --git a/go/test/endtoend/vtcombo/vttest_sample_test.go b/go/test/endtoend/vtcombo/vttest_sample_test.go index daeb5e8deb9..4895c1195b0 100644 --- a/go/test/endtoend/vtcombo/vttest_sample_test.go +++ b/go/test/endtoend/vtcombo/vttest_sample_test.go @@ -130,6 +130,8 @@ func TestStandalone(t *testing.T) { tmp, _ := cmd.([]any) require.Contains(t, tmp[0], "vtcombo") + assertVSchemaExists(t, grpcAddress) + ctx := context.Background() conn, err := vtgateconn.Dial(ctx, grpcAddress) require.NoError(t, err) @@ -160,6 +162,17 @@ func TestStandalone(t *testing.T) { assertTransactionalityAndRollbackObeyed(ctx, t, conn, idStart) } +func assertVSchemaExists(t *testing.T, grpcAddress string) { + tmpCmd := exec.Command("vtctldclient", "--server", grpcAddress, "--compact", "GetVSchema", "routed") + + log.Infof("Running vtctldclient with command: %v", tmpCmd.Args) + + output, err := tmpCmd.CombinedOutput() + require.NoError(t, err, fmt.Sprintf("Output:\n%v", string(output))) + + assert.Equal(t, "{}\n", string(output)) +} + func assertInsertedRowsExist(ctx context.Context, t *testing.T, conn *vtgateconn.VTGateConn, idStart, rowCount int) { cur := conn.Session(ks1+":-80@rdonly", nil) bindVariables := map[string]*querypb.BindVariable{ diff --git a/go/test/endtoend/vtgate/connectiondrain/main_test.go b/go/test/endtoend/vtgate/connectiondrain/main_test.go new file mode 100644 index 00000000000..6dae9b72be9 --- /dev/null +++ b/go/test/endtoend/vtgate/connectiondrain/main_test.go @@ -0,0 +1,187 @@ +/* +Copyright 2024 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 connectiondrain + +import ( + "context" + _ "embed" + "flag" + "os" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/test/endtoend/cluster" + "vitess.io/vitess/go/test/endtoend/utils" +) + +var ( + keyspaceName = "ks" + cell = "zone-1" + + //go:embed schema.sql + schemaSQL string +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + os.Exit(m.Run()) +} + +func setupCluster(t *testing.T) (*cluster.LocalProcessCluster, mysql.ConnParams) { + clusterInstance := cluster.NewCluster(cell, "localhost") + + // Start topo server + err := clusterInstance.StartTopo() + require.NoError(t, err) + + // Start keyspace + keyspace := &cluster.Keyspace{ + Name: keyspaceName, + SchemaSQL: schemaSQL, + } + err = clusterInstance.StartUnshardedKeyspace(*keyspace, 0, false) + require.NoError(t, err) + + // Start vtgate + clusterInstance.VtGateExtraArgs = append(clusterInstance.VtGateExtraArgs, "--mysql-server-drain-onterm", "--onterm_timeout", "30s") + err = clusterInstance.StartVtgate() + require.NoError(t, err) + + vtParams := clusterInstance.GetVTParams(keyspaceName) + return clusterInstance, vtParams +} + +func start(t *testing.T, vtParams mysql.ConnParams) (*mysql.Conn, func()) { + vtConn, err := mysql.Connect(context.Background(), &vtParams) + require.NoError(t, err) + + deleteAll := func() { + _, _ = utils.ExecAllowError(t, vtConn, "set workload = oltp") + + tables := []string{"t1"} + for _, table := range tables { + _, _ = utils.ExecAllowError(t, vtConn, "delete from "+table) + } + } + + deleteAll() + + return vtConn, func() { + deleteAll() + vtConn.Close() + cluster.PanicHandler(t) + } +} + +func TestConnectionDrainCloseConnections(t *testing.T) { + clusterInstance, vtParams := setupCluster(t) + defer clusterInstance.Teardown() + + vtConn, closer := start(t, vtParams) + defer closer() + + // Create a second connection, this connection will be used to create a transaction. + vtConn2, err := mysql.Connect(context.Background(), &vtParams) + require.NoError(t, err) + + // Start the transaction with the second connection + _, err = vtConn2.ExecuteFetch("BEGIN", 1, false) + require.NoError(t, err) + _, err = vtConn2.ExecuteFetch("select id1 from t1", 1, false) + require.NoError(t, err) + + _, err = vtConn.ExecuteFetch("select id1 from t1", 1, false) + require.NoError(t, err) + + // Tearing down vtgate here, from there on vtConn should still be able to conclude in-flight transaction and + // execute queries with idle connections. However, no new connections are allowed. + err = clusterInstance.VtgateProcess.Terminate() + require.NoError(t, err) + + // Give enough time to vtgate to receive and start processing the SIGTERM signal + time.Sleep(2 * time.Second) + + // Create a third connection, this connection should not be allowed. + // Set a connection timeout to 1s otherwise the connection will take forever + // and eventually vtgate will reach the --onterm_timeout. + vtParams.ConnectTimeoutMs = 1000 + defer func() { + vtParams.ConnectTimeoutMs = 0 + }() + _, err = mysql.Connect(context.Background(), &vtParams) + require.Error(t, err) + + // Idle connections should be allowed to execute queries until they are drained + _, err = vtConn.ExecuteFetch("select id1 from t1", 1, false) + require.NoError(t, err) + + // Finish the transaction + _, err = vtConn2.ExecuteFetch("select id1 from t1", 1, false) + require.NoError(t, err) + _, err = vtConn2.ExecuteFetch("COMMIT", 1, false) + require.NoError(t, err) + vtConn2.Close() + + // vtgate should still be running + require.False(t, clusterInstance.VtgateProcess.IsShutdown()) + + // This connection should still be allowed + _, err = vtConn.ExecuteFetch("select id1 from t1", 1, false) + require.NoError(t, err) + vtConn.Close() + + // Give enough time for vtgate to finish all the onterm hooks without reaching the 30s of --onterm_timeout + time.Sleep(10 * time.Second) + + // By now the vtgate should have shutdown on its own and without reaching --onterm_timeout + require.True(t, clusterInstance.VtgateProcess.IsShutdown()) +} + +func TestConnectionDrainOnTermTimeout(t *testing.T) { + clusterInstance, vtParams := setupCluster(t) + defer clusterInstance.Teardown() + + // Connect to vtgate again, this should work + vtConn, err := mysql.Connect(context.Background(), &vtParams) + require.NoError(t, err) + vtConn2, err := mysql.Connect(context.Background(), &vtParams) + require.NoError(t, err) + + defer func() { + vtConn.Close() + vtConn2.Close() + }() + + // Tearing down vtgate here, we want to reach the onterm_timeout of 30s + err = clusterInstance.VtgateProcess.Terminate() + require.NoError(t, err) + + // Run a busy query that returns only after the onterm_timeout is reached, this should fail when we reach the timeout + _, err = vtConn.ExecuteFetch("select sleep(40)", 1, false) + require.Error(t, err) + + // Running a query after we have reached the onterm_timeout should fail + _, err = vtConn2.ExecuteFetch("select id from t1", 1, false) + require.Error(t, err) + + // By now vtgate will be shutdown becaused it reached its onterm_timeout, despite idle connections still being opened + require.True(t, clusterInstance.VtgateProcess.IsShutdown()) +} diff --git a/go/test/endtoend/vtgate/connectiondrain/schema.sql b/go/test/endtoend/vtgate/connectiondrain/schema.sql new file mode 100644 index 00000000000..45db74d062f --- /dev/null +++ b/go/test/endtoend/vtgate/connectiondrain/schema.sql @@ -0,0 +1,5 @@ +create table t1( + id1 bigint, + id2 bigint, + primary key(id1) +) Engine=InnoDB; diff --git a/go/test/endtoend/vtgate/queries/aggregation/aggregation_test.go b/go/test/endtoend/vtgate/queries/aggregation/aggregation_test.go index 531e1077bf6..9a6ad90cc5b 100644 --- a/go/test/endtoend/vtgate/queries/aggregation/aggregation_test.go +++ b/go/test/endtoend/vtgate/queries/aggregation/aggregation_test.go @@ -18,6 +18,7 @@ package aggregation import ( "fmt" + "math/rand/v2" "slices" "sort" "strings" @@ -69,6 +70,18 @@ func start(t *testing.T) (utils.MySQLCompare, func()) { } } +func TestAggrWithLimit(t *testing.T) { + utils.SkipIfBinaryIsBelowVersion(t, 21, "vtgate") + mcmp, closer := start(t) + defer closer() + + for i := range 1000 { + r := rand.IntN(50) + mcmp.Exec(fmt.Sprintf("insert into aggr_test(id, val1, val2) values(%d, 'a', %d)", i, r)) + } + mcmp.Exec("select val2, count(*) from aggr_test group by val2 order by count(*), val2 limit 10") +} + func TestAggregateTypes(t *testing.T) { mcmp, closer := start(t) defer closer() @@ -777,3 +790,15 @@ func TestHavingQueries(t *testing.T) { }) } } + +// TestJsonAggregation tests that json aggregation works for single sharded queries. +func TestJsonAggregation(t *testing.T) { + utils.SkipIfBinaryIsBelowVersion(t, 21, "vtgate") + mcmp, closer := start(t) + defer closer() + + mcmp.Exec("insert into t3(id5, id6, id7) values(1,2,1), (2,2,4), (3,2,4), (4,1,2), (5,2,1), (6,2,6), (7,1,7)") + + mcmp.Exec("select count(1) from t3 where id6 = 2 group by id7 having json_arrayagg(id5+1) = json_array(2, 6)") + mcmp.Exec(`select count(1) from t3 where id6 = 2 group by id7 having json_objectagg(id5+1, id7) = json_object("2",1,"6",1)`) +} diff --git a/go/test/endtoend/vtgate/queries/benchmark/benchmark_test.go b/go/test/endtoend/vtgate/queries/benchmark/benchmark_test.go index 9a064c1769a..b76ae5a35c7 100644 --- a/go/test/endtoend/vtgate/queries/benchmark/benchmark_test.go +++ b/go/test/endtoend/vtgate/queries/benchmark/benchmark_test.go @@ -32,6 +32,35 @@ type testQuery struct { intTyp []bool } +var deleteUser, deleteUserExtra = "delete from user", "delete from user_extra" + +func generateInserts(userSize int, userExtraSize int) (string, string) { + var userInserts []string + var userExtraInserts []string + + // Generate user table inserts + for i := 1; i <= userSize; i++ { + id := i + notShardingKey := i + typeValue := i % 5 // Just an example for type values + teamID := i%userExtraSize + 1 // To ensure team_id references user_extra id + userInserts = append(userInserts, fmt.Sprintf("(%d, %d, %d, %d)", id, notShardingKey, typeValue, teamID)) + } + + // Generate user_extra table inserts + for i := 1; i <= userExtraSize; i++ { + id := i + notShardingKey := i + colValue := fmt.Sprintf("col_value_%d", i) + userExtraInserts = append(userExtraInserts, fmt.Sprintf("(%d, %d, '%s')", id, notShardingKey, colValue)) + } + + userInsertStatement := fmt.Sprintf("INSERT INTO user (id, not_sharding_key, type, team_id) VALUES %s;", strings.Join(userInserts, ", ")) + userExtraInsertStatement := fmt.Sprintf("INSERT INTO user_extra (id, not_sharding_key, col) VALUES %s;", strings.Join(userExtraInserts, ", ")) + + return userInsertStatement, userExtraInsertStatement +} + func (tq *testQuery) getInsertQuery(rows int) string { var allRows []string for i := 0; i < rows; i++ { @@ -146,3 +175,25 @@ func BenchmarkShardedTblDeleteIn(b *testing.B) { }) } } + +func BenchmarkShardedAggrPushDown(b *testing.B) { + conn, closer := start(b) + defer closer() + + sizes := []int{100, 500, 1000} + + for _, user := range sizes { + for _, userExtra := range sizes { + insert1, insert2 := generateInserts(user, userExtra) + _ = utils.Exec(b, conn, insert1) + _ = utils.Exec(b, conn, insert2) + b.Run(fmt.Sprintf("user-%d-user_extra-%d", user, userExtra), func(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = utils.Exec(b, conn, "select sum(user.type) from user join user_extra on user.team_id = user_extra.id group by user_extra.id order by user_extra.id") + } + }) + _ = utils.Exec(b, conn, deleteUser) + _ = utils.Exec(b, conn, deleteUserExtra) + } + } +} diff --git a/go/test/endtoend/vtgate/queries/benchmark/sharded_schema.sql b/go/test/endtoend/vtgate/queries/benchmark/sharded_schema.sql index 850b6ffc15a..92f63c40f0f 100644 --- a/go/test/endtoend/vtgate/queries/benchmark/sharded_schema.sql +++ b/go/test/endtoend/vtgate/queries/benchmark/sharded_schema.sql @@ -1,16 +1,33 @@ create table tbl_no_lkp_vdx ( id bigint, - c1 varchar(50), - c2 varchar(50), - c3 varchar(50), - c4 varchar(50), - c5 varchar(50), - c6 varchar(50), - c7 varchar(50), - c8 varchar(50), - c9 varchar(50), + c1 varchar(50), + c2 varchar(50), + c3 varchar(50), + c4 varchar(50), + c5 varchar(50), + c6 varchar(50), + c7 varchar(50), + c8 varchar(50), + c9 varchar(50), c10 varchar(50), c11 varchar(50), c12 varchar(50) -) Engine = InnoDB; \ No newline at end of file +) Engine = InnoDB; + +create table user +( + id bigint, + not_sharding_key bigint, + type int, + team_id int, + primary key (id) +); + +create table user_extra +( + id bigint, + not_sharding_key bigint, + col varchar(50), + primary key (id) +); \ No newline at end of file diff --git a/go/test/endtoend/vtgate/queries/benchmark/vschema.json b/go/test/endtoend/vtgate/queries/benchmark/vschema.json index 4970e8b7437..efc854af8ff 100644 --- a/go/test/endtoend/vtgate/queries/benchmark/vschema.json +++ b/go/test/endtoend/vtgate/queries/benchmark/vschema.json @@ -13,6 +13,22 @@ "name": "xxhash" } ] + }, + "user": { + "column_vindexes": [ + { + "column": "id", + "name": "xxhash" + } + ] + }, + "user_extra": { + "column_vindexes": [ + { + "column": "id", + "name": "xxhash" + } + ] } } } \ No newline at end of file diff --git a/go/test/endtoend/vtgate/queries/normalize/normalize_test.go b/go/test/endtoend/vtgate/queries/normalize/normalize_test.go index 51d9f9f24bf..f7d6f45a784 100644 --- a/go/test/endtoend/vtgate/queries/normalize/normalize_test.go +++ b/go/test/endtoend/vtgate/queries/normalize/normalize_test.go @@ -28,7 +28,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "vitess.io/vitess/go/test/endtoend/cluster" "vitess.io/vitess/go/test/endtoend/utils" "vitess.io/vitess/go/mysql" @@ -41,11 +40,7 @@ func TestNormalizeAllFields(t *testing.T) { insertQuery := `insert into t1 values (1, "chars", "variable chars", x'73757265', 0x676F, 0.33, 9.99, 1, "1976-06-08", "small", "b", "{\"key\":\"value\"}", point(1,5), b'011', 0b0101)` normalizedInsertQuery := `insert into t1 values (:vtg1 /* INT64 */, :vtg2 /* VARCHAR */, :vtg3 /* VARCHAR */, :vtg4 /* HEXVAL */, :vtg5 /* HEXNUM */, :vtg6 /* DECIMAL(3,2) */, :vtg7 /* DECIMAL(3,2) */, :vtg8 /* INT64 */, :vtg9 /* VARCHAR */, :vtg10 /* VARCHAR */, :vtg11 /* VARCHAR */, :vtg12 /* VARCHAR */, point(:vtg13 /* INT64 */, :vtg14 /* INT64 */), :vtg15 /* BITNUM */, :vtg16 /* BITNUM */)` - vtgateVersion, err := cluster.GetMajorVersion("vtgate") - require.NoError(t, err) - if vtgateVersion < 20 { - normalizedInsertQuery = `insert into t1 values (:vtg1 /* INT64 */, :vtg2 /* VARCHAR */, :vtg3 /* VARCHAR */, :vtg4 /* HEXVAL */, :vtg5 /* HEXNUM */, :vtg6 /* DECIMAL */, :vtg7 /* DECIMAL */, :vtg8 /* INT64 */, :vtg9 /* VARCHAR */, :vtg10 /* VARCHAR */, :vtg11 /* VARCHAR */, :vtg12 /* VARCHAR */, point(:vtg13 /* INT64 */, :vtg14 /* INT64 */), :vtg15 /* BITNUM */, :vtg16 /* BITNUM */)` - } + selectQuery := "select * from t1" utils.Exec(t, conn, insertQuery) qr := utils.Exec(t, conn, selectQuery) diff --git a/go/test/endtoend/vtgate/queries/subquery/subquery_test.go b/go/test/endtoend/vtgate/queries/subquery/subquery_test.go index abbf5ff15e8..eb949e1c697 100644 --- a/go/test/endtoend/vtgate/queries/subquery/subquery_test.go +++ b/go/test/endtoend/vtgate/queries/subquery/subquery_test.go @@ -23,6 +23,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/test/endtoend/cluster" "vitess.io/vitess/go/test/endtoend/utils" ) @@ -34,7 +36,7 @@ func start(t *testing.T) (utils.MySQLCompare, func()) { deleteAll := func() { _, _ = utils.ExecAllowError(t, mcmp.VtConn, "set workload = oltp") - tables := []string{"t1", "t1_id2_idx", "t2", "t2_id4_idx"} + tables := []string{"t1", "t1_id2_idx", "t2", "t2_id4_idx", "user", "user_extra"} for _, table := range tables { _, _ = mcmp.ExecAndIgnore("delete from " + table) } @@ -78,9 +80,7 @@ func TestNotINQueries(t *testing.T) { } -// Test only supported in >= v16.0.0 func TestSubqueriesExists(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 16, "vtgate") mcmp, closer := start(t) defer closer() @@ -232,3 +232,18 @@ func TestSubqueries(t *testing.T) { }) } } + +func TestProperTypesOfPullOutValue(t *testing.T) { + utils.SkipIfBinaryIsBelowVersion(t, 21, "vtgate") + + query := "select (select sum(id) from user) from user_extra" + + mcmp, closer := start(t) + defer closer() + + mcmp.Exec("INSERT INTO user (id, name) VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Charlie'), (4, 'David'), (5, 'Eve'), (6, 'Frank'), (7, 'Grace'), (8, 'Hannah'), (9, 'Ivy'), (10, 'Jack')") + mcmp.Exec("INSERT INTO user_extra (user_id, extra_info) VALUES (1, 'info1'), (2, 'info1'), (3, 'info1'), (3, 'info2'), (4, 'info1'), (5, 'info1'), (6, 'info1'), (7, 'info1'), (8, 'info1')") + + r := mcmp.Exec(query) + require.True(t, r.Fields[0].Type == sqltypes.Decimal) +} diff --git a/go/test/endtoend/vtgate/reservedconn/main_test.go b/go/test/endtoend/vtgate/reservedconn/main_test.go index 528182a82e2..8c0278604f7 100644 --- a/go/test/endtoend/vtgate/reservedconn/main_test.go +++ b/go/test/endtoend/vtgate/reservedconn/main_test.go @@ -100,61 +100,46 @@ CREATE TABLE test_vdx ( ` ) -var enableSettingsPool bool - func TestMain(m *testing.M) { defer cluster.PanicHandler(nil) flag.Parse() - code := runAllTests(m) - if code != 0 { - os.Exit(code) - } + exitCode := func() int { + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() - println("running with settings pool enabled") - // run again with settings pool enabled. - enableSettingsPool = true - code = runAllTests(m) - os.Exit(code) -} + // Start topo server + if err := clusterInstance.StartTopo(); err != nil { + return 1 + } -func runAllTests(m *testing.M) int { - clusterInstance = cluster.NewCluster(cell, hostname) - defer clusterInstance.Teardown() - - // Start topo server - if err := clusterInstance.StartTopo(); err != nil { - return 1 - } - - // Start keyspace - keyspace := &cluster.Keyspace{ - Name: keyspaceName, - SchemaSQL: sqlSchema, - VSchema: vSchema, - } - clusterInstance.VtTabletExtraArgs = []string{"--queryserver-config-transaction-timeout", "5s"} - if enableSettingsPool { - clusterInstance.VtTabletExtraArgs = append(clusterInstance.VtTabletExtraArgs, "--queryserver-enable-settings-pool") - } - if err := clusterInstance.StartKeyspace(*keyspace, []string{"-80", "80-"}, 1, false); err != nil { - return 1 - } - - // Start vtgate - // This test requires setting the mysql_server_version vtgate flag - // to 5.7 regardless of the actual MySQL version used for the tests. - clusterInstance.VtGateExtraArgs = []string{"--lock_heartbeat_time", "2s", "--mysql_server_version", "5.7.0"} - clusterInstance.VtGatePlannerVersion = querypb.ExecuteOptions_Gen4 - if err := clusterInstance.StartVtgate(); err != nil { - return 1 - } - - vtParams = mysql.ConnParams{ - Host: clusterInstance.Hostname, - Port: clusterInstance.VtgateMySQLPort, - } - return m.Run() + // Start keyspace + keyspace := &cluster.Keyspace{ + Name: keyspaceName, + SchemaSQL: sqlSchema, + VSchema: vSchema, + } + clusterInstance.VtTabletExtraArgs = []string{"--queryserver-config-transaction-timeout", "5s"} + if err := clusterInstance.StartKeyspace(*keyspace, []string{"-80", "80-"}, 1, false); err != nil { + return 1 + } + + // Start vtgate + // This test requires setting the mysql_server_version vtgate flag + // to 5.7 regardless of the actual MySQL version used for the tests. + clusterInstance.VtGateExtraArgs = []string{"--lock_heartbeat_time", "2s", "--mysql_server_version", "5.7.0"} + clusterInstance.VtGatePlannerVersion = querypb.ExecuteOptions_Gen4 + if err := clusterInstance.StartVtgate(); err != nil { + return 1 + } + + vtParams = mysql.ConnParams{ + Host: clusterInstance.Hostname, + Port: clusterInstance.VtgateMySQLPort, + } + return m.Run() + }() + os.Exit(exitCode) } func assertIsEmpty(t *testing.T, conn *mysql.Conn, query string) { diff --git a/go/test/endtoend/vtgate/reservedconn/reconnect1/main_test.go b/go/test/endtoend/vtgate/reservedconn/reconnect1/main_test.go index 491ce6bc6ab..9a4d7c50dbd 100644 --- a/go/test/endtoend/vtgate/reservedconn/reconnect1/main_test.go +++ b/go/test/endtoend/vtgate/reservedconn/reconnect1/main_test.go @@ -62,58 +62,42 @@ var ( ` ) -var enableSettingsPool bool - func TestMain(m *testing.M) { defer cluster.PanicHandler(nil) flag.Parse() - code := runAllTests(m) - if code != 0 { - os.Exit(code) - } - - println("running with settings pool enabled") - // run again with settings pool enabled. - enableSettingsPool = true - code = runAllTests(m) - os.Exit(code) -} - -func runAllTests(m *testing.M) int { + exitCode := func() int { + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() - clusterInstance = cluster.NewCluster(cell, hostname) - defer clusterInstance.Teardown() - - // Start topo server - if err := clusterInstance.StartTopo(); err != nil { - return 1 - } + // Start topo server + if err := clusterInstance.StartTopo(); err != nil { + return 1 + } - // Start keyspace - keyspace := &cluster.Keyspace{ - Name: keyspaceName, - SchemaSQL: sqlSchema, - VSchema: vSchema, - } - if enableSettingsPool { - clusterInstance.VtTabletExtraArgs = append(clusterInstance.VtTabletExtraArgs, "--queryserver-enable-settings-pool") - } - if err := clusterInstance.StartKeyspace(*keyspace, []string{"-80", "80-"}, 1, true); err != nil { - return 1 - } + // Start keyspace + keyspace := &cluster.Keyspace{ + Name: keyspaceName, + SchemaSQL: sqlSchema, + VSchema: vSchema, + } + if err := clusterInstance.StartKeyspace(*keyspace, []string{"-80", "80-"}, 1, true); err != nil { + return 1 + } - // Start vtgate - clusterInstance.VtGateExtraArgs = []string{"--lock_heartbeat_time", "2s"} - if err := clusterInstance.StartVtgate(); err != nil { - return 1 - } + // Start vtgate + clusterInstance.VtGateExtraArgs = []string{"--lock_heartbeat_time", "2s"} + if err := clusterInstance.StartVtgate(); err != nil { + return 1 + } - vtParams = mysql.ConnParams{ - Host: clusterInstance.Hostname, - Port: clusterInstance.VtgateMySQLPort, - } - return m.Run() + vtParams = mysql.ConnParams{ + Host: clusterInstance.Hostname, + Port: clusterInstance.VtgateMySQLPort, + } + return m.Run() + }() + os.Exit(exitCode) } func TestServingChange(t *testing.T) { diff --git a/go/test/endtoend/vtgate/reservedconn/reconnect2/main_test.go b/go/test/endtoend/vtgate/reservedconn/reconnect2/main_test.go index a448574c282..915d76051a4 100644 --- a/go/test/endtoend/vtgate/reservedconn/reconnect2/main_test.go +++ b/go/test/endtoend/vtgate/reservedconn/reconnect2/main_test.go @@ -63,58 +63,44 @@ var ( ` ) -var enableSettingsPool bool - func TestMain(m *testing.M) { defer cluster.PanicHandler(nil) flag.Parse() - code := runAllTests(m) - if code != 0 { - os.Exit(code) - } + exitCode := func() int { + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() - println("running with settings pool enabled") - // run again with settings pool enabled. - enableSettingsPool = true - code = runAllTests(m) - os.Exit(code) -} + // Start topo server + if err := clusterInstance.StartTopo(); err != nil { + return 1 + } + + // Start keyspace + keyspace := &cluster.Keyspace{ + Name: keyspaceName, + SchemaSQL: sqlSchema, + VSchema: vSchema, + } + clusterInstance.VtTabletExtraArgs = []string{"--queryserver-config-transaction-timeout", "5s"} + if err := clusterInstance.StartKeyspace(*keyspace, []string{"-80", "80-"}, 1, true); err != nil { + return 1 + } + + // Start vtgate + clusterInstance.VtGateExtraArgs = []string{"--lock_heartbeat_time", "2s"} + if err := clusterInstance.StartVtgate(); err != nil { + return 1 + } + + vtParams = mysql.ConnParams{ + Host: clusterInstance.Hostname, + Port: clusterInstance.VtgateMySQLPort, + } + return m.Run() + }() + os.Exit(exitCode) -func runAllTests(m *testing.M) int { - clusterInstance = cluster.NewCluster(cell, hostname) - defer clusterInstance.Teardown() - - // Start topo server - if err := clusterInstance.StartTopo(); err != nil { - return 1 - } - - // Start keyspace - keyspace := &cluster.Keyspace{ - Name: keyspaceName, - SchemaSQL: sqlSchema, - VSchema: vSchema, - } - clusterInstance.VtTabletExtraArgs = []string{"--queryserver-config-transaction-timeout", "5s"} - if enableSettingsPool { - clusterInstance.VtTabletExtraArgs = append(clusterInstance.VtTabletExtraArgs, "--queryserver-enable-settings-pool") - } - if err := clusterInstance.StartKeyspace(*keyspace, []string{"-80", "80-"}, 1, true); err != nil { - return 1 - } - - // Start vtgate - clusterInstance.VtGateExtraArgs = []string{"--lock_heartbeat_time", "2s"} - if err := clusterInstance.StartVtgate(); err != nil { - return 1 - } - - vtParams = mysql.ConnParams{ - Host: clusterInstance.Hostname, - Port: clusterInstance.VtgateMySQLPort, - } - return m.Run() } func TestTabletChange(t *testing.T) { diff --git a/go/test/endtoend/vtgate/reservedconn/reconnect3/main_test.go b/go/test/endtoend/vtgate/reservedconn/reconnect3/main_test.go index 677c24666b2..20d255941db 100644 --- a/go/test/endtoend/vtgate/reservedconn/reconnect3/main_test.go +++ b/go/test/endtoend/vtgate/reservedconn/reconnect3/main_test.go @@ -39,55 +39,40 @@ var ( sqlSchema = `create table test(id bigint primary key)Engine=InnoDB;` ) -var enableSettingsPool bool - func TestMain(m *testing.M) { defer cluster.PanicHandler(nil) flag.Parse() - code := runAllTests(m) - if code != 0 { - os.Exit(code) - } - - println("running with settings pool enabled") - // run again with settings pool enabled. - enableSettingsPool = true - code = runAllTests(m) - os.Exit(code) -} - -func runAllTests(m *testing.M) int { - clusterInstance = cluster.NewCluster(cell, hostname) - defer clusterInstance.Teardown() - - // Start topo server - if err := clusterInstance.StartTopo(); err != nil { - return 1 - } - - // Start keyspace - keyspace := &cluster.Keyspace{ - Name: keyspaceName, - SchemaSQL: sqlSchema, - } - if enableSettingsPool { - clusterInstance.VtTabletExtraArgs = append(clusterInstance.VtTabletExtraArgs, "--queryserver-enable-settings-pool") - } - if err := clusterInstance.StartUnshardedKeyspace(*keyspace, 2, false); err != nil { - return 1 - } - - // Start vtgate - if err := clusterInstance.StartVtgate(); err != nil { - return 1 - } - - vtParams = mysql.ConnParams{ - Host: clusterInstance.Hostname, - Port: clusterInstance.VtgateMySQLPort, - } - return m.Run() + exitCode := func() int { + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() + + // Start topo server + if err := clusterInstance.StartTopo(); err != nil { + return 1 + } + + // Start keyspace + keyspace := &cluster.Keyspace{ + Name: keyspaceName, + SchemaSQL: sqlSchema, + } + if err := clusterInstance.StartUnshardedKeyspace(*keyspace, 2, false); err != nil { + return 1 + } + + // Start vtgate + if err := clusterInstance.StartVtgate(); err != nil { + return 1 + } + + vtParams = mysql.ConnParams{ + Host: clusterInstance.Hostname, + Port: clusterInstance.VtgateMySQLPort, + } + return m.Run() + }() + os.Exit(exitCode) } func TestMysqlDownServingChange(t *testing.T) { diff --git a/go/test/endtoend/vtgate/reservedconn/reconnect4/main_test.go b/go/test/endtoend/vtgate/reservedconn/reconnect4/main_test.go index 1dc53a89506..d4a61665a6d 100644 --- a/go/test/endtoend/vtgate/reservedconn/reconnect4/main_test.go +++ b/go/test/endtoend/vtgate/reservedconn/reconnect4/main_test.go @@ -39,55 +39,40 @@ var ( sqlSchema = `create table test(id bigint primary key)Engine=InnoDB;` ) -var enableSettingsPool bool - func TestMain(m *testing.M) { defer cluster.PanicHandler(nil) flag.Parse() - code := runAllTests(m) - if code != 0 { - os.Exit(code) - } - - println("running with settings pool enabled") - // run again with settings pool enabled. - enableSettingsPool = true - code = runAllTests(m) - os.Exit(code) -} - -func runAllTests(m *testing.M) int { - clusterInstance = cluster.NewCluster(cell, hostname) - defer clusterInstance.Teardown() - - // Start topo server - if err := clusterInstance.StartTopo(); err != nil { - return 1 - } - - // Start keyspace - keyspace := &cluster.Keyspace{ - Name: keyspaceName, - SchemaSQL: sqlSchema, - } - if enableSettingsPool { - clusterInstance.VtTabletExtraArgs = append(clusterInstance.VtTabletExtraArgs, "--queryserver-enable-settings-pool") - } - if err := clusterInstance.StartUnshardedKeyspace(*keyspace, 2, false); err != nil { - return 1 - } - - // Start vtgate - if err := clusterInstance.StartVtgate(); err != nil { - return 1 - } - - vtParams = mysql.ConnParams{ - Host: clusterInstance.Hostname, - Port: clusterInstance.VtgateMySQLPort, - } - return m.Run() + exitCode := func() int { + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() + + // Start topo server + if err := clusterInstance.StartTopo(); err != nil { + return 1 + } + + // Start keyspace + keyspace := &cluster.Keyspace{ + Name: keyspaceName, + SchemaSQL: sqlSchema, + } + if err := clusterInstance.StartUnshardedKeyspace(*keyspace, 2, false); err != nil { + return 1 + } + + // Start vtgate + if err := clusterInstance.StartVtgate(); err != nil { + return 1 + } + + vtParams = mysql.ConnParams{ + Host: clusterInstance.Hostname, + Port: clusterInstance.VtgateMySQLPort, + } + return m.Run() + }() + os.Exit(exitCode) } func TestVttabletDownServingChange(t *testing.T) { diff --git a/go/test/endtoend/vtgate/schematracker/sharded/st_sharded_test.go b/go/test/endtoend/vtgate/schematracker/sharded/st_sharded_test.go index 8f8050bebe1..4c495d257b5 100644 --- a/go/test/endtoend/vtgate/schematracker/sharded/st_sharded_test.go +++ b/go/test/endtoend/vtgate/schematracker/sharded/st_sharded_test.go @@ -296,9 +296,6 @@ func TestDMLOnNewTable(t *testing.T) { // TestNewView validates that view tracking works as expected. func TestNewView(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 16, "vtgate") - utils.SkipIfBinaryIsBelowVersion(t, 16, "vttablet") - ctx := context.Background() conn, err := mysql.Connect(ctx, &vtParams) require.NoError(t, err) @@ -321,9 +318,6 @@ func TestNewView(t *testing.T) { // TestViewAndTable validates that new column added in table is present in the view definition func TestViewAndTable(t *testing.T) { - utils.SkipIfBinaryIsBelowVersion(t, 16, "vtgate") - utils.SkipIfBinaryIsBelowVersion(t, 16, "vttablet") - ctx := context.Background() conn, err := mysql.Connect(ctx, &vtParams) require.NoError(t, err) diff --git a/go/test/endtoend/vtgate/unsharded/main_test.go b/go/test/endtoend/vtgate/unsharded/main_test.go index 461a3c73b35..91326acce4d 100644 --- a/go/test/endtoend/vtgate/unsharded/main_test.go +++ b/go/test/endtoend/vtgate/unsharded/main_test.go @@ -146,62 +146,47 @@ END; `} ) -var enableSettingsPool bool - func TestMain(m *testing.M) { defer cluster.PanicHandler(nil) flag.Parse() - code := runAllTests(m) - if code != 0 { - os.Exit(code) - } - - println("running with settings pool enabled") - // run again with settings pool enabled. - enableSettingsPool = true - code = runAllTests(m) - os.Exit(code) -} - -func runAllTests(m *testing.M) int { - clusterInstance = cluster.NewCluster(cell, hostname) - defer clusterInstance.Teardown() - - // Start topo server - if err := clusterInstance.StartTopo(); err != nil { - return 1 - } - - // Start keyspace - Keyspace := &cluster.Keyspace{ - Name: KeyspaceName, - SchemaSQL: SchemaSQL, - VSchema: VSchema, - } - clusterInstance.VtTabletExtraArgs = []string{"--queryserver-config-transaction-timeout", "3s", "--queryserver-config-max-result-size", "30"} - if enableSettingsPool { - clusterInstance.VtTabletExtraArgs = append(clusterInstance.VtTabletExtraArgs, "--queryserver-enable-settings-pool") - } - if err := clusterInstance.StartUnshardedKeyspace(*Keyspace, 0, false); err != nil { - log.Fatal(err.Error()) - return 1 - } - - // Start vtgate - clusterInstance.VtGateExtraArgs = []string{"--warn_sharded_only=true"} - if err := clusterInstance.StartVtgate(); err != nil { - log.Fatal(err.Error()) - return 1 - } - - primaryTablet := clusterInstance.Keyspaces[0].Shards[0].PrimaryTablet().VttabletProcess - if err := primaryTablet.QueryTabletMultiple(createProcSQL, KeyspaceName, true); err != nil { - log.Fatal(err.Error()) - return 1 - } - - return m.Run() + exitCode := func() int { + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() + + // Start topo server + if err := clusterInstance.StartTopo(); err != nil { + return 1 + } + + // Start keyspace + Keyspace := &cluster.Keyspace{ + Name: KeyspaceName, + SchemaSQL: SchemaSQL, + VSchema: VSchema, + } + clusterInstance.VtTabletExtraArgs = []string{"--queryserver-config-transaction-timeout", "3s", "--queryserver-config-max-result-size", "30"} + if err := clusterInstance.StartUnshardedKeyspace(*Keyspace, 0, false); err != nil { + log.Fatal(err.Error()) + return 1 + } + + // Start vtgate + clusterInstance.VtGateExtraArgs = []string{"--warn_sharded_only=true"} + if err := clusterInstance.StartVtgate(); err != nil { + log.Fatal(err.Error()) + return 1 + } + + primaryTablet := clusterInstance.Keyspaces[0].Shards[0].PrimaryTablet().VttabletProcess + if err := primaryTablet.QueryTabletMultiple(createProcSQL, KeyspaceName, true); err != nil { + log.Fatal(err.Error()) + return 1 + } + + return m.Run() + }() + os.Exit(exitCode) } func TestSelectIntoAndLoadFrom(t *testing.T) { diff --git a/go/test/endtoend/vtgate/vitess_tester/aggregation/aggregation.test b/go/test/endtoend/vtgate/vitess_tester/aggregation/aggregation.test new file mode 100644 index 00000000000..f4c82933d91 --- /dev/null +++ b/go/test/endtoend/vtgate/vitess_tester/aggregation/aggregation.test @@ -0,0 +1,64 @@ +CREATE TABLE `t1` +( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(191) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE InnoDB, + CHARSET utf8mb4, + COLLATE utf8mb4_unicode_ci; + +CREATE TABLE `t2` +( + `id` bigint unsigned NOT NULL AUTO_INCREMENT, + `t1_id` int unsigned NOT NULL, + PRIMARY KEY (`id`) +) ENGINE InnoDB, + CHARSET utf8mb4, + COLLATE utf8mb4_unicode_ci; + +CREATE TABLE `t3` +( + `id` bigint unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(191) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE InnoDB, + CHARSET utf8mb4, + COLLATE utf8mb4_unicode_ci; + +insert into t1 (id, name) +values (1, 'A'), + (2, 'B'), + (3, 'C'), + (4, 'D'); + +insert into t2 (id, t1_id) +values (1, 1), + (2, 2), + (3, 3); + +insert into t3 (id, name) +values (1, 'A'), + (2, 'B'), + (3, 'B'), + (4, 'B'), + (5, 'B'); + +-- wait_authoritative t1 +-- wait_authoritative t2 +-- wait_authoritative t3 +select group_concat(t3.name SEPARATOR ', ') as "Group Name" +from t1 + join t2 on t1.id = t2.t1_id + left join t3 on t1.id = t3.id +group by t1.id; + +select COUNT(*) +from (select 1 as one + FROM `t3` + WHERE `t3`.`name` = 'B' + ORDER BY id DESC + LIMIT 25 OFFSET 0) subquery_for_count; + +select u.id, u.t1_id, t.num_segments +from (select id, count(*) as num_segments from t1 group by 1 order by 2 desc limit 20) t + join t2 u on u.id = t.id; \ No newline at end of file diff --git a/go/test/endtoend/vtgate/vitess_tester/join/join.test b/go/test/endtoend/vtgate/vitess_tester/join/join.test new file mode 100644 index 00000000000..cffd3a1b3aa --- /dev/null +++ b/go/test/endtoend/vtgate/vitess_tester/join/join.test @@ -0,0 +1,49 @@ +CREATE TABLE `t1` +( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(191) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE InnoDB, + CHARSET utf8mb4, + COLLATE utf8mb4_unicode_ci; + +CREATE TABLE `t2` +( + `id` bigint unsigned NOT NULL AUTO_INCREMENT, + `t1_id` int unsigned NOT NULL, + PRIMARY KEY (`id`) +) ENGINE InnoDB, + CHARSET utf8mb4, + COLLATE utf8mb4_unicode_ci; + +CREATE TABLE `t3` +( + `id` bigint unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(191) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE InnoDB, + CHARSET utf8mb4, + COLLATE utf8mb4_unicode_ci; + +insert into t1 (id, name) +values (1, 'A'), + (2, 'B'), + (3, 'C'), + (4, 'D'); + +insert into t2 (id, t1_id) +values (1, 1), + (2, 2), + (3, 3); + +insert into t3 (id, name) +values (1, 'A'), + (2, 'B'), + (3, 'B'), + (4, 'B'), + (5, 'B'); + +-- wait_authoritative t1 +-- wait_authoritative t2 +-- wait_authoritative t3 +select 42 from t1 join t2 on t1.id = t2.t1_id join t3 on t1.id = t3.id where t1.name or t2.id or t3.name; diff --git a/go/test/endtoend/vtgate/vitess_tester/join/vschema.json b/go/test/endtoend/vtgate/vitess_tester/join/vschema.json new file mode 100644 index 00000000000..b922d3f760c --- /dev/null +++ b/go/test/endtoend/vtgate/vitess_tester/join/vschema.json @@ -0,0 +1,38 @@ +{ + "keyspaces": { + "joinks": { + "sharded": true, + "vindexes": { + "hash": { + "type": "hash" + } + }, + "tables": { + "t1": { + "column_vindexes": [ + { + "column": "id", + "name": "hash" + } + ] + }, + "t2": { + "column_vindexes": [ + { + "column": "t1_id", + "name": "hash" + } + ] + }, + "t3": { + "column_vindexes": [ + { + "column": "id", + "name": "hash" + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/go/test/endtoend/vtgate/vitess_tester/subquery/subquery.test b/go/test/endtoend/vtgate/vitess_tester/subquery/subquery.test new file mode 100644 index 00000000000..8f86f2a2cf1 --- /dev/null +++ b/go/test/endtoend/vtgate/vitess_tester/subquery/subquery.test @@ -0,0 +1,42 @@ +create table t1 +( + id1 bigint, + id2 bigint, + primary key (id1) +) Engine = InnoDB; + +create table t2 +( + id3 bigint, + id4 bigint, + primary key (id3) +) Engine = InnoDB; + +INSERT INTO t1 (id1, id2) VALUES +(0, 0), +(1, 1), +(2, 2), +(3, 3), +(4, 4); + +INSERT INTO t2 (id3, id4) VALUES +(0, 0), +(1, 1); + +# Aggregation query with multiple expressions one of which is an IN subquery. +SELECT count(*) FROM t1 WHERE id1 = 0 AND id1 IN (SELECT id4 FROM t2); +# Aggregation query with a complex expression that has an IN subquery. +SELECT count(*) FROM t1 WHERE id1 = 2 OR id1 IN (SELECT id4 FROM t2); +# Aggregation query with multiple expressions one of which is an IN subquery that returns empty results. +SELECT count(*) FROM t1 WHERE id1 = 0 AND id1 IN (SELECT id4 FROM t2 where id4 = 3); +# Aggregation query with a complex expression that has an IN subquery that returns empty results. +SELECT count(*) FROM t1 WHERE id1 = 2 OR id1 IN (SELECT id4 FROM t2 where id4 = 3); + +# Aggregation query with multiple expressions one of which is an NOT IN subquery. +SELECT count(*) FROM t1 WHERE id1 = 2 AND id1 NOT IN (SELECT id4 FROM t2); +# Aggregation query with a complex expression that has an NOT IN subquery. +SELECT count(*) FROM t1 WHERE id1 = 0 OR id1 NOT IN (SELECT id4 FROM t2); +# Aggregation query with multiple expressions one of which is an NOT IN subquery that returns empty results. +SELECT count(*) FROM t1 WHERE id1 = 2 AND id1 NOT IN (SELECT id4 FROM t2 where id4 = 3); +# Aggregation query with a complex expression that has an NOT IN subquery that returns empty results. +SELECT count(*) FROM t1 WHERE id1 = 0 OR id1 NOT IN (SELECT id4 FROM t2 where id4 = 3); \ No newline at end of file diff --git a/go/test/utils/noleak.go b/go/test/utils/noleak.go index 31d454ec789..41e1a42b960 100644 --- a/go/test/utils/noleak.go +++ b/go/test/utils/noleak.go @@ -81,6 +81,7 @@ func ensureNoGoroutines() error { goleak.IgnoreTopFunction("vitess.io/vitess/go/vt/logutil.(*ThrottledLogger).log.func1"), goleak.IgnoreTopFunction("vitess.io/vitess/go/vt/vttablet/tabletserver/throttle.initThrottleTicker.func1.1"), goleak.IgnoreTopFunction("vitess.io/vitess/go/vt/vttablet/tabletserver/throttle.NewBackgroundClient.initThrottleTicker.func1.1"), + goleak.IgnoreTopFunction("vitess.io/vitess/go/stats.(*Rates).track"), goleak.IgnoreTopFunction("testing.tRunner.func1"), } diff --git a/go/timer/rate_limiter.go b/go/timer/rate_limiter.go index d42a4d7e14c..7ff602fb658 100644 --- a/go/timer/rate_limiter.go +++ b/go/timer/rate_limiter.go @@ -77,6 +77,14 @@ func (r *RateLimiter) DoEmpty() { _ = r.Do(nil) } +// AllowOne allows the next Do() call to run, even if the rate limiter would otherwise skip it. +func (r *RateLimiter) AllowOne() { + r.mu.Lock() + defer r.mu.Unlock() + + r.lastDoValue = r.tickerValue.Load() - 1 +} + // Diff returns the logical clock diff between the ticker and the last Do() call. func (r *RateLimiter) Diff() int64 { r.mu.Lock() @@ -87,7 +95,9 @@ func (r *RateLimiter) Diff() int64 { // Stop terminates rate limiter's operation and will not allow any more Do() executions. func (r *RateLimiter) Stop() { - r.cancel() + if r.cancel != nil { + r.cancel() + } r.mu.Lock() defer r.mu.Unlock() diff --git a/go/timer/rate_limiter_test.go b/go/timer/rate_limiter_test.go index 83690b98a22..70a3240d5f5 100644 --- a/go/timer/rate_limiter_test.go +++ b/go/timer/rate_limiter_test.go @@ -54,6 +54,23 @@ func TestRateLimiterShort(t *testing.T) { assert.Less(t, val, 10) } +func TestRateLimiterAllowOne(t *testing.T) { + r := NewRateLimiter(time.Millisecond * 250) + require.NotNil(t, r) + defer r.Stop() + val := 0 + incr := func() error { val++; return nil } + times := 10 + for range times { + time.Sleep(time.Millisecond * 100) + r.AllowOne() + err := r.Do(incr) + assert.NoError(t, err) + } + // we expect exactly 10 successful entries. + assert.Equal(t, times, val) +} + func TestRateLimiterStop(t *testing.T) { r := NewRateLimiter(time.Millisecond * 10) require.NotNil(t, r) @@ -91,3 +108,8 @@ func TestRateLimiterDiff(t *testing.T) { r.DoEmpty() assert.LessOrEqual(t, r.Diff(), int64(1)) } + +func TestRateLimiterUninitialized(t *testing.T) { + r := &RateLimiter{} + r.Stop() +} diff --git a/go/timer/suspendable_ticker.go b/go/timer/suspendable_ticker.go index f2694a5cab3..2288460e13d 100644 --- a/go/timer/suspendable_ticker.go +++ b/go/timer/suspendable_ticker.go @@ -17,6 +17,7 @@ limitations under the License. package timer import ( + "context" "sync/atomic" "time" ) @@ -29,19 +30,22 @@ type SuspendableTicker struct { C chan time.Time suspended atomic.Bool + cancel context.CancelFunc } // NewSuspendableTicker creates a new suspendable ticker, indicating whether the ticker should start // suspendable or running func NewSuspendableTicker(d time.Duration, initiallySuspended bool) *SuspendableTicker { + ctx, cancel := context.WithCancel(context.Background()) s := &SuspendableTicker{ ticker: time.NewTicker(d), C: make(chan time.Time), + cancel: cancel, } if initiallySuspended { s.suspended.Store(true) } - go s.loop() + go s.loop(ctx) return s } @@ -58,7 +62,7 @@ func (s *SuspendableTicker) Resume() { // Stop completely stops the timer, like time.Timer func (s *SuspendableTicker) Stop() { - s.ticker.Stop() + s.cancel() } // TickNow generates a tick at this point in time. It may block @@ -78,11 +82,22 @@ func (s *SuspendableTicker) TickAfter(d time.Duration) { }) } -func (s *SuspendableTicker) loop() { - for t := range s.ticker.C { - if !s.suspended.Load() { - // not suspended - s.C <- t +func (s *SuspendableTicker) loop(ctx context.Context) { + defer s.ticker.Stop() + + for { + select { + case <-ctx.Done(): + return + case t := <-s.ticker.C: + if !s.suspended.Load() { + // not suspended + select { + case <-ctx.Done(): + return + case s.C <- t: + } + } } } } diff --git a/go/tools/go-upgrade/go-upgrade.go b/go/tools/go-upgrade/go-upgrade.go index ee42040e5c0..34543120202 100644 --- a/go/tools/go-upgrade/go-upgrade.go +++ b/go/tools/go-upgrade/go-upgrade.go @@ -393,6 +393,9 @@ func replaceGoVersionInCodebase(old, new *version.Version, workflowUpdate bool) "./test/templates", "./build.env", "./docker/bootstrap/Dockerfile.common", + "./docker/lite/Dockerfile", + "./docker/lite/Dockerfile.percona80", + "./docker/vttestserver/Dockerfile.mysql80", } if workflowUpdate { explore = append(explore, "./.github/workflows") @@ -435,9 +438,6 @@ func updateBootstrapVersionInCodebase(old, new string, newGoVersion *version.Ver return nil } files, err := getListOfFilesInPaths([]string{ - "./docker/lite", - "./docker/local", - "./docker/vttestserver", "./Makefile", "./test/templates", }) diff --git a/go/vt/binlog/binlogplayer/binlog_player_test.go b/go/vt/binlog/binlogplayer/binlog_player_test.go index 5c6e28df704..99b0ef496b3 100644 --- a/go/vt/binlog/binlogplayer/binlog_player_test.go +++ b/go/vt/binlog/binlogplayer/binlog_player_test.go @@ -382,7 +382,7 @@ func applyEvents(blp *BinlogPlayer) func() error { func TestCreateVReplicationKeyRange(t *testing.T) { want := "insert into _vt.vreplication " + "(workflow, source, pos, max_tps, max_replication_lag, time_updated, transaction_timestamp, state, db_name, workflow_type, workflow_sub_type, defer_secondary_keys, options) " + - `values ('Resharding', 'keyspace:\"ks\" shard:\"0\" key_range:{end:\"\\x80\"}', 'MariaDB/0-1-1083', 9223372036854775807, 9223372036854775807, 481823, 0, 'Running', 'db', 0, 0, false, '{}')` + `values ('Resharding', 'keyspace:"ks" shard:"0" key_range:{end:"\\x80"}', 'MariaDB/0-1-1083', 9223372036854775807, 9223372036854775807, 481823, 0, 'Running', 'db', 0, 0, false, '{}')` bls := binlogdatapb.BinlogSource{ Keyspace: "ks", @@ -401,7 +401,7 @@ func TestCreateVReplicationKeyRange(t *testing.T) { func TestCreateVReplicationTables(t *testing.T) { want := "insert into _vt.vreplication " + "(workflow, source, pos, max_tps, max_replication_lag, time_updated, transaction_timestamp, state, db_name, workflow_type, workflow_sub_type, defer_secondary_keys, options) " + - `values ('Resharding', 'keyspace:\"ks\" shard:\"0\" tables:\"a\" tables:\"b\"', 'MariaDB/0-1-1083', 9223372036854775807, 9223372036854775807, 481823, 0, 'Running', 'db', 0, 0, false, '{}')` + `values ('Resharding', 'keyspace:"ks" shard:"0" tables:"a" tables:"b"', 'MariaDB/0-1-1083', 9223372036854775807, 9223372036854775807, 481823, 0, 'Running', 'db', 0, 0, false, '{}')` bls := binlogdatapb.BinlogSource{ Keyspace: "ks", diff --git a/go/vt/binlog/binlogplayer/dbclient.go b/go/vt/binlog/binlogplayer/dbclient.go index 61789f345c7..c3463b4cc2c 100644 --- a/go/vt/binlog/binlogplayer/dbclient.go +++ b/go/vt/binlog/binlogplayer/dbclient.go @@ -23,6 +23,7 @@ import ( "vitess.io/vitess/go/constants/sidecar" "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/mysql/capabilities" "vitess.io/vitess/go/mysql/sqlerror" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/textutil" @@ -41,6 +42,7 @@ type DBClient interface { Close() ExecuteFetch(query string, maxrows int) (qr *sqltypes.Result, err error) ExecuteFetchMulti(query string, maxrows int) (qrs []*sqltypes.Result, err error) + SupportsCapability(capability capabilities.FlavorCapability) (bool, error) } // dbClientImpl is a real DBClient backed by a mysql connection. @@ -123,6 +125,10 @@ func (dc *dbClientImpl) Close() { dc.dbConn.Close() } +func (dc *dbClientImpl) SupportsCapability(capability capabilities.FlavorCapability) (bool, error) { + return dc.dbConn.SupportsCapability(capability) +} + // LogError logs a message after truncating it to avoid spamming logs func LogError(msg string, err error) { log.Errorf("%s: %s", msg, MessageTruncate(err.Error())) diff --git a/go/vt/binlog/binlogplayer/fake_dbclient.go b/go/vt/binlog/binlogplayer/fake_dbclient.go index 750f35b3fe3..234dfd528e0 100644 --- a/go/vt/binlog/binlogplayer/fake_dbclient.go +++ b/go/vt/binlog/binlogplayer/fake_dbclient.go @@ -20,6 +20,7 @@ import ( "fmt" "strings" + "vitess.io/vitess/go/mysql/capabilities" "vitess.io/vitess/go/sqltypes" ) @@ -84,3 +85,7 @@ func (dc *fakeDBClient) ExecuteFetch(query string, maxrows int) (qr *sqltypes.Re func (dc *fakeDBClient) ExecuteFetchMulti(query string, maxrows int) ([]*sqltypes.Result, error) { return make([]*sqltypes.Result, 0), nil } + +func (dc *fakeDBClient) SupportsCapability(capability capabilities.FlavorCapability) (bool, error) { + return false, nil +} diff --git a/go/vt/binlog/binlogplayer/mock_dbclient.go b/go/vt/binlog/binlogplayer/mock_dbclient.go index 02e7ea28d7b..c27ae02ebaf 100644 --- a/go/vt/binlog/binlogplayer/mock_dbclient.go +++ b/go/vt/binlog/binlogplayer/mock_dbclient.go @@ -24,6 +24,7 @@ import ( "testing" "time" + "vitess.io/vitess/go/mysql/capabilities" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/sqlparser" ) @@ -260,3 +261,7 @@ func (dc *MockDBClient) RemoveInvariant(query string) { defer dc.expectMu.Unlock() delete(dc.invariants, query) } + +func (dc *MockDBClient) SupportsCapability(capability capabilities.FlavorCapability) (bool, error) { + return false, nil +} diff --git a/go/vt/mysqlctl/builtinbackupengine.go b/go/vt/mysqlctl/builtinbackupengine.go index 3bc39e45e72..e388912783a 100644 --- a/go/vt/mysqlctl/builtinbackupengine.go +++ b/go/vt/mysqlctl/builtinbackupengine.go @@ -92,8 +92,7 @@ var ( // it implements the BackupEngine interface and contains all the logic // required to implement a backup/restore by copying files from and to // the correct location / storage bucket -type BuiltinBackupEngine struct { -} +type BuiltinBackupEngine struct{} // builtinBackupManifest represents the backup. It lists all the files, the // Position that the backup was taken at, the compression engine used, etc. @@ -186,7 +185,7 @@ func (fe *FileEntry) fullPath(cnf *Mycnf) (string, error) { return path.Join(fe.ParentPath, root, fe.Name), nil } -// open attempts t oopen the file +// open attempts to open the file func (fe *FileEntry) open(cnf *Mycnf, readOnly bool) (*os.File, error) { name, err := fe.fullPath(cnf) if err != nil { @@ -194,7 +193,7 @@ func (fe *FileEntry) open(cnf *Mycnf, readOnly bool) (*os.File, error) { } var fd *os.File if readOnly { - if fd, err = os.Open(name); err != nil { + if fd, err = openForSequential(name); err != nil { return nil, vterrors.Wrapf(err, "cannot open source file %v", name) } } else { @@ -393,7 +392,6 @@ func (be *BuiltinBackupEngine) executeIncrementalBackup(ctx context.Context, par // executeFullBackup returns a BackupResult that indicates the usability of the backup, // and an overall error. func (be *BuiltinBackupEngine) executeFullBackup(ctx context.Context, params BackupParams, bh backupstorage.BackupHandle) (BackupResult, error) { - if params.IncrementalFromPos != "" { return be.executeIncrementalBackup(ctx, params, bh) } @@ -968,7 +966,6 @@ func (be *BuiltinBackupEngine) executeRestoreIncrementalBackup(ctx context.Conte // we return the position from which replication should start // otherwise an error is returned func (be *BuiltinBackupEngine) ExecuteRestore(ctx context.Context, params RestoreParams, bh backupstorage.BackupHandle) (*BackupManifest, error) { - var bm builtinBackupManifest if err := getBackupManifestInto(ctx, bh, &bm); err != nil { return nil, err @@ -1108,7 +1105,7 @@ func (be *BuiltinBackupEngine) restoreFile(ctx context.Context, params RestorePa // Create the uncompresser if needed. if !bm.SkipCompress { var decompressor io.ReadCloser - var deCompressionEngine = bm.CompressionEngine + deCompressionEngine := bm.CompressionEngine if deCompressionEngine == "" { // for backward compatibility diff --git a/go/vt/mysqlctl/builtinbackupengine_linux.go b/go/vt/mysqlctl/builtinbackupengine_linux.go new file mode 100644 index 00000000000..0185e091deb --- /dev/null +++ b/go/vt/mysqlctl/builtinbackupengine_linux.go @@ -0,0 +1,44 @@ +/* +Copyright 2024 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 +li*/ + +package mysqlctl + +import ( + "os" + + "golang.org/x/sys/unix" +) + +// openForSequential opens a file and hints to the kernel that this file +// is intended to be read sequentially, setting the FADV_SEQUENTIAL flag. +// See: https://linux.die.net/man/2/fadvise +func openForSequential(name string) (*os.File, error) { + f, err := os.Open(name) + if err != nil { + return nil, err + } + // XXX: beyond this path, if we error, we need to close + // our File since we're not returning it anymore. + fstat, err := f.Stat() + if err != nil { + f.Close() + return nil, err + } + if err := unix.Fadvise(int(f.Fd()), 0, fstat.Size(), unix.FADV_SEQUENTIAL); err != nil { + f.Close() + return nil, err + } + return f, nil +} diff --git a/go/vt/mysqlctl/builtinbackupengine_stub.go b/go/vt/mysqlctl/builtinbackupengine_stub.go new file mode 100644 index 00000000000..0c0ae9b9ef5 --- /dev/null +++ b/go/vt/mysqlctl/builtinbackupengine_stub.go @@ -0,0 +1,24 @@ +//go:build !linux + +/* +Copyright 2024 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 +li*/ + +package mysqlctl + +import "os" + +func openForSequential(name string) (*os.File, error) { + return os.Open(name) +} diff --git a/go/vt/mysqlctl/fakemysqldaemon.go b/go/vt/mysqlctl/fakemysqldaemon.go index 317aed4f578..7cdca498ded 100644 --- a/go/vt/mysqlctl/fakemysqldaemon.go +++ b/go/vt/mysqlctl/fakemysqldaemon.go @@ -96,6 +96,9 @@ type FakeMysqlDaemon struct { // PrimaryStatusError is used by PrimaryStatus. PrimaryStatusError error + // GlobalStatusVars is used by GetGlobalStatusVars. + GlobalStatusVars map[string]string + // CurrentSourceHost is returned by ReplicationStatus. CurrentSourceHost string @@ -419,9 +422,7 @@ func (fmd *FakeMysqlDaemon) SetSuperReadOnly(ctx context.Context, on bool) (Rese // GetGlobalStatusVars is part of the MysqlDaemon interface. func (fmd *FakeMysqlDaemon) GetGlobalStatusVars(ctx context.Context, variables []string) (map[string]string, error) { - return make(map[string]string), fmd.ExecuteSuperQueryList(ctx, []string{ - "FAKE " + getGlobalStatusQuery, - }) + return fmd.GlobalStatusVars, nil } // StartReplication is part of the MysqlDaemon interface. diff --git a/go/vt/mysqlctl/xtrabackupengine.go b/go/vt/mysqlctl/xtrabackupengine.go index 3f8491fdfb6..e6d02eedc1d 100644 --- a/go/vt/mysqlctl/xtrabackupengine.go +++ b/go/vt/mysqlctl/xtrabackupengine.go @@ -71,6 +71,7 @@ const ( writerBufferSize = 2 * 1024 * 1024 /*2 MiB*/ xtrabackupBinaryName = "xtrabackup" xtrabackupEngineName = "xtrabackup" + xtrabackupInfoFile = "xtrabackup_info" xbstream = "xbstream" ) @@ -292,7 +293,6 @@ func (be *XtrabackupEngine) backupFiles( numStripes int, flavor string, ) (replicationPosition replication.Position, finalErr error) { - backupProgram := path.Join(xtrabackupEnginePath, xtrabackupBinaryName) flagsToExec := []string{"--defaults-file=" + params.Cnf.Path, "--backup", @@ -300,6 +300,7 @@ func (be *XtrabackupEngine) backupFiles( "--slave-info", "--user=" + xtrabackupUser, "--target-dir=" + params.Cnf.TmpDir, + "--extra-lsndir=" + params.Cnf.TmpDir, } if xtrabackupStreamMode != "" { flagsToExec = append(flagsToExec, "--stream="+xtrabackupStreamMode) @@ -398,27 +399,14 @@ func (be *XtrabackupEngine) backupFiles( // the replication position. Note that if we don't read stderr as we go, the // xtrabackup process gets blocked when the write buffer fills up. stderrBuilder := &strings.Builder{} - posBuilder := &strings.Builder{} stderrDone := make(chan struct{}) go func() { defer close(stderrDone) scanner := bufio.NewScanner(backupErr) - capture := false for scanner.Scan() { line := scanner.Text() params.Logger.Infof("xtrabackup stderr: %s", line) - - // Wait until we see the first line of the binlog position. - // Then capture all subsequent lines. We need multiple lines since - // the value we're looking for has newlines in it. - if !capture { - if !strings.Contains(line, "MySQL binlog position") { - continue - } - capture = true - } - fmt.Fprintln(posBuilder, line) } if err := scanner.Err(); err != nil { params.Logger.Errorf("error reading from xtrabackup stderr: %v", err) @@ -462,8 +450,7 @@ func (be *XtrabackupEngine) backupFiles( return replicationPosition, vterrors.Wrap(err, fmt.Sprintf("xtrabackup failed with error. Output=%s", sterrOutput)) } - posOutput := posBuilder.String() - replicationPosition, rerr := findReplicationPosition(posOutput, flavor, params.Logger) + replicationPosition, rerr := findReplicationPositionFromXtrabackupInfo(params.Cnf.TmpDir, flavor, params.Logger) if rerr != nil { return replicationPosition, vterrors.Wrap(rerr, "backup failed trying to find replication position") } @@ -751,6 +738,22 @@ func (be *XtrabackupEngine) extractFiles(ctx context.Context, logger logutil.Log return nil } +func findReplicationPositionFromXtrabackupInfo(directory, flavor string, logger logutil.Logger) (replication.Position, error) { + f, err := os.Open(path.Join(directory, xtrabackupInfoFile)) + if err != nil { + return replication.Position{}, vterrors.Errorf(vtrpc.Code_INVALID_ARGUMENT, + "couldn't open %q to read GTID position", path.Join(directory, xtrabackupInfoFile)) + } + defer f.Close() + + contents, err := io.ReadAll(f) + if err != nil { + return replication.Position{}, vterrors.Errorf(vtrpc.Code_INVALID_ARGUMENT, "couldn't read GTID position from %q", f.Name()) + } + + return findReplicationPosition(string(contents), flavor, logger) +} + var xtrabackupReplicationPositionRegexp = regexp.MustCompile(`GTID of the last change '([^']*)'`) func findReplicationPosition(input, flavor string, logger logutil.Logger) (replication.Position, error) { diff --git a/go/vt/mysqlctl/xtrabackupengine_test.go b/go/vt/mysqlctl/xtrabackupengine_test.go index f560833d278..1139c671ca5 100644 --- a/go/vt/mysqlctl/xtrabackupengine_test.go +++ b/go/vt/mysqlctl/xtrabackupengine_test.go @@ -20,6 +20,8 @@ import ( "bytes" "crypto/rand" "io" + "os" + "path" "testing" "github.com/stretchr/testify/assert" @@ -49,22 +51,47 @@ func TestFindReplicationPosition(t *testing.T) { assert.NoError(t, err) assert.Equal(t, want, pos.String()) } +func TestFindReplicationPositionFromXtrabackupInfo(t *testing.T) { + input := `tool_version = 8.0.35-30 + binlog_pos = filename 'vt-0476396352-bin.000005', position '310088991', GTID of the last change '145e508e-ae54-11e9-8ce6-46824dd1815e:1-3, + 1e51f8be-ae54-11e9-a7c6-4280a041109b:1-3, + 47b59de1-b368-11e9-b48b-624401d35560:1-152981, + 557def0a-b368-11e9-84ed-f6fffd91cc57:1-3, + 599ef589-ae55-11e9-9688-ca1f44501925:1-14857169, + b9ce485d-b36b-11e9-9b17-2a6e0a6011f4:1-371262' + format = xbstream + ` + want := "145e508e-ae54-11e9-8ce6-46824dd1815e:1-3,1e51f8be-ae54-11e9-a7c6-4280a041109b:1-3,47b59de1-b368-11e9-b48b-624401d35560:1-152981,557def0a-b368-11e9-84ed-f6fffd91cc57:1-3,599ef589-ae55-11e9-9688-ca1f44501925:1-14857169,b9ce485d-b36b-11e9-9b17-2a6e0a6011f4:1-371262" + + tmp, err := os.MkdirTemp(t.TempDir(), "test") + assert.NoError(t, err) + + f, err := os.Create(path.Join(tmp, xtrabackupInfoFile)) + assert.NoError(t, err) + _, err = f.WriteString(input) + assert.NoError(t, err) + assert.NoError(t, f.Close()) + + pos, err := findReplicationPositionFromXtrabackupInfo(tmp, "MySQL56", logutil.NewConsoleLogger()) + assert.NoError(t, err) + assert.Equal(t, want, pos.String()) +} -func TestFindReplicationPositionNoMatch(t *testing.T) { +func TestFindReplicationPositionNoMatchFromXtrabackupInfo(t *testing.T) { // Make sure failure to find a match triggers an error. input := `nothing` - _, err := findReplicationPosition(input, "MySQL56", logutil.NewConsoleLogger()) + _, err := findReplicationPositionFromXtrabackupInfo(input, "MySQL56", logutil.NewConsoleLogger()) assert.Error(t, err) } -func TestFindReplicationPositionEmptyMatch(t *testing.T) { +func TestFindReplicationPositionEmptyMatchFromXtrabackupInfo(t *testing.T) { // Make sure failure to find a match triggers an error. input := `GTID of the last change ' '` - _, err := findReplicationPosition(input, "MySQL56", logutil.NewConsoleLogger()) + _, err := findReplicationPositionFromXtrabackupInfo(input, "MySQL56", logutil.NewConsoleLogger()) assert.Error(t, err) } diff --git a/go/vt/proto/query/query.pb.go b/go/vt/proto/query/query.pb.go index 03a58dc1b4b..8851ead4050 100644 --- a/go/vt/proto/query/query.pb.go +++ b/go/vt/proto/query/query.pb.go @@ -315,6 +315,9 @@ const ( // BITNUM specifies a base 2 binary type (unquoted varbinary). // Properties: 34, IsText. Type_BITNUM Type = 4130 + // VECTOR specifies a VECTOR type + // Properties: 35, IsQuoted. + Type_VECTOR Type = 2083 ) // Enum value maps for Type. @@ -355,6 +358,7 @@ var ( 4128: "HEXNUM", 4129: "HEXVAL", 4130: "BITNUM", + 2083: "VECTOR", } Type_value = map[string]int32{ "NULL_TYPE": 0, @@ -392,6 +396,7 @@ var ( "HEXNUM": 4128, "HEXVAL": 4129, "BITNUM": 4130, + "VECTOR": 2083, } ) @@ -428,8 +433,8 @@ type TransactionState int32 const ( TransactionState_UNKNOWN TransactionState = 0 TransactionState_PREPARE TransactionState = 1 - TransactionState_COMMIT TransactionState = 2 - TransactionState_ROLLBACK TransactionState = 3 + TransactionState_ROLLBACK TransactionState = 2 + TransactionState_COMMIT TransactionState = 3 ) // Enum value maps for TransactionState. @@ -437,14 +442,14 @@ var ( TransactionState_name = map[int32]string{ 0: "UNKNOWN", 1: "PREPARE", - 2: "COMMIT", - 3: "ROLLBACK", + 2: "ROLLBACK", + 3: "COMMIT", } TransactionState_value = map[string]int32{ "UNKNOWN": 0, "PREPARE": 1, - "COMMIT": 2, - "ROLLBACK": 3, + "ROLLBACK": 2, + "COMMIT": 3, } ) @@ -3538,6 +3543,118 @@ func (x *ReadTransactionResponse) GetMetadata() *TransactionMetadata { return nil } +// UnresolvedTransactionsRequest is the payload to UnresolvedTransactions +type UnresolvedTransactionsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + EffectiveCallerId *vtrpc.CallerID `protobuf:"bytes,1,opt,name=effective_caller_id,json=effectiveCallerId,proto3" json:"effective_caller_id,omitempty"` + ImmediateCallerId *VTGateCallerID `protobuf:"bytes,2,opt,name=immediate_caller_id,json=immediateCallerId,proto3" json:"immediate_caller_id,omitempty"` + Target *Target `protobuf:"bytes,3,opt,name=target,proto3" json:"target,omitempty"` +} + +func (x *UnresolvedTransactionsRequest) Reset() { + *x = UnresolvedTransactionsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_query_proto_msgTypes[39] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UnresolvedTransactionsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UnresolvedTransactionsRequest) ProtoMessage() {} + +func (x *UnresolvedTransactionsRequest) ProtoReflect() protoreflect.Message { + mi := &file_query_proto_msgTypes[39] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UnresolvedTransactionsRequest.ProtoReflect.Descriptor instead. +func (*UnresolvedTransactionsRequest) Descriptor() ([]byte, []int) { + return file_query_proto_rawDescGZIP(), []int{39} +} + +func (x *UnresolvedTransactionsRequest) GetEffectiveCallerId() *vtrpc.CallerID { + if x != nil { + return x.EffectiveCallerId + } + return nil +} + +func (x *UnresolvedTransactionsRequest) GetImmediateCallerId() *VTGateCallerID { + if x != nil { + return x.ImmediateCallerId + } + return nil +} + +func (x *UnresolvedTransactionsRequest) GetTarget() *Target { + if x != nil { + return x.Target + } + return nil +} + +// UnresolvedTransactionsResponse is the returned value from UnresolvedTransactions +type UnresolvedTransactionsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Transactions []*TransactionMetadata `protobuf:"bytes,1,rep,name=transactions,proto3" json:"transactions,omitempty"` +} + +func (x *UnresolvedTransactionsResponse) Reset() { + *x = UnresolvedTransactionsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_query_proto_msgTypes[40] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UnresolvedTransactionsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UnresolvedTransactionsResponse) ProtoMessage() {} + +func (x *UnresolvedTransactionsResponse) ProtoReflect() protoreflect.Message { + mi := &file_query_proto_msgTypes[40] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UnresolvedTransactionsResponse.ProtoReflect.Descriptor instead. +func (*UnresolvedTransactionsResponse) Descriptor() ([]byte, []int) { + return file_query_proto_rawDescGZIP(), []int{40} +} + +func (x *UnresolvedTransactionsResponse) GetTransactions() []*TransactionMetadata { + if x != nil { + return x.Transactions + } + return nil +} + // BeginExecuteRequest is the payload to BeginExecute type BeginExecuteRequest struct { state protoimpl.MessageState @@ -3556,7 +3673,7 @@ type BeginExecuteRequest struct { func (x *BeginExecuteRequest) Reset() { *x = BeginExecuteRequest{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[39] + mi := &file_query_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3569,7 +3686,7 @@ func (x *BeginExecuteRequest) String() string { func (*BeginExecuteRequest) ProtoMessage() {} func (x *BeginExecuteRequest) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[39] + mi := &file_query_proto_msgTypes[41] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3582,7 +3699,7 @@ func (x *BeginExecuteRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BeginExecuteRequest.ProtoReflect.Descriptor instead. func (*BeginExecuteRequest) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{39} + return file_query_proto_rawDescGZIP(), []int{41} } func (x *BeginExecuteRequest) GetEffectiveCallerId() *vtrpc.CallerID { @@ -3656,7 +3773,7 @@ type BeginExecuteResponse struct { func (x *BeginExecuteResponse) Reset() { *x = BeginExecuteResponse{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[40] + mi := &file_query_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3669,7 +3786,7 @@ func (x *BeginExecuteResponse) String() string { func (*BeginExecuteResponse) ProtoMessage() {} func (x *BeginExecuteResponse) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[40] + mi := &file_query_proto_msgTypes[42] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3682,7 +3799,7 @@ func (x *BeginExecuteResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use BeginExecuteResponse.ProtoReflect.Descriptor instead. func (*BeginExecuteResponse) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{40} + return file_query_proto_rawDescGZIP(), []int{42} } func (x *BeginExecuteResponse) GetError() *vtrpc.RPCError { @@ -3738,7 +3855,7 @@ type BeginStreamExecuteRequest struct { func (x *BeginStreamExecuteRequest) Reset() { *x = BeginStreamExecuteRequest{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[41] + mi := &file_query_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3751,7 +3868,7 @@ func (x *BeginStreamExecuteRequest) String() string { func (*BeginStreamExecuteRequest) ProtoMessage() {} func (x *BeginStreamExecuteRequest) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[41] + mi := &file_query_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3764,7 +3881,7 @@ func (x *BeginStreamExecuteRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BeginStreamExecuteRequest.ProtoReflect.Descriptor instead. func (*BeginStreamExecuteRequest) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{41} + return file_query_proto_rawDescGZIP(), []int{43} } func (x *BeginStreamExecuteRequest) GetEffectiveCallerId() *vtrpc.CallerID { @@ -3838,7 +3955,7 @@ type BeginStreamExecuteResponse struct { func (x *BeginStreamExecuteResponse) Reset() { *x = BeginStreamExecuteResponse{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[42] + mi := &file_query_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3851,7 +3968,7 @@ func (x *BeginStreamExecuteResponse) String() string { func (*BeginStreamExecuteResponse) ProtoMessage() {} func (x *BeginStreamExecuteResponse) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[42] + mi := &file_query_proto_msgTypes[44] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3864,7 +3981,7 @@ func (x *BeginStreamExecuteResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use BeginStreamExecuteResponse.ProtoReflect.Descriptor instead. func (*BeginStreamExecuteResponse) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{42} + return file_query_proto_rawDescGZIP(), []int{44} } func (x *BeginStreamExecuteResponse) GetError() *vtrpc.RPCError { @@ -3918,7 +4035,7 @@ type MessageStreamRequest struct { func (x *MessageStreamRequest) Reset() { *x = MessageStreamRequest{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[43] + mi := &file_query_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3931,7 +4048,7 @@ func (x *MessageStreamRequest) String() string { func (*MessageStreamRequest) ProtoMessage() {} func (x *MessageStreamRequest) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[43] + mi := &file_query_proto_msgTypes[45] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3944,7 +4061,7 @@ func (x *MessageStreamRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MessageStreamRequest.ProtoReflect.Descriptor instead. func (*MessageStreamRequest) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{43} + return file_query_proto_rawDescGZIP(), []int{45} } func (x *MessageStreamRequest) GetEffectiveCallerId() *vtrpc.CallerID { @@ -3987,7 +4104,7 @@ type MessageStreamResponse struct { func (x *MessageStreamResponse) Reset() { *x = MessageStreamResponse{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[44] + mi := &file_query_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4000,7 +4117,7 @@ func (x *MessageStreamResponse) String() string { func (*MessageStreamResponse) ProtoMessage() {} func (x *MessageStreamResponse) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[44] + mi := &file_query_proto_msgTypes[46] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4013,7 +4130,7 @@ func (x *MessageStreamResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MessageStreamResponse.ProtoReflect.Descriptor instead. func (*MessageStreamResponse) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{44} + return file_query_proto_rawDescGZIP(), []int{46} } func (x *MessageStreamResponse) GetResult() *QueryResult { @@ -4040,7 +4157,7 @@ type MessageAckRequest struct { func (x *MessageAckRequest) Reset() { *x = MessageAckRequest{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[45] + mi := &file_query_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4053,7 +4170,7 @@ func (x *MessageAckRequest) String() string { func (*MessageAckRequest) ProtoMessage() {} func (x *MessageAckRequest) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[45] + mi := &file_query_proto_msgTypes[47] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4066,7 +4183,7 @@ func (x *MessageAckRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MessageAckRequest.ProtoReflect.Descriptor instead. func (*MessageAckRequest) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{45} + return file_query_proto_rawDescGZIP(), []int{47} } func (x *MessageAckRequest) GetEffectiveCallerId() *vtrpc.CallerID { @@ -4119,7 +4236,7 @@ type MessageAckResponse struct { func (x *MessageAckResponse) Reset() { *x = MessageAckResponse{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[46] + mi := &file_query_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4132,7 +4249,7 @@ func (x *MessageAckResponse) String() string { func (*MessageAckResponse) ProtoMessage() {} func (x *MessageAckResponse) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[46] + mi := &file_query_proto_msgTypes[48] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4145,7 +4262,7 @@ func (x *MessageAckResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MessageAckResponse.ProtoReflect.Descriptor instead. func (*MessageAckResponse) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{46} + return file_query_proto_rawDescGZIP(), []int{48} } func (x *MessageAckResponse) GetResult() *QueryResult { @@ -4173,7 +4290,7 @@ type ReserveExecuteRequest struct { func (x *ReserveExecuteRequest) Reset() { *x = ReserveExecuteRequest{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[47] + mi := &file_query_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4186,7 +4303,7 @@ func (x *ReserveExecuteRequest) String() string { func (*ReserveExecuteRequest) ProtoMessage() {} func (x *ReserveExecuteRequest) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[47] + mi := &file_query_proto_msgTypes[49] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4199,7 +4316,7 @@ func (x *ReserveExecuteRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReserveExecuteRequest.ProtoReflect.Descriptor instead. func (*ReserveExecuteRequest) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{47} + return file_query_proto_rawDescGZIP(), []int{49} } func (x *ReserveExecuteRequest) GetEffectiveCallerId() *vtrpc.CallerID { @@ -4267,7 +4384,7 @@ type ReserveExecuteResponse struct { func (x *ReserveExecuteResponse) Reset() { *x = ReserveExecuteResponse{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[48] + mi := &file_query_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4280,7 +4397,7 @@ func (x *ReserveExecuteResponse) String() string { func (*ReserveExecuteResponse) ProtoMessage() {} func (x *ReserveExecuteResponse) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[48] + mi := &file_query_proto_msgTypes[50] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4293,7 +4410,7 @@ func (x *ReserveExecuteResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ReserveExecuteResponse.ProtoReflect.Descriptor instead. func (*ReserveExecuteResponse) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{48} + return file_query_proto_rawDescGZIP(), []int{50} } func (x *ReserveExecuteResponse) GetError() *vtrpc.RPCError { @@ -4342,7 +4459,7 @@ type ReserveStreamExecuteRequest struct { func (x *ReserveStreamExecuteRequest) Reset() { *x = ReserveStreamExecuteRequest{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[49] + mi := &file_query_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4355,7 +4472,7 @@ func (x *ReserveStreamExecuteRequest) String() string { func (*ReserveStreamExecuteRequest) ProtoMessage() {} func (x *ReserveStreamExecuteRequest) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[49] + mi := &file_query_proto_msgTypes[51] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4368,7 +4485,7 @@ func (x *ReserveStreamExecuteRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReserveStreamExecuteRequest.ProtoReflect.Descriptor instead. func (*ReserveStreamExecuteRequest) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{49} + return file_query_proto_rawDescGZIP(), []int{51} } func (x *ReserveStreamExecuteRequest) GetEffectiveCallerId() *vtrpc.CallerID { @@ -4436,7 +4553,7 @@ type ReserveStreamExecuteResponse struct { func (x *ReserveStreamExecuteResponse) Reset() { *x = ReserveStreamExecuteResponse{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[50] + mi := &file_query_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4449,7 +4566,7 @@ func (x *ReserveStreamExecuteResponse) String() string { func (*ReserveStreamExecuteResponse) ProtoMessage() {} func (x *ReserveStreamExecuteResponse) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[50] + mi := &file_query_proto_msgTypes[52] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4462,7 +4579,7 @@ func (x *ReserveStreamExecuteResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ReserveStreamExecuteResponse.ProtoReflect.Descriptor instead. func (*ReserveStreamExecuteResponse) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{50} + return file_query_proto_rawDescGZIP(), []int{52} } func (x *ReserveStreamExecuteResponse) GetError() *vtrpc.RPCError { @@ -4511,7 +4628,7 @@ type ReserveBeginExecuteRequest struct { func (x *ReserveBeginExecuteRequest) Reset() { *x = ReserveBeginExecuteRequest{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[51] + mi := &file_query_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4524,7 +4641,7 @@ func (x *ReserveBeginExecuteRequest) String() string { func (*ReserveBeginExecuteRequest) ProtoMessage() {} func (x *ReserveBeginExecuteRequest) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[51] + mi := &file_query_proto_msgTypes[53] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4537,7 +4654,7 @@ func (x *ReserveBeginExecuteRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReserveBeginExecuteRequest.ProtoReflect.Descriptor instead. func (*ReserveBeginExecuteRequest) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{51} + return file_query_proto_rawDescGZIP(), []int{53} } func (x *ReserveBeginExecuteRequest) GetEffectiveCallerId() *vtrpc.CallerID { @@ -4612,7 +4729,7 @@ type ReserveBeginExecuteResponse struct { func (x *ReserveBeginExecuteResponse) Reset() { *x = ReserveBeginExecuteResponse{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[52] + mi := &file_query_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4625,7 +4742,7 @@ func (x *ReserveBeginExecuteResponse) String() string { func (*ReserveBeginExecuteResponse) ProtoMessage() {} func (x *ReserveBeginExecuteResponse) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[52] + mi := &file_query_proto_msgTypes[54] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4638,7 +4755,7 @@ func (x *ReserveBeginExecuteResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ReserveBeginExecuteResponse.ProtoReflect.Descriptor instead. func (*ReserveBeginExecuteResponse) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{52} + return file_query_proto_rawDescGZIP(), []int{54} } func (x *ReserveBeginExecuteResponse) GetError() *vtrpc.RPCError { @@ -4701,7 +4818,7 @@ type ReserveBeginStreamExecuteRequest struct { func (x *ReserveBeginStreamExecuteRequest) Reset() { *x = ReserveBeginStreamExecuteRequest{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[53] + mi := &file_query_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4714,7 +4831,7 @@ func (x *ReserveBeginStreamExecuteRequest) String() string { func (*ReserveBeginStreamExecuteRequest) ProtoMessage() {} func (x *ReserveBeginStreamExecuteRequest) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[53] + mi := &file_query_proto_msgTypes[55] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4727,7 +4844,7 @@ func (x *ReserveBeginStreamExecuteRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReserveBeginStreamExecuteRequest.ProtoReflect.Descriptor instead. func (*ReserveBeginStreamExecuteRequest) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{53} + return file_query_proto_rawDescGZIP(), []int{55} } func (x *ReserveBeginStreamExecuteRequest) GetEffectiveCallerId() *vtrpc.CallerID { @@ -4802,7 +4919,7 @@ type ReserveBeginStreamExecuteResponse struct { func (x *ReserveBeginStreamExecuteResponse) Reset() { *x = ReserveBeginStreamExecuteResponse{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[54] + mi := &file_query_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4815,7 +4932,7 @@ func (x *ReserveBeginStreamExecuteResponse) String() string { func (*ReserveBeginStreamExecuteResponse) ProtoMessage() {} func (x *ReserveBeginStreamExecuteResponse) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[54] + mi := &file_query_proto_msgTypes[56] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4828,7 +4945,7 @@ func (x *ReserveBeginStreamExecuteResponse) ProtoReflect() protoreflect.Message // Deprecated: Use ReserveBeginStreamExecuteResponse.ProtoReflect.Descriptor instead. func (*ReserveBeginStreamExecuteResponse) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{54} + return file_query_proto_rawDescGZIP(), []int{56} } func (x *ReserveBeginStreamExecuteResponse) GetError() *vtrpc.RPCError { @@ -4889,7 +5006,7 @@ type ReleaseRequest struct { func (x *ReleaseRequest) Reset() { *x = ReleaseRequest{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[55] + mi := &file_query_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4902,7 +5019,7 @@ func (x *ReleaseRequest) String() string { func (*ReleaseRequest) ProtoMessage() {} func (x *ReleaseRequest) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[55] + mi := &file_query_proto_msgTypes[57] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4915,7 +5032,7 @@ func (x *ReleaseRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReleaseRequest.ProtoReflect.Descriptor instead. func (*ReleaseRequest) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{55} + return file_query_proto_rawDescGZIP(), []int{57} } func (x *ReleaseRequest) GetEffectiveCallerId() *vtrpc.CallerID { @@ -4963,7 +5080,7 @@ type ReleaseResponse struct { func (x *ReleaseResponse) Reset() { *x = ReleaseResponse{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[56] + mi := &file_query_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4976,7 +5093,7 @@ func (x *ReleaseResponse) String() string { func (*ReleaseResponse) ProtoMessage() {} func (x *ReleaseResponse) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[56] + mi := &file_query_proto_msgTypes[58] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4989,7 +5106,7 @@ func (x *ReleaseResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ReleaseResponse.ProtoReflect.Descriptor instead. func (*ReleaseResponse) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{56} + return file_query_proto_rawDescGZIP(), []int{58} } // StreamHealthRequest is the payload for StreamHealth @@ -5002,7 +5119,7 @@ type StreamHealthRequest struct { func (x *StreamHealthRequest) Reset() { *x = StreamHealthRequest{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[57] + mi := &file_query_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5015,7 +5132,7 @@ func (x *StreamHealthRequest) String() string { func (*StreamHealthRequest) ProtoMessage() {} func (x *StreamHealthRequest) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[57] + mi := &file_query_proto_msgTypes[59] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5028,7 +5145,7 @@ func (x *StreamHealthRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StreamHealthRequest.ProtoReflect.Descriptor instead. func (*StreamHealthRequest) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{57} + return file_query_proto_rawDescGZIP(), []int{59} } // RealtimeStats contains information about the tablet status. @@ -5070,13 +5187,14 @@ type RealtimeStats struct { // view_schema_changed is to provide list of views that have schema changes detected by the tablet. ViewSchemaChanged []string `protobuf:"bytes,8,rep,name=view_schema_changed,json=viewSchemaChanged,proto3" json:"view_schema_changed,omitempty"` // udfs_changed is used to signal that the UDFs have changed on the tablet. - UdfsChanged bool `protobuf:"varint,9,opt,name=udfs_changed,json=udfsChanged,proto3" json:"udfs_changed,omitempty"` + UdfsChanged bool `protobuf:"varint,9,opt,name=udfs_changed,json=udfsChanged,proto3" json:"udfs_changed,omitempty"` + TxUnresolved bool `protobuf:"varint,10,opt,name=tx_unresolved,json=txUnresolved,proto3" json:"tx_unresolved,omitempty"` } func (x *RealtimeStats) Reset() { *x = RealtimeStats{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[58] + mi := &file_query_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5089,7 +5207,7 @@ func (x *RealtimeStats) String() string { func (*RealtimeStats) ProtoMessage() {} func (x *RealtimeStats) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[58] + mi := &file_query_proto_msgTypes[60] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5102,7 +5220,7 @@ func (x *RealtimeStats) ProtoReflect() protoreflect.Message { // Deprecated: Use RealtimeStats.ProtoReflect.Descriptor instead. func (*RealtimeStats) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{58} + return file_query_proto_rawDescGZIP(), []int{60} } func (x *RealtimeStats) GetHealthError() string { @@ -5168,6 +5286,13 @@ func (x *RealtimeStats) GetUdfsChanged() bool { return false } +func (x *RealtimeStats) GetTxUnresolved() bool { + if x != nil { + return x.TxUnresolved + } + return false +} + // AggregateStats contains information about the health of a group of // tablets for a Target. It is used to propagate stats from a vtgate // to another, or from the Gateway layer of a vtgate to the routing @@ -5194,7 +5319,7 @@ type AggregateStats struct { func (x *AggregateStats) Reset() { *x = AggregateStats{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[59] + mi := &file_query_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5207,7 +5332,7 @@ func (x *AggregateStats) String() string { func (*AggregateStats) ProtoMessage() {} func (x *AggregateStats) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[59] + mi := &file_query_proto_msgTypes[61] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5220,7 +5345,7 @@ func (x *AggregateStats) ProtoReflect() protoreflect.Message { // Deprecated: Use AggregateStats.ProtoReflect.Descriptor instead. func (*AggregateStats) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{59} + return file_query_proto_rawDescGZIP(), []int{61} } func (x *AggregateStats) GetHealthyTabletCount() int32 { @@ -5314,7 +5439,7 @@ type StreamHealthResponse struct { func (x *StreamHealthResponse) Reset() { *x = StreamHealthResponse{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[60] + mi := &file_query_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5327,7 +5452,7 @@ func (x *StreamHealthResponse) String() string { func (*StreamHealthResponse) ProtoMessage() {} func (x *StreamHealthResponse) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[60] + mi := &file_query_proto_msgTypes[62] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5340,7 +5465,7 @@ func (x *StreamHealthResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StreamHealthResponse.ProtoReflect.Descriptor instead. func (*StreamHealthResponse) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{60} + return file_query_proto_rawDescGZIP(), []int{62} } func (x *StreamHealthResponse) GetTarget() *Target { @@ -5393,7 +5518,7 @@ type TransactionMetadata struct { func (x *TransactionMetadata) Reset() { *x = TransactionMetadata{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[61] + mi := &file_query_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5406,7 +5531,7 @@ func (x *TransactionMetadata) String() string { func (*TransactionMetadata) ProtoMessage() {} func (x *TransactionMetadata) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[61] + mi := &file_query_proto_msgTypes[63] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5419,7 +5544,7 @@ func (x *TransactionMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use TransactionMetadata.ProtoReflect.Descriptor instead. func (*TransactionMetadata) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{61} + return file_query_proto_rawDescGZIP(), []int{63} } func (x *TransactionMetadata) GetDtid() string { @@ -5464,7 +5589,7 @@ type GetSchemaRequest struct { func (x *GetSchemaRequest) Reset() { *x = GetSchemaRequest{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[62] + mi := &file_query_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5477,7 +5602,7 @@ func (x *GetSchemaRequest) String() string { func (*GetSchemaRequest) ProtoMessage() {} func (x *GetSchemaRequest) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[62] + mi := &file_query_proto_msgTypes[64] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5490,7 +5615,7 @@ func (x *GetSchemaRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSchemaRequest.ProtoReflect.Descriptor instead. func (*GetSchemaRequest) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{62} + return file_query_proto_rawDescGZIP(), []int{64} } func (x *GetSchemaRequest) GetTarget() *Target { @@ -5528,7 +5653,7 @@ type UDFInfo struct { func (x *UDFInfo) Reset() { *x = UDFInfo{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[63] + mi := &file_query_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5541,7 +5666,7 @@ func (x *UDFInfo) String() string { func (*UDFInfo) ProtoMessage() {} func (x *UDFInfo) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[63] + mi := &file_query_proto_msgTypes[65] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5554,7 +5679,7 @@ func (x *UDFInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use UDFInfo.ProtoReflect.Descriptor instead. func (*UDFInfo) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{63} + return file_query_proto_rawDescGZIP(), []int{65} } func (x *UDFInfo) GetName() string { @@ -5592,7 +5717,7 @@ type GetSchemaResponse struct { func (x *GetSchemaResponse) Reset() { *x = GetSchemaResponse{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[64] + mi := &file_query_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5605,7 +5730,7 @@ func (x *GetSchemaResponse) String() string { func (*GetSchemaResponse) ProtoMessage() {} func (x *GetSchemaResponse) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[64] + mi := &file_query_proto_msgTypes[66] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5618,7 +5743,7 @@ func (x *GetSchemaResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSchemaResponse.ProtoReflect.Descriptor instead. func (*GetSchemaResponse) Descriptor() ([]byte, []int) { - return file_query_proto_rawDescGZIP(), []int{64} + return file_query_proto_rawDescGZIP(), []int{66} } func (x *GetSchemaResponse) GetUdfs() []*UDFInfo { @@ -5654,7 +5779,7 @@ type StreamEvent_Statement struct { func (x *StreamEvent_Statement) Reset() { *x = StreamEvent_Statement{} if protoimpl.UnsafeEnabled { - mi := &file_query_proto_msgTypes[66] + mi := &file_query_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5667,7 +5792,7 @@ func (x *StreamEvent_Statement) String() string { func (*StreamEvent_Statement) ProtoMessage() {} func (x *StreamEvent_Statement) ProtoReflect() protoreflect.Message { - mi := &file_query_proto_msgTypes[66] + mi := &file_query_proto_msgTypes[68] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6183,47 +6308,9 @@ var file_query_proto_rawDesc = []byte{ 0x73, 0x65, 0x12, 0x36, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0xe0, 0x02, 0x0a, 0x13, 0x42, - 0x65, 0x67, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x13, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, - 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0f, 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x44, - 0x52, 0x11, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, - 0x72, 0x49, 0x64, 0x12, 0x45, 0x0a, 0x13, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, - 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x15, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x56, 0x54, 0x47, 0x61, 0x74, 0x65, 0x43, - 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, - 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x06, 0x74, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x71, 0x75, 0x65, - 0x72, 0x79, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x12, 0x27, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x11, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x2f, 0x0a, 0x07, 0x6f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x71, 0x75, - 0x65, 0x72, 0x79, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x72, - 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0a, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, - 0x70, 0x72, 0x65, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x22, 0xfe, 0x01, - 0x0a, 0x14, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, - 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2a, 0x0a, - 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 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, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, - 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, - 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, - 0x18, 0x04, 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, 0x0b, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x73, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x73, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 0xe6, - 0x02, 0x0a, 0x19, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x13, + 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0xce, 0x01, 0x0a, 0x1d, 0x55, + 0x6e, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x13, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, 0x65, 0x66, 0x66, 0x65, @@ -6234,52 +6321,14 @@ var file_query_proto_rawDesc = []byte{ 0x44, 0x52, 0x11, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x54, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x27, 0x0a, 0x05, 0x71, - 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x71, 0x75, 0x65, - 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x05, 0x71, - 0x75, 0x65, 0x72, 0x79, 0x12, 0x2f, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x45, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x5f, 0x71, 0x75, 0x65, - 0x72, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x51, - 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x64, 0x49, 0x64, 0x22, 0x84, 0x02, 0x0a, 0x1a, 0x42, 0x65, 0x67, 0x69, - 0x6e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, - 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2a, 0x0a, - 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 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, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, - 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, - 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, - 0x18, 0x04, 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, 0x0b, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x73, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x73, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 0xd9, - 0x01, 0x0a, 0x14, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x13, 0x65, 0x66, 0x66, 0x65, 0x63, - 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6c, - 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, - 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x45, 0x0a, 0x13, 0x69, 0x6d, 0x6d, 0x65, - 0x64, 0x69, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x56, 0x54, - 0x47, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, 0x69, 0x6d, - 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, - 0x25, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0d, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x43, 0x0a, 0x15, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 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, - 0xf6, 0x01, 0x0a, 0x11, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x41, 0x63, 0x6b, 0x52, 0x65, + 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x60, 0x0a, 0x1e, 0x55, + 0x6e, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, + 0x0c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, + 0x0c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe0, 0x02, + 0x0a, 0x13, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x13, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x65, @@ -6291,361 +6340,460 @@ var file_query_proto_rawDesc = []byte{ 0x64, 0x69, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, - 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x03, 0x69, 0x64, 0x73, 0x22, 0x40, 0x0a, 0x12, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x41, 0x63, 0x6b, 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, 0xe8, 0x02, 0x0a, 0x15, 0x52, - 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x13, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, - 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, - 0x49, 0x44, 0x52, 0x11, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x61, 0x6c, - 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x45, 0x0a, 0x13, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, - 0x74, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x56, 0x54, 0x47, 0x61, 0x74, - 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, 0x69, 0x6d, 0x6d, 0x65, 0x64, - 0x69, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x06, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x71, - 0x75, 0x65, 0x72, 0x79, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x12, 0x27, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, 0x6e, 0x64, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x25, 0x0a, 0x0e, - 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, + 0x72, 0x67, 0x65, 0x74, 0x12, 0x27, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, 0x6e, + 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x2f, 0x0a, + 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, + 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x4f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, + 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x49, 0x64, 0x12, + 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x07, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, + 0x22, 0xfe, 0x01, 0x0a, 0x14, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x05, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x12, 0x2a, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 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, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x25, 0x0a, 0x0e, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x45, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x5f, 0x71, 0x75, 0x65, 0x72, - 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x51, 0x75, - 0x65, 0x72, 0x69, 0x65, 0x73, 0x22, 0xc6, 0x01, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x25, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0f, 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, - 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2a, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, - 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, 0x72, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, - 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x64, 0x49, 0x64, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, - 0x6c, 0x69, 0x61, 0x73, 0x18, 0x04, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0xee, - 0x02, 0x0a, 0x1b, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, - 0x0a, 0x13, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, - 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, 0x65, 0x66, - 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, - 0x45, 0x0a, 0x13, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x61, 0x6c, - 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x71, - 0x75, 0x65, 0x72, 0x79, 0x2e, 0x56, 0x54, 0x47, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, - 0x72, 0x49, 0x44, 0x52, 0x11, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x43, 0x61, - 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x54, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x27, 0x0a, - 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x71, - 0x75, 0x65, 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, - 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x2f, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, + 0x6e, 0x49, 0x64, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, + 0x69, 0x61, 0x73, 0x18, 0x04, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x32, 0x0a, + 0x15, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x63, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x73, 0x22, 0xe6, 0x02, 0x0a, 0x19, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x3f, 0x0a, 0x13, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x61, 0x6c, + 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, + 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, 0x65, + 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, + 0x12, 0x45, 0x0a, 0x13, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x61, + 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, + 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x56, 0x54, 0x47, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, + 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x43, + 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, + 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x27, + 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, + 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x2f, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x5f, + 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x70, + 0x72, 0x65, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, + 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x49, 0x64, 0x22, 0x84, 0x02, 0x0a, 0x1a, 0x42, + 0x65, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x05, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x12, 0x2a, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 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, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x25, 0x0a, 0x0e, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, + 0x69, 0x61, 0x73, 0x18, 0x04, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x32, 0x0a, + 0x15, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x63, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x73, 0x22, 0xd9, 0x01, 0x0a, 0x14, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x13, 0x65, 0x66, + 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, + 0x69, 0x76, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x45, 0x0a, 0x13, 0x69, + 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x2e, 0x56, 0x54, 0x47, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, + 0x11, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x25, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x43, 0x0a, + 0x15, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 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, 0xf6, 0x01, 0x0a, 0x11, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x41, 0x63, + 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x13, 0x65, 0x66, 0x66, 0x65, + 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, + 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, + 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x45, 0x0a, 0x13, 0x69, 0x6d, 0x6d, + 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x56, + 0x54, 0x47, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, 0x69, + 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, + 0x12, 0x25, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0d, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, + 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x03, 0x69, + 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x03, 0x69, 0x64, 0x73, 0x22, 0x40, 0x0a, 0x12, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x41, 0x63, 0x6b, 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, 0xe8, 0x02, + 0x0a, 0x15, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x13, 0x65, 0x66, 0x66, 0x65, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6c, + 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, + 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x45, 0x0a, 0x13, 0x69, 0x6d, 0x6d, 0x65, + 0x64, 0x69, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x56, 0x54, + 0x47, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, 0x69, 0x6d, + 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, + 0x25, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0d, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x27, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x42, 0x6f, + 0x75, 0x6e, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, + 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, - 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x5f, 0x71, + 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, + 0x65, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x22, 0xc6, 0x01, 0x0a, 0x16, 0x52, 0x65, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, + 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2a, 0x0a, 0x06, 0x72, 0x65, + 0x73, 0x75, 0x6c, 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, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x64, 0x49, 0x64, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x04, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, + 0x73, 0x22, 0xee, 0x02, 0x0a, 0x1b, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x3f, 0x0a, 0x13, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, + 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, + 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, + 0x11, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x45, 0x0a, 0x13, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x5f, + 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x15, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x56, 0x54, 0x47, 0x61, 0x74, 0x65, 0x43, 0x61, + 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, + 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x06, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x12, 0x27, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x11, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x2f, 0x0a, 0x07, 0x6f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x71, 0x75, 0x65, + 0x72, 0x79, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, + 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x51, 0x75, 0x65, 0x72, 0x69, + 0x65, 0x73, 0x22, 0xcc, 0x01, 0x0a, 0x1c, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, + 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2a, 0x0a, 0x06, 0x72, 0x65, + 0x73, 0x75, 0x6c, 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, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x64, 0x49, 0x64, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x04, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, + 0x73, 0x22, 0xf4, 0x02, 0x0a, 0x1a, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x42, 0x65, 0x67, + 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x3f, 0x0a, 0x13, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x61, + 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, + 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, + 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x45, 0x0a, 0x13, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x5f, 0x63, + 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, + 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x56, 0x54, 0x47, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, + 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, + 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, + 0x27, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, + 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x2f, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, + 0x5f, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, + 0x70, 0x72, 0x65, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x6f, + 0x73, 0x74, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, + 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x70, 0x6f, 0x73, 0x74, 0x42, 0x65, 0x67, 0x69, + 0x6e, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x22, 0xa6, 0x02, 0x0a, 0x1b, 0x52, 0x65, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, + 0x2a, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 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, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x74, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x69, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x64, 0x49, 0x64, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, + 0x69, 0x61, 0x73, 0x18, 0x05, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x32, 0x0a, + 0x15, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x63, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x73, 0x22, 0xfa, 0x02, 0x0a, 0x20, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x42, 0x65, 0x67, + 0x69, 0x6e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x13, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, + 0x69, 0x76, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6c, 0x6c, + 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, + 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x45, 0x0a, 0x13, 0x69, 0x6d, 0x6d, 0x65, 0x64, + 0x69, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x56, 0x54, 0x47, + 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, 0x69, 0x6d, 0x6d, + 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, + 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, + 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x27, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, + 0x6e, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x2f, + 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x15, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x06, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, + 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x6f, 0x73, 0x74, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x71, + 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x70, 0x6f, + 0x73, 0x74, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x22, 0xac, + 0x02, 0x0a, 0x21, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x53, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x45, + 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2a, 0x0a, 0x06, 0x72, + 0x65, 0x73, 0x75, 0x6c, 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, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1f, - 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x22, - 0xcc, 0x01, 0x0a, 0x1c, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x25, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0f, 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, - 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2a, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, - 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, 0x72, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, - 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x64, 0x49, 0x64, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, - 0x6c, 0x69, 0x61, 0x73, 0x18, 0x04, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0xf4, - 0x02, 0x0a, 0x1a, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x45, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, - 0x13, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x65, - 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x72, - 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, 0x65, 0x66, 0x66, - 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x45, - 0x0a, 0x13, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x71, 0x75, - 0x65, 0x72, 0x79, 0x2e, 0x56, 0x54, 0x47, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, - 0x49, 0x44, 0x52, 0x11, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, - 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x54, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x27, 0x0a, 0x05, - 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x71, 0x75, - 0x65, 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x05, - 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x2f, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x45, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x5f, 0x71, 0x75, - 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x65, - 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x6f, 0x73, 0x74, 0x5f, - 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x10, 0x70, 0x6f, 0x73, 0x74, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x51, 0x75, - 0x65, 0x72, 0x69, 0x65, 0x73, 0x22, 0xa6, 0x02, 0x0a, 0x1b, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, - 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2a, 0x0a, 0x06, - 0x72, 0x65, 0x73, 0x75, 0x6c, 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, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, - 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x49, 0x64, - 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, - 0x18, 0x05, 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, 0x0b, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x73, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x73, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 0xfa, - 0x02, 0x0a, 0x20, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x13, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, - 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, - 0x44, 0x52, 0x11, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x61, 0x6c, 0x6c, - 0x65, 0x72, 0x49, 0x64, 0x12, 0x45, 0x0a, 0x13, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, - 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x15, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x56, 0x54, 0x47, 0x61, 0x74, 0x65, - 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, - 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x06, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x71, 0x75, - 0x65, 0x72, 0x79, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x12, 0x27, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x11, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x2f, 0x0a, 0x07, 0x6f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x71, - 0x75, 0x65, 0x72, 0x79, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, - 0x70, 0x72, 0x65, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x2c, 0x0a, - 0x12, 0x70, 0x6f, 0x73, 0x74, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x71, 0x75, 0x65, 0x72, - 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x70, 0x6f, 0x73, 0x74, 0x42, - 0x65, 0x67, 0x69, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x22, 0xac, 0x02, 0x0a, 0x21, - 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x65, - 0x61, 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x25, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2a, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, - 0x6c, 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, 0x72, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x74, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, - 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0a, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x49, 0x64, 0x12, 0x38, 0x0a, 0x0c, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x05, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, - 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 0x87, 0x02, 0x0a, 0x0e, 0x52, - 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, - 0x13, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x65, - 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x76, 0x74, 0x72, - 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, 0x65, 0x66, 0x66, - 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x45, - 0x0a, 0x13, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x71, 0x75, - 0x65, 0x72, 0x79, 0x2e, 0x56, 0x54, 0x47, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, - 0x49, 0x44, 0x52, 0x11, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, - 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x54, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x25, 0x0a, 0x0e, - 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, - 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x64, 0x49, 0x64, 0x22, 0x11, 0x0a, 0x0f, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x0a, 0x13, 0x53, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x99, - 0x03, 0x0a, 0x0d, 0x52, 0x65, 0x61, 0x6c, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, - 0x12, 0x21, 0x0a, 0x0c, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x45, 0x72, - 0x72, 0x6f, 0x72, 0x12, 0x36, 0x0a, 0x17, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x15, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x4c, 0x61, 0x67, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x62, - 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x5f, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x62, 0x69, 0x6e, 0x6c, 0x6f, - 0x67, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x47, 0x0a, - 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, + 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x49, 0x64, 0x12, + 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, + 0x05, 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, 0x0b, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 0x87, 0x02, + 0x0a, 0x0e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x3f, 0x0a, 0x13, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x61, + 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, + 0x76, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, + 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x45, 0x0a, 0x13, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x5f, 0x63, + 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, + 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x56, 0x54, 0x47, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, + 0x6c, 0x65, 0x72, 0x49, 0x44, 0x52, 0x11, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, + 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, + 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x64, 0x49, 0x64, 0x22, 0x11, 0x0a, 0x0f, 0x52, 0x65, 0x6c, 0x65, 0x61, + 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x0a, 0x13, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x22, 0xbe, 0x03, 0x0a, 0x0d, 0x52, 0x65, 0x61, 0x6c, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, + 0x61, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x6c, 0x74, + 0x68, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x36, 0x0a, 0x17, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, - 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1d, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, - 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x61, 0x67, 0x53, - 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x70, 0x75, 0x5f, 0x75, 0x73, - 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x63, 0x70, 0x75, 0x55, 0x73, - 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x71, 0x70, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, - 0x52, 0x03, 0x71, 0x70, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x18, 0x07, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x12, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, - 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x2e, 0x0a, 0x13, 0x76, 0x69, 0x65, 0x77, 0x5f, - 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x18, 0x08, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x76, 0x69, 0x65, 0x77, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, - 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x64, 0x66, 0x73, 0x5f, - 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x75, - 0x64, 0x66, 0x73, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x22, 0xf6, 0x01, 0x0a, 0x0e, 0x41, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x30, 0x0a, - 0x14, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x68, 0x65, 0x61, - 0x6c, 0x74, 0x68, 0x79, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, - 0x34, 0x0a, 0x16, 0x75, 0x6e, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x5f, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x14, 0x75, 0x6e, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x3d, 0x0a, 0x1b, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, - 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x18, 0x72, 0x65, 0x70, 0x6c, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x61, 0x67, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, - 0x73, 0x4d, 0x69, 0x6e, 0x12, 0x3d, 0x0a, 0x1b, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x5f, - 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x18, 0x72, 0x65, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x61, 0x67, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, - 0x4d, 0x61, 0x78, 0x22, 0x95, 0x02, 0x0a, 0x14, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x48, 0x65, - 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x06, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x71, - 0x75, 0x65, 0x72, 0x79, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x12, 0x3f, 0x0a, - 0x1c, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x74, 0x65, 0x72, 0x6d, 0x5f, 0x73, 0x74, - 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x19, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x54, 0x65, 0x72, 0x6d, - 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3b, - 0x0a, 0x0e, 0x72, 0x65, 0x61, 0x6c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x52, - 0x65, 0x61, 0x6c, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x0d, 0x72, 0x65, - 0x61, 0x6c, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x38, 0x0a, 0x0c, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x05, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, - 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0xae, 0x01, 0x0a, 0x13, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x74, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x64, 0x74, 0x69, 0x64, 0x12, 0x2d, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, - 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x63, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, 0x69, - 0x6d, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x31, 0x0a, 0x0c, 0x70, 0x61, 0x72, - 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x0d, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x0c, - 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x73, 0x22, 0x91, 0x01, 0x0a, - 0x10, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x25, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0d, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x35, 0x0a, 0x0a, 0x74, 0x61, 0x62, 0x6c, - 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x71, - 0x75, 0x65, 0x72, 0x79, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x54, 0x61, 0x62, 0x6c, 0x65, - 0x54, 0x79, 0x70, 0x65, 0x52, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, - 0x22, 0x6d, 0x0a, 0x07, 0x55, 0x44, 0x46, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x20, 0x0a, 0x0b, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6e, - 0x67, 0x12, 0x2c, 0x0a, 0x0b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0b, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x54, - 0x79, 0x70, 0x65, 0x52, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x22, - 0xd5, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x04, 0x75, 0x64, 0x66, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x55, 0x44, 0x46, 0x49, - 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x75, 0x64, 0x66, 0x73, 0x12, 0x58, 0x0a, 0x10, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x53, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x61, - 0x62, 0x6c, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x0f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x1a, 0x42, 0x0a, 0x14, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x65, 0x66, 0x69, - 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 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, 0x92, 0x03, 0x0a, 0x09, 0x4d, 0x79, 0x53, 0x71, - 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x4d, 0x50, 0x54, 0x59, 0x10, 0x00, - 0x12, 0x11, 0x0a, 0x0d, 0x4e, 0x4f, 0x54, 0x5f, 0x4e, 0x55, 0x4c, 0x4c, 0x5f, 0x46, 0x4c, 0x41, - 0x47, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x52, 0x49, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x46, - 0x4c, 0x41, 0x47, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x55, 0x4e, 0x49, 0x51, 0x55, 0x45, 0x5f, - 0x4b, 0x45, 0x59, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x04, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x55, - 0x4c, 0x54, 0x49, 0x50, 0x4c, 0x45, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, - 0x08, 0x12, 0x0d, 0x0a, 0x09, 0x42, 0x4c, 0x4f, 0x42, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x10, - 0x12, 0x11, 0x0a, 0x0d, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x46, 0x4c, 0x41, - 0x47, 0x10, 0x20, 0x12, 0x11, 0x0a, 0x0d, 0x5a, 0x45, 0x52, 0x4f, 0x46, 0x49, 0x4c, 0x4c, 0x5f, - 0x46, 0x4c, 0x41, 0x47, 0x10, 0x40, 0x12, 0x10, 0x0a, 0x0b, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, - 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x80, 0x01, 0x12, 0x0e, 0x0a, 0x09, 0x45, 0x4e, 0x55, 0x4d, - 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x80, 0x02, 0x12, 0x18, 0x0a, 0x13, 0x41, 0x55, 0x54, 0x4f, - 0x5f, 0x49, 0x4e, 0x43, 0x52, 0x45, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, - 0x80, 0x04, 0x12, 0x13, 0x0a, 0x0e, 0x54, 0x49, 0x4d, 0x45, 0x53, 0x54, 0x41, 0x4d, 0x50, 0x5f, - 0x46, 0x4c, 0x41, 0x47, 0x10, 0x80, 0x08, 0x12, 0x0d, 0x0a, 0x08, 0x53, 0x45, 0x54, 0x5f, 0x46, - 0x4c, 0x41, 0x47, 0x10, 0x80, 0x10, 0x12, 0x1a, 0x0a, 0x15, 0x4e, 0x4f, 0x5f, 0x44, 0x45, 0x46, - 0x41, 0x55, 0x4c, 0x54, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, - 0x80, 0x20, 0x12, 0x17, 0x0a, 0x12, 0x4f, 0x4e, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, - 0x4e, 0x4f, 0x57, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x80, 0x40, 0x12, 0x0e, 0x0a, 0x08, 0x4e, - 0x55, 0x4d, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x80, 0x80, 0x02, 0x12, 0x13, 0x0a, 0x0d, 0x50, - 0x41, 0x52, 0x54, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x80, 0x80, 0x01, - 0x12, 0x10, 0x0a, 0x0a, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x80, - 0x80, 0x02, 0x12, 0x11, 0x0a, 0x0b, 0x55, 0x4e, 0x49, 0x51, 0x55, 0x45, 0x5f, 0x46, 0x4c, 0x41, - 0x47, 0x10, 0x80, 0x80, 0x04, 0x12, 0x11, 0x0a, 0x0b, 0x42, 0x49, 0x4e, 0x43, 0x4d, 0x50, 0x5f, - 0x46, 0x4c, 0x41, 0x47, 0x10, 0x80, 0x80, 0x08, 0x1a, 0x02, 0x10, 0x01, 0x2a, 0x6b, 0x0a, 0x04, - 0x46, 0x6c, 0x61, 0x67, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x0f, - 0x0a, 0x0a, 0x49, 0x53, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x4c, 0x10, 0x80, 0x02, 0x12, - 0x0f, 0x0a, 0x0a, 0x49, 0x53, 0x55, 0x4e, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x10, 0x80, 0x04, - 0x12, 0x0c, 0x0a, 0x07, 0x49, 0x53, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x10, 0x80, 0x08, 0x12, 0x0d, - 0x0a, 0x08, 0x49, 0x53, 0x51, 0x55, 0x4f, 0x54, 0x45, 0x44, 0x10, 0x80, 0x10, 0x12, 0x0b, 0x0a, - 0x06, 0x49, 0x53, 0x54, 0x45, 0x58, 0x54, 0x10, 0x80, 0x20, 0x12, 0x0d, 0x0a, 0x08, 0x49, 0x53, - 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x10, 0x80, 0x40, 0x2a, 0xc0, 0x03, 0x0a, 0x04, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x55, 0x4c, 0x4c, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x10, - 0x00, 0x12, 0x09, 0x0a, 0x04, 0x49, 0x4e, 0x54, 0x38, 0x10, 0x81, 0x02, 0x12, 0x0a, 0x0a, 0x05, - 0x55, 0x49, 0x4e, 0x54, 0x38, 0x10, 0x82, 0x06, 0x12, 0x0a, 0x0a, 0x05, 0x49, 0x4e, 0x54, 0x31, - 0x36, 0x10, 0x83, 0x02, 0x12, 0x0b, 0x0a, 0x06, 0x55, 0x49, 0x4e, 0x54, 0x31, 0x36, 0x10, 0x84, - 0x06, 0x12, 0x0a, 0x0a, 0x05, 0x49, 0x4e, 0x54, 0x32, 0x34, 0x10, 0x85, 0x02, 0x12, 0x0b, 0x0a, - 0x06, 0x55, 0x49, 0x4e, 0x54, 0x32, 0x34, 0x10, 0x86, 0x06, 0x12, 0x0a, 0x0a, 0x05, 0x49, 0x4e, - 0x54, 0x33, 0x32, 0x10, 0x87, 0x02, 0x12, 0x0b, 0x0a, 0x06, 0x55, 0x49, 0x4e, 0x54, 0x33, 0x32, - 0x10, 0x88, 0x06, 0x12, 0x0a, 0x0a, 0x05, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x89, 0x02, 0x12, - 0x0b, 0x0a, 0x06, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x8a, 0x06, 0x12, 0x0c, 0x0a, 0x07, - 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x33, 0x32, 0x10, 0x8b, 0x08, 0x12, 0x0c, 0x0a, 0x07, 0x46, 0x4c, - 0x4f, 0x41, 0x54, 0x36, 0x34, 0x10, 0x8c, 0x08, 0x12, 0x0e, 0x0a, 0x09, 0x54, 0x49, 0x4d, 0x45, - 0x53, 0x54, 0x41, 0x4d, 0x50, 0x10, 0x8d, 0x10, 0x12, 0x09, 0x0a, 0x04, 0x44, 0x41, 0x54, 0x45, - 0x10, 0x8e, 0x10, 0x12, 0x09, 0x0a, 0x04, 0x54, 0x49, 0x4d, 0x45, 0x10, 0x8f, 0x10, 0x12, 0x0d, - 0x0a, 0x08, 0x44, 0x41, 0x54, 0x45, 0x54, 0x49, 0x4d, 0x45, 0x10, 0x90, 0x10, 0x12, 0x09, 0x0a, - 0x04, 0x59, 0x45, 0x41, 0x52, 0x10, 0x91, 0x06, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x43, 0x49, - 0x4d, 0x41, 0x4c, 0x10, 0x12, 0x12, 0x09, 0x0a, 0x04, 0x54, 0x45, 0x58, 0x54, 0x10, 0x93, 0x30, - 0x12, 0x09, 0x0a, 0x04, 0x42, 0x4c, 0x4f, 0x42, 0x10, 0x94, 0x50, 0x12, 0x0c, 0x0a, 0x07, 0x56, - 0x41, 0x52, 0x43, 0x48, 0x41, 0x52, 0x10, 0x95, 0x30, 0x12, 0x0e, 0x0a, 0x09, 0x56, 0x41, 0x52, - 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x10, 0x96, 0x50, 0x12, 0x09, 0x0a, 0x04, 0x43, 0x48, 0x41, - 0x52, 0x10, 0x97, 0x30, 0x12, 0x0b, 0x0a, 0x06, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x10, 0x98, - 0x50, 0x12, 0x08, 0x0a, 0x03, 0x42, 0x49, 0x54, 0x10, 0x99, 0x10, 0x12, 0x09, 0x0a, 0x04, 0x45, - 0x4e, 0x55, 0x4d, 0x10, 0x9a, 0x10, 0x12, 0x08, 0x0a, 0x03, 0x53, 0x45, 0x54, 0x10, 0x9b, 0x10, - 0x12, 0x09, 0x0a, 0x05, 0x54, 0x55, 0x50, 0x4c, 0x45, 0x10, 0x1c, 0x12, 0x0d, 0x0a, 0x08, 0x47, - 0x45, 0x4f, 0x4d, 0x45, 0x54, 0x52, 0x59, 0x10, 0x9d, 0x10, 0x12, 0x09, 0x0a, 0x04, 0x4a, 0x53, - 0x4f, 0x4e, 0x10, 0x9e, 0x10, 0x12, 0x0e, 0x0a, 0x0a, 0x45, 0x58, 0x50, 0x52, 0x45, 0x53, 0x53, - 0x49, 0x4f, 0x4e, 0x10, 0x1f, 0x12, 0x0b, 0x0a, 0x06, 0x48, 0x45, 0x58, 0x4e, 0x55, 0x4d, 0x10, - 0xa0, 0x20, 0x12, 0x0b, 0x0a, 0x06, 0x48, 0x45, 0x58, 0x56, 0x41, 0x4c, 0x10, 0xa1, 0x20, 0x12, - 0x0b, 0x0a, 0x06, 0x42, 0x49, 0x54, 0x4e, 0x55, 0x4d, 0x10, 0xa2, 0x20, 0x2a, 0x46, 0x0a, 0x10, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, - 0x07, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, - 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x4f, 0x4c, 0x4c, 0x42, 0x41, - 0x43, 0x4b, 0x10, 0x03, 0x2a, 0x3b, 0x0a, 0x0f, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x54, 0x61, - 0x62, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x56, 0x49, 0x45, 0x57, 0x53, - 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x53, 0x10, 0x01, 0x12, 0x07, - 0x0a, 0x03, 0x41, 0x4c, 0x4c, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x55, 0x44, 0x46, 0x53, 0x10, - 0x03, 0x42, 0x35, 0x0a, 0x0f, 0x69, 0x6f, 0x2e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x73, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x22, 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, 0x71, 0x75, 0x65, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x15, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x61, 0x67, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x30, + 0x0a, 0x14, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, + 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x62, 0x69, + 0x6e, 0x6c, 0x6f, 0x67, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, + 0x12, 0x47, 0x0a, 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x65, 0x63, + 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1d, 0x66, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, + 0x61, 0x67, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x70, 0x75, + 0x5f, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x63, 0x70, + 0x75, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x71, 0x70, 0x73, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x01, 0x52, 0x03, 0x71, 0x70, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x74, 0x61, 0x62, 0x6c, + 0x65, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, + 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x63, 0x68, + 0x65, 0x6d, 0x61, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x2e, 0x0a, 0x13, 0x76, 0x69, + 0x65, 0x77, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x64, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x76, 0x69, 0x65, 0x77, 0x53, 0x63, 0x68, + 0x65, 0x6d, 0x61, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x64, + 0x66, 0x73, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0b, 0x75, 0x64, 0x66, 0x73, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x23, 0x0a, + 0x0d, 0x74, 0x78, 0x5f, 0x75, 0x6e, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x74, 0x78, 0x55, 0x6e, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, + 0x65, 0x64, 0x22, 0xf6, 0x01, 0x0a, 0x0e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, + 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x12, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x54, 0x61, 0x62, 0x6c, + 0x65, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x34, 0x0a, 0x16, 0x75, 0x6e, 0x68, 0x65, 0x61, + 0x6c, 0x74, 0x68, 0x79, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x75, 0x6e, 0x68, 0x65, 0x61, 0x6c, 0x74, + 0x68, 0x79, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x3d, 0x0a, + 0x1b, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x61, 0x67, + 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x18, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, + 0x61, 0x67, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x4d, 0x69, 0x6e, 0x12, 0x3d, 0x0a, 0x1b, + 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x61, 0x67, 0x5f, + 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x18, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x61, + 0x67, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x4d, 0x61, 0x78, 0x22, 0x95, 0x02, 0x0a, 0x14, + 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x54, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x6e, 0x67, 0x12, 0x3f, 0x0a, 0x1c, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, + 0x5f, 0x74, 0x65, 0x72, 0x6d, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x19, 0x70, 0x72, 0x69, + 0x6d, 0x61, 0x72, 0x79, 0x54, 0x65, 0x72, 0x6d, 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3b, 0x0a, 0x0e, 0x72, 0x65, 0x61, 0x6c, 0x74, 0x69, + 0x6d, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, + 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x61, 0x6c, 0x74, 0x69, 0x6d, 0x65, 0x53, + 0x74, 0x61, 0x74, 0x73, 0x52, 0x0d, 0x72, 0x65, 0x61, 0x6c, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, + 0x61, 0x74, 0x73, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, + 0x69, 0x61, 0x73, 0x18, 0x05, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4a, 0x04, 0x08, + 0x06, 0x10, 0x07, 0x22, 0xae, 0x01, 0x0a, 0x13, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x64, + 0x74, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x74, 0x69, 0x64, 0x12, + 0x2d, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, + 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x21, + 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x64, 0x12, 0x31, 0x0a, 0x0c, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, + 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, + 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x0c, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, + 0x61, 0x6e, 0x74, 0x73, 0x22, 0x91, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x06, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x12, 0x35, 0x0a, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x53, 0x63, 0x68, + 0x65, 0x6d, 0x61, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x09, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x6d, 0x0a, 0x07, 0x55, 0x44, 0x46, 0x49, + 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x61, 0x67, 0x67, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x61, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x2c, 0x0a, 0x0b, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0b, + 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x22, 0xd5, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x53, + 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, + 0x04, 0x75, 0x64, 0x66, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x2e, 0x55, 0x44, 0x46, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x75, 0x64, 0x66, + 0x73, 0x12, 0x58, 0x0a, 0x10, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x74, 0x61, 0x62, 0x6c, + 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x42, 0x0a, 0x14, 0x54, + 0x61, 0x62, 0x6c, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 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, + 0x92, 0x03, 0x0a, 0x09, 0x4d, 0x79, 0x53, 0x71, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x09, 0x0a, + 0x05, 0x45, 0x4d, 0x50, 0x54, 0x59, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x4e, 0x4f, 0x54, 0x5f, + 0x4e, 0x55, 0x4c, 0x4c, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x50, + 0x52, 0x49, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x02, 0x12, 0x13, 0x0a, + 0x0f, 0x55, 0x4e, 0x49, 0x51, 0x55, 0x45, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x46, 0x4c, 0x41, 0x47, + 0x10, 0x04, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x50, 0x4c, 0x45, 0x5f, 0x4b, + 0x45, 0x59, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x08, 0x12, 0x0d, 0x0a, 0x09, 0x42, 0x4c, 0x4f, + 0x42, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x10, 0x12, 0x11, 0x0a, 0x0d, 0x55, 0x4e, 0x53, 0x49, + 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x20, 0x12, 0x11, 0x0a, 0x0d, 0x5a, + 0x45, 0x52, 0x4f, 0x46, 0x49, 0x4c, 0x4c, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x40, 0x12, 0x10, + 0x0a, 0x0b, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x80, 0x01, + 0x12, 0x0e, 0x0a, 0x09, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x80, 0x02, + 0x12, 0x18, 0x0a, 0x13, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x49, 0x4e, 0x43, 0x52, 0x45, 0x4d, 0x45, + 0x4e, 0x54, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x80, 0x04, 0x12, 0x13, 0x0a, 0x0e, 0x54, 0x49, + 0x4d, 0x45, 0x53, 0x54, 0x41, 0x4d, 0x50, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x80, 0x08, 0x12, + 0x0d, 0x0a, 0x08, 0x53, 0x45, 0x54, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x80, 0x10, 0x12, 0x1a, + 0x0a, 0x15, 0x4e, 0x4f, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x5f, 0x56, 0x41, 0x4c, + 0x55, 0x45, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x80, 0x20, 0x12, 0x17, 0x0a, 0x12, 0x4f, 0x4e, + 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x4e, 0x4f, 0x57, 0x5f, 0x46, 0x4c, 0x41, 0x47, + 0x10, 0x80, 0x40, 0x12, 0x0e, 0x0a, 0x08, 0x4e, 0x55, 0x4d, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, + 0x80, 0x80, 0x02, 0x12, 0x13, 0x0a, 0x0d, 0x50, 0x41, 0x52, 0x54, 0x5f, 0x4b, 0x45, 0x59, 0x5f, + 0x46, 0x4c, 0x41, 0x47, 0x10, 0x80, 0x80, 0x01, 0x12, 0x10, 0x0a, 0x0a, 0x47, 0x52, 0x4f, 0x55, + 0x50, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x80, 0x80, 0x02, 0x12, 0x11, 0x0a, 0x0b, 0x55, 0x4e, + 0x49, 0x51, 0x55, 0x45, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x80, 0x80, 0x04, 0x12, 0x11, 0x0a, + 0x0b, 0x42, 0x49, 0x4e, 0x43, 0x4d, 0x50, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x10, 0x80, 0x80, 0x08, + 0x1a, 0x02, 0x10, 0x01, 0x2a, 0x6b, 0x0a, 0x04, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x08, 0x0a, 0x04, + 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0a, 0x49, 0x53, 0x49, 0x4e, 0x54, 0x45, + 0x47, 0x52, 0x41, 0x4c, 0x10, 0x80, 0x02, 0x12, 0x0f, 0x0a, 0x0a, 0x49, 0x53, 0x55, 0x4e, 0x53, + 0x49, 0x47, 0x4e, 0x45, 0x44, 0x10, 0x80, 0x04, 0x12, 0x0c, 0x0a, 0x07, 0x49, 0x53, 0x46, 0x4c, + 0x4f, 0x41, 0x54, 0x10, 0x80, 0x08, 0x12, 0x0d, 0x0a, 0x08, 0x49, 0x53, 0x51, 0x55, 0x4f, 0x54, + 0x45, 0x44, 0x10, 0x80, 0x10, 0x12, 0x0b, 0x0a, 0x06, 0x49, 0x53, 0x54, 0x45, 0x58, 0x54, 0x10, + 0x80, 0x20, 0x12, 0x0d, 0x0a, 0x08, 0x49, 0x53, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x10, 0x80, + 0x40, 0x2a, 0xcd, 0x03, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x55, + 0x4c, 0x4c, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x04, 0x49, 0x4e, 0x54, + 0x38, 0x10, 0x81, 0x02, 0x12, 0x0a, 0x0a, 0x05, 0x55, 0x49, 0x4e, 0x54, 0x38, 0x10, 0x82, 0x06, + 0x12, 0x0a, 0x0a, 0x05, 0x49, 0x4e, 0x54, 0x31, 0x36, 0x10, 0x83, 0x02, 0x12, 0x0b, 0x0a, 0x06, + 0x55, 0x49, 0x4e, 0x54, 0x31, 0x36, 0x10, 0x84, 0x06, 0x12, 0x0a, 0x0a, 0x05, 0x49, 0x4e, 0x54, + 0x32, 0x34, 0x10, 0x85, 0x02, 0x12, 0x0b, 0x0a, 0x06, 0x55, 0x49, 0x4e, 0x54, 0x32, 0x34, 0x10, + 0x86, 0x06, 0x12, 0x0a, 0x0a, 0x05, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x87, 0x02, 0x12, 0x0b, + 0x0a, 0x06, 0x55, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x88, 0x06, 0x12, 0x0a, 0x0a, 0x05, 0x49, + 0x4e, 0x54, 0x36, 0x34, 0x10, 0x89, 0x02, 0x12, 0x0b, 0x0a, 0x06, 0x55, 0x49, 0x4e, 0x54, 0x36, + 0x34, 0x10, 0x8a, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x33, 0x32, 0x10, + 0x8b, 0x08, 0x12, 0x0c, 0x0a, 0x07, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x36, 0x34, 0x10, 0x8c, 0x08, + 0x12, 0x0e, 0x0a, 0x09, 0x54, 0x49, 0x4d, 0x45, 0x53, 0x54, 0x41, 0x4d, 0x50, 0x10, 0x8d, 0x10, + 0x12, 0x09, 0x0a, 0x04, 0x44, 0x41, 0x54, 0x45, 0x10, 0x8e, 0x10, 0x12, 0x09, 0x0a, 0x04, 0x54, + 0x49, 0x4d, 0x45, 0x10, 0x8f, 0x10, 0x12, 0x0d, 0x0a, 0x08, 0x44, 0x41, 0x54, 0x45, 0x54, 0x49, + 0x4d, 0x45, 0x10, 0x90, 0x10, 0x12, 0x09, 0x0a, 0x04, 0x59, 0x45, 0x41, 0x52, 0x10, 0x91, 0x06, + 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x43, 0x49, 0x4d, 0x41, 0x4c, 0x10, 0x12, 0x12, 0x09, 0x0a, + 0x04, 0x54, 0x45, 0x58, 0x54, 0x10, 0x93, 0x30, 0x12, 0x09, 0x0a, 0x04, 0x42, 0x4c, 0x4f, 0x42, + 0x10, 0x94, 0x50, 0x12, 0x0c, 0x0a, 0x07, 0x56, 0x41, 0x52, 0x43, 0x48, 0x41, 0x52, 0x10, 0x95, + 0x30, 0x12, 0x0e, 0x0a, 0x09, 0x56, 0x41, 0x52, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x10, 0x96, + 0x50, 0x12, 0x09, 0x0a, 0x04, 0x43, 0x48, 0x41, 0x52, 0x10, 0x97, 0x30, 0x12, 0x0b, 0x0a, 0x06, + 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x10, 0x98, 0x50, 0x12, 0x08, 0x0a, 0x03, 0x42, 0x49, 0x54, + 0x10, 0x99, 0x10, 0x12, 0x09, 0x0a, 0x04, 0x45, 0x4e, 0x55, 0x4d, 0x10, 0x9a, 0x10, 0x12, 0x08, + 0x0a, 0x03, 0x53, 0x45, 0x54, 0x10, 0x9b, 0x10, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x55, 0x50, 0x4c, + 0x45, 0x10, 0x1c, 0x12, 0x0d, 0x0a, 0x08, 0x47, 0x45, 0x4f, 0x4d, 0x45, 0x54, 0x52, 0x59, 0x10, + 0x9d, 0x10, 0x12, 0x09, 0x0a, 0x04, 0x4a, 0x53, 0x4f, 0x4e, 0x10, 0x9e, 0x10, 0x12, 0x0e, 0x0a, + 0x0a, 0x45, 0x58, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x1f, 0x12, 0x0b, 0x0a, + 0x06, 0x48, 0x45, 0x58, 0x4e, 0x55, 0x4d, 0x10, 0xa0, 0x20, 0x12, 0x0b, 0x0a, 0x06, 0x48, 0x45, + 0x58, 0x56, 0x41, 0x4c, 0x10, 0xa1, 0x20, 0x12, 0x0b, 0x0a, 0x06, 0x42, 0x49, 0x54, 0x4e, 0x55, + 0x4d, 0x10, 0xa2, 0x20, 0x12, 0x0b, 0x0a, 0x06, 0x56, 0x45, 0x43, 0x54, 0x4f, 0x52, 0x10, 0xa3, + 0x10, 0x2a, 0x46, 0x0a, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, + 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x10, 0x01, 0x12, + 0x0c, 0x0a, 0x08, 0x52, 0x4f, 0x4c, 0x4c, 0x42, 0x41, 0x43, 0x4b, 0x10, 0x02, 0x12, 0x0a, 0x0a, + 0x06, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x03, 0x2a, 0x3b, 0x0a, 0x0f, 0x53, 0x63, 0x68, + 0x65, 0x6d, 0x61, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a, 0x05, + 0x56, 0x49, 0x45, 0x57, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x41, 0x42, 0x4c, 0x45, + 0x53, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4c, 0x4c, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, + 0x55, 0x44, 0x46, 0x53, 0x10, 0x03, 0x42, 0x35, 0x0a, 0x0f, 0x69, 0x6f, 0x2e, 0x76, 0x69, 0x74, + 0x65, 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x22, 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, 0x71, 0x75, 0x65, 0x72, 0x79, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -6661,7 +6809,7 @@ func file_query_proto_rawDescGZIP() []byte { } var file_query_proto_enumTypes = make([]protoimpl.EnumInfo, 12) -var file_query_proto_msgTypes = make([]protoimpl.MessageInfo, 68) +var file_query_proto_msgTypes = make([]protoimpl.MessageInfo, 70) var file_query_proto_goTypes = []any{ (MySqlFlag)(0), // 0: query.MySqlFlag (Flag)(0), // 1: query.Flag @@ -6714,46 +6862,48 @@ var file_query_proto_goTypes = []any{ (*ConcludeTransactionResponse)(nil), // 48: query.ConcludeTransactionResponse (*ReadTransactionRequest)(nil), // 49: query.ReadTransactionRequest (*ReadTransactionResponse)(nil), // 50: query.ReadTransactionResponse - (*BeginExecuteRequest)(nil), // 51: query.BeginExecuteRequest - (*BeginExecuteResponse)(nil), // 52: query.BeginExecuteResponse - (*BeginStreamExecuteRequest)(nil), // 53: query.BeginStreamExecuteRequest - (*BeginStreamExecuteResponse)(nil), // 54: query.BeginStreamExecuteResponse - (*MessageStreamRequest)(nil), // 55: query.MessageStreamRequest - (*MessageStreamResponse)(nil), // 56: query.MessageStreamResponse - (*MessageAckRequest)(nil), // 57: query.MessageAckRequest - (*MessageAckResponse)(nil), // 58: query.MessageAckResponse - (*ReserveExecuteRequest)(nil), // 59: query.ReserveExecuteRequest - (*ReserveExecuteResponse)(nil), // 60: query.ReserveExecuteResponse - (*ReserveStreamExecuteRequest)(nil), // 61: query.ReserveStreamExecuteRequest - (*ReserveStreamExecuteResponse)(nil), // 62: query.ReserveStreamExecuteResponse - (*ReserveBeginExecuteRequest)(nil), // 63: query.ReserveBeginExecuteRequest - (*ReserveBeginExecuteResponse)(nil), // 64: query.ReserveBeginExecuteResponse - (*ReserveBeginStreamExecuteRequest)(nil), // 65: query.ReserveBeginStreamExecuteRequest - (*ReserveBeginStreamExecuteResponse)(nil), // 66: query.ReserveBeginStreamExecuteResponse - (*ReleaseRequest)(nil), // 67: query.ReleaseRequest - (*ReleaseResponse)(nil), // 68: query.ReleaseResponse - (*StreamHealthRequest)(nil), // 69: query.StreamHealthRequest - (*RealtimeStats)(nil), // 70: query.RealtimeStats - (*AggregateStats)(nil), // 71: query.AggregateStats - (*StreamHealthResponse)(nil), // 72: query.StreamHealthResponse - (*TransactionMetadata)(nil), // 73: query.TransactionMetadata - (*GetSchemaRequest)(nil), // 74: query.GetSchemaRequest - (*UDFInfo)(nil), // 75: query.UDFInfo - (*GetSchemaResponse)(nil), // 76: query.GetSchemaResponse - nil, // 77: query.BoundQuery.BindVariablesEntry - (*StreamEvent_Statement)(nil), // 78: query.StreamEvent.Statement - nil, // 79: query.GetSchemaResponse.TableDefinitionEntry - (topodata.TabletType)(0), // 80: topodata.TabletType - (*vtrpc.CallerID)(nil), // 81: vtrpc.CallerID - (*vtrpc.RPCError)(nil), // 82: vtrpc.RPCError - (*topodata.TabletAlias)(nil), // 83: topodata.TabletAlias + (*UnresolvedTransactionsRequest)(nil), // 51: query.UnresolvedTransactionsRequest + (*UnresolvedTransactionsResponse)(nil), // 52: query.UnresolvedTransactionsResponse + (*BeginExecuteRequest)(nil), // 53: query.BeginExecuteRequest + (*BeginExecuteResponse)(nil), // 54: query.BeginExecuteResponse + (*BeginStreamExecuteRequest)(nil), // 55: query.BeginStreamExecuteRequest + (*BeginStreamExecuteResponse)(nil), // 56: query.BeginStreamExecuteResponse + (*MessageStreamRequest)(nil), // 57: query.MessageStreamRequest + (*MessageStreamResponse)(nil), // 58: query.MessageStreamResponse + (*MessageAckRequest)(nil), // 59: query.MessageAckRequest + (*MessageAckResponse)(nil), // 60: query.MessageAckResponse + (*ReserveExecuteRequest)(nil), // 61: query.ReserveExecuteRequest + (*ReserveExecuteResponse)(nil), // 62: query.ReserveExecuteResponse + (*ReserveStreamExecuteRequest)(nil), // 63: query.ReserveStreamExecuteRequest + (*ReserveStreamExecuteResponse)(nil), // 64: query.ReserveStreamExecuteResponse + (*ReserveBeginExecuteRequest)(nil), // 65: query.ReserveBeginExecuteRequest + (*ReserveBeginExecuteResponse)(nil), // 66: query.ReserveBeginExecuteResponse + (*ReserveBeginStreamExecuteRequest)(nil), // 67: query.ReserveBeginStreamExecuteRequest + (*ReserveBeginStreamExecuteResponse)(nil), // 68: query.ReserveBeginStreamExecuteResponse + (*ReleaseRequest)(nil), // 69: query.ReleaseRequest + (*ReleaseResponse)(nil), // 70: query.ReleaseResponse + (*StreamHealthRequest)(nil), // 71: query.StreamHealthRequest + (*RealtimeStats)(nil), // 72: query.RealtimeStats + (*AggregateStats)(nil), // 73: query.AggregateStats + (*StreamHealthResponse)(nil), // 74: query.StreamHealthResponse + (*TransactionMetadata)(nil), // 75: query.TransactionMetadata + (*GetSchemaRequest)(nil), // 76: query.GetSchemaRequest + (*UDFInfo)(nil), // 77: query.UDFInfo + (*GetSchemaResponse)(nil), // 78: query.GetSchemaResponse + nil, // 79: query.BoundQuery.BindVariablesEntry + (*StreamEvent_Statement)(nil), // 80: query.StreamEvent.Statement + nil, // 81: query.GetSchemaResponse.TableDefinitionEntry + (topodata.TabletType)(0), // 82: topodata.TabletType + (*vtrpc.CallerID)(nil), // 83: vtrpc.CallerID + (*vtrpc.RPCError)(nil), // 84: vtrpc.RPCError + (*topodata.TabletAlias)(nil), // 85: topodata.TabletAlias } var file_query_proto_depIdxs = []int32{ - 80, // 0: query.Target.tablet_type:type_name -> topodata.TabletType + 82, // 0: query.Target.tablet_type:type_name -> topodata.TabletType 2, // 1: query.Value.type:type_name -> query.Type 2, // 2: query.BindVariable.type:type_name -> query.Type 15, // 3: query.BindVariable.values:type_name -> query.Value - 77, // 4: query.BoundQuery.bind_variables:type_name -> query.BoundQuery.BindVariablesEntry + 79, // 4: query.BoundQuery.bind_variables:type_name -> query.BoundQuery.BindVariablesEntry 5, // 5: query.ExecuteOptions.included_fields:type_name -> query.ExecuteOptions.IncludedFields 6, // 6: query.ExecuteOptions.workload:type_name -> query.ExecuteOptions.Workload 7, // 7: query.ExecuteOptions.transaction_isolation:type_name -> query.ExecuteOptions.TransactionIsolation @@ -6763,138 +6913,142 @@ var file_query_proto_depIdxs = []int32{ 2, // 11: query.Field.type:type_name -> query.Type 19, // 12: query.QueryResult.fields:type_name -> query.Field 20, // 13: query.QueryResult.rows:type_name -> query.Row - 78, // 14: query.StreamEvent.statements:type_name -> query.StreamEvent.Statement + 80, // 14: query.StreamEvent.statements:type_name -> query.StreamEvent.Statement 14, // 15: query.StreamEvent.event_token:type_name -> query.EventToken - 81, // 16: query.ExecuteRequest.effective_caller_id:type_name -> vtrpc.CallerID + 83, // 16: query.ExecuteRequest.effective_caller_id:type_name -> vtrpc.CallerID 13, // 17: query.ExecuteRequest.immediate_caller_id:type_name -> query.VTGateCallerID 12, // 18: query.ExecuteRequest.target:type_name -> query.Target 17, // 19: query.ExecuteRequest.query:type_name -> query.BoundQuery 18, // 20: query.ExecuteRequest.options:type_name -> query.ExecuteOptions 21, // 21: query.ExecuteResponse.result:type_name -> query.QueryResult - 82, // 22: query.ResultWithError.error:type_name -> vtrpc.RPCError + 84, // 22: query.ResultWithError.error:type_name -> vtrpc.RPCError 21, // 23: query.ResultWithError.result:type_name -> query.QueryResult - 81, // 24: query.StreamExecuteRequest.effective_caller_id:type_name -> vtrpc.CallerID + 83, // 24: query.StreamExecuteRequest.effective_caller_id:type_name -> vtrpc.CallerID 13, // 25: query.StreamExecuteRequest.immediate_caller_id:type_name -> query.VTGateCallerID 12, // 26: query.StreamExecuteRequest.target:type_name -> query.Target 17, // 27: query.StreamExecuteRequest.query:type_name -> query.BoundQuery 18, // 28: query.StreamExecuteRequest.options:type_name -> query.ExecuteOptions 21, // 29: query.StreamExecuteResponse.result:type_name -> query.QueryResult - 81, // 30: query.BeginRequest.effective_caller_id:type_name -> vtrpc.CallerID + 83, // 30: query.BeginRequest.effective_caller_id:type_name -> vtrpc.CallerID 13, // 31: query.BeginRequest.immediate_caller_id:type_name -> query.VTGateCallerID 12, // 32: query.BeginRequest.target:type_name -> query.Target 18, // 33: query.BeginRequest.options:type_name -> query.ExecuteOptions - 83, // 34: query.BeginResponse.tablet_alias:type_name -> topodata.TabletAlias - 81, // 35: query.CommitRequest.effective_caller_id:type_name -> vtrpc.CallerID + 85, // 34: query.BeginResponse.tablet_alias:type_name -> topodata.TabletAlias + 83, // 35: query.CommitRequest.effective_caller_id:type_name -> vtrpc.CallerID 13, // 36: query.CommitRequest.immediate_caller_id:type_name -> query.VTGateCallerID 12, // 37: query.CommitRequest.target:type_name -> query.Target - 81, // 38: query.RollbackRequest.effective_caller_id:type_name -> vtrpc.CallerID + 83, // 38: query.RollbackRequest.effective_caller_id:type_name -> vtrpc.CallerID 13, // 39: query.RollbackRequest.immediate_caller_id:type_name -> query.VTGateCallerID 12, // 40: query.RollbackRequest.target:type_name -> query.Target - 81, // 41: query.PrepareRequest.effective_caller_id:type_name -> vtrpc.CallerID + 83, // 41: query.PrepareRequest.effective_caller_id:type_name -> vtrpc.CallerID 13, // 42: query.PrepareRequest.immediate_caller_id:type_name -> query.VTGateCallerID 12, // 43: query.PrepareRequest.target:type_name -> query.Target - 81, // 44: query.CommitPreparedRequest.effective_caller_id:type_name -> vtrpc.CallerID + 83, // 44: query.CommitPreparedRequest.effective_caller_id:type_name -> vtrpc.CallerID 13, // 45: query.CommitPreparedRequest.immediate_caller_id:type_name -> query.VTGateCallerID 12, // 46: query.CommitPreparedRequest.target:type_name -> query.Target - 81, // 47: query.RollbackPreparedRequest.effective_caller_id:type_name -> vtrpc.CallerID + 83, // 47: query.RollbackPreparedRequest.effective_caller_id:type_name -> vtrpc.CallerID 13, // 48: query.RollbackPreparedRequest.immediate_caller_id:type_name -> query.VTGateCallerID 12, // 49: query.RollbackPreparedRequest.target:type_name -> query.Target - 81, // 50: query.CreateTransactionRequest.effective_caller_id:type_name -> vtrpc.CallerID + 83, // 50: query.CreateTransactionRequest.effective_caller_id:type_name -> vtrpc.CallerID 13, // 51: query.CreateTransactionRequest.immediate_caller_id:type_name -> query.VTGateCallerID 12, // 52: query.CreateTransactionRequest.target:type_name -> query.Target 12, // 53: query.CreateTransactionRequest.participants:type_name -> query.Target - 81, // 54: query.StartCommitRequest.effective_caller_id:type_name -> vtrpc.CallerID + 83, // 54: query.StartCommitRequest.effective_caller_id:type_name -> vtrpc.CallerID 13, // 55: query.StartCommitRequest.immediate_caller_id:type_name -> query.VTGateCallerID 12, // 56: query.StartCommitRequest.target:type_name -> query.Target - 81, // 57: query.SetRollbackRequest.effective_caller_id:type_name -> vtrpc.CallerID + 83, // 57: query.SetRollbackRequest.effective_caller_id:type_name -> vtrpc.CallerID 13, // 58: query.SetRollbackRequest.immediate_caller_id:type_name -> query.VTGateCallerID 12, // 59: query.SetRollbackRequest.target:type_name -> query.Target - 81, // 60: query.ConcludeTransactionRequest.effective_caller_id:type_name -> vtrpc.CallerID + 83, // 60: query.ConcludeTransactionRequest.effective_caller_id:type_name -> vtrpc.CallerID 13, // 61: query.ConcludeTransactionRequest.immediate_caller_id:type_name -> query.VTGateCallerID 12, // 62: query.ConcludeTransactionRequest.target:type_name -> query.Target - 81, // 63: query.ReadTransactionRequest.effective_caller_id:type_name -> vtrpc.CallerID + 83, // 63: query.ReadTransactionRequest.effective_caller_id:type_name -> vtrpc.CallerID 13, // 64: query.ReadTransactionRequest.immediate_caller_id:type_name -> query.VTGateCallerID 12, // 65: query.ReadTransactionRequest.target:type_name -> query.Target - 73, // 66: query.ReadTransactionResponse.metadata:type_name -> query.TransactionMetadata - 81, // 67: query.BeginExecuteRequest.effective_caller_id:type_name -> vtrpc.CallerID - 13, // 68: query.BeginExecuteRequest.immediate_caller_id:type_name -> query.VTGateCallerID - 12, // 69: query.BeginExecuteRequest.target:type_name -> query.Target - 17, // 70: query.BeginExecuteRequest.query:type_name -> query.BoundQuery - 18, // 71: query.BeginExecuteRequest.options:type_name -> query.ExecuteOptions - 82, // 72: query.BeginExecuteResponse.error:type_name -> vtrpc.RPCError - 21, // 73: query.BeginExecuteResponse.result:type_name -> query.QueryResult - 83, // 74: query.BeginExecuteResponse.tablet_alias:type_name -> topodata.TabletAlias - 81, // 75: query.BeginStreamExecuteRequest.effective_caller_id:type_name -> vtrpc.CallerID - 13, // 76: query.BeginStreamExecuteRequest.immediate_caller_id:type_name -> query.VTGateCallerID - 12, // 77: query.BeginStreamExecuteRequest.target:type_name -> query.Target - 17, // 78: query.BeginStreamExecuteRequest.query:type_name -> query.BoundQuery - 18, // 79: query.BeginStreamExecuteRequest.options:type_name -> query.ExecuteOptions - 82, // 80: query.BeginStreamExecuteResponse.error:type_name -> vtrpc.RPCError - 21, // 81: query.BeginStreamExecuteResponse.result:type_name -> query.QueryResult - 83, // 82: query.BeginStreamExecuteResponse.tablet_alias:type_name -> topodata.TabletAlias - 81, // 83: query.MessageStreamRequest.effective_caller_id:type_name -> vtrpc.CallerID - 13, // 84: query.MessageStreamRequest.immediate_caller_id:type_name -> query.VTGateCallerID - 12, // 85: query.MessageStreamRequest.target:type_name -> query.Target - 21, // 86: query.MessageStreamResponse.result:type_name -> query.QueryResult - 81, // 87: query.MessageAckRequest.effective_caller_id:type_name -> vtrpc.CallerID - 13, // 88: query.MessageAckRequest.immediate_caller_id:type_name -> query.VTGateCallerID - 12, // 89: query.MessageAckRequest.target:type_name -> query.Target - 15, // 90: query.MessageAckRequest.ids:type_name -> query.Value - 21, // 91: query.MessageAckResponse.result:type_name -> query.QueryResult - 81, // 92: query.ReserveExecuteRequest.effective_caller_id:type_name -> vtrpc.CallerID - 13, // 93: query.ReserveExecuteRequest.immediate_caller_id:type_name -> query.VTGateCallerID - 12, // 94: query.ReserveExecuteRequest.target:type_name -> query.Target - 17, // 95: query.ReserveExecuteRequest.query:type_name -> query.BoundQuery - 18, // 96: query.ReserveExecuteRequest.options:type_name -> query.ExecuteOptions - 82, // 97: query.ReserveExecuteResponse.error:type_name -> vtrpc.RPCError - 21, // 98: query.ReserveExecuteResponse.result:type_name -> query.QueryResult - 83, // 99: query.ReserveExecuteResponse.tablet_alias:type_name -> topodata.TabletAlias - 81, // 100: query.ReserveStreamExecuteRequest.effective_caller_id:type_name -> vtrpc.CallerID - 13, // 101: query.ReserveStreamExecuteRequest.immediate_caller_id:type_name -> query.VTGateCallerID - 12, // 102: query.ReserveStreamExecuteRequest.target:type_name -> query.Target - 17, // 103: query.ReserveStreamExecuteRequest.query:type_name -> query.BoundQuery - 18, // 104: query.ReserveStreamExecuteRequest.options:type_name -> query.ExecuteOptions - 82, // 105: query.ReserveStreamExecuteResponse.error:type_name -> vtrpc.RPCError - 21, // 106: query.ReserveStreamExecuteResponse.result:type_name -> query.QueryResult - 83, // 107: query.ReserveStreamExecuteResponse.tablet_alias:type_name -> topodata.TabletAlias - 81, // 108: query.ReserveBeginExecuteRequest.effective_caller_id:type_name -> vtrpc.CallerID - 13, // 109: query.ReserveBeginExecuteRequest.immediate_caller_id:type_name -> query.VTGateCallerID - 12, // 110: query.ReserveBeginExecuteRequest.target:type_name -> query.Target - 17, // 111: query.ReserveBeginExecuteRequest.query:type_name -> query.BoundQuery - 18, // 112: query.ReserveBeginExecuteRequest.options:type_name -> query.ExecuteOptions - 82, // 113: query.ReserveBeginExecuteResponse.error:type_name -> vtrpc.RPCError - 21, // 114: query.ReserveBeginExecuteResponse.result:type_name -> query.QueryResult - 83, // 115: query.ReserveBeginExecuteResponse.tablet_alias:type_name -> topodata.TabletAlias - 81, // 116: query.ReserveBeginStreamExecuteRequest.effective_caller_id:type_name -> vtrpc.CallerID - 13, // 117: query.ReserveBeginStreamExecuteRequest.immediate_caller_id:type_name -> query.VTGateCallerID - 12, // 118: query.ReserveBeginStreamExecuteRequest.target:type_name -> query.Target - 17, // 119: query.ReserveBeginStreamExecuteRequest.query:type_name -> query.BoundQuery - 18, // 120: query.ReserveBeginStreamExecuteRequest.options:type_name -> query.ExecuteOptions - 82, // 121: query.ReserveBeginStreamExecuteResponse.error:type_name -> vtrpc.RPCError - 21, // 122: query.ReserveBeginStreamExecuteResponse.result:type_name -> query.QueryResult - 83, // 123: query.ReserveBeginStreamExecuteResponse.tablet_alias:type_name -> topodata.TabletAlias - 81, // 124: query.ReleaseRequest.effective_caller_id:type_name -> vtrpc.CallerID - 13, // 125: query.ReleaseRequest.immediate_caller_id:type_name -> query.VTGateCallerID - 12, // 126: query.ReleaseRequest.target:type_name -> query.Target - 12, // 127: query.StreamHealthResponse.target:type_name -> query.Target - 70, // 128: query.StreamHealthResponse.realtime_stats:type_name -> query.RealtimeStats - 83, // 129: query.StreamHealthResponse.tablet_alias:type_name -> topodata.TabletAlias - 3, // 130: query.TransactionMetadata.state:type_name -> query.TransactionState - 12, // 131: query.TransactionMetadata.participants:type_name -> query.Target - 12, // 132: query.GetSchemaRequest.target:type_name -> query.Target - 4, // 133: query.GetSchemaRequest.table_type:type_name -> query.SchemaTableType - 2, // 134: query.UDFInfo.return_type:type_name -> query.Type - 75, // 135: query.GetSchemaResponse.udfs:type_name -> query.UDFInfo - 79, // 136: query.GetSchemaResponse.table_definition:type_name -> query.GetSchemaResponse.TableDefinitionEntry - 16, // 137: query.BoundQuery.BindVariablesEntry.value:type_name -> query.BindVariable - 11, // 138: query.StreamEvent.Statement.category:type_name -> query.StreamEvent.Statement.Category - 19, // 139: query.StreamEvent.Statement.primary_key_fields:type_name -> query.Field - 20, // 140: query.StreamEvent.Statement.primary_key_values:type_name -> query.Row - 141, // [141:141] is the sub-list for method output_type - 141, // [141:141] is the sub-list for method input_type - 141, // [141:141] is the sub-list for extension type_name - 141, // [141:141] is the sub-list for extension extendee - 0, // [0:141] is the sub-list for field type_name + 75, // 66: query.ReadTransactionResponse.metadata:type_name -> query.TransactionMetadata + 83, // 67: query.UnresolvedTransactionsRequest.effective_caller_id:type_name -> vtrpc.CallerID + 13, // 68: query.UnresolvedTransactionsRequest.immediate_caller_id:type_name -> query.VTGateCallerID + 12, // 69: query.UnresolvedTransactionsRequest.target:type_name -> query.Target + 75, // 70: query.UnresolvedTransactionsResponse.transactions:type_name -> query.TransactionMetadata + 83, // 71: query.BeginExecuteRequest.effective_caller_id:type_name -> vtrpc.CallerID + 13, // 72: query.BeginExecuteRequest.immediate_caller_id:type_name -> query.VTGateCallerID + 12, // 73: query.BeginExecuteRequest.target:type_name -> query.Target + 17, // 74: query.BeginExecuteRequest.query:type_name -> query.BoundQuery + 18, // 75: query.BeginExecuteRequest.options:type_name -> query.ExecuteOptions + 84, // 76: query.BeginExecuteResponse.error:type_name -> vtrpc.RPCError + 21, // 77: query.BeginExecuteResponse.result:type_name -> query.QueryResult + 85, // 78: query.BeginExecuteResponse.tablet_alias:type_name -> topodata.TabletAlias + 83, // 79: query.BeginStreamExecuteRequest.effective_caller_id:type_name -> vtrpc.CallerID + 13, // 80: query.BeginStreamExecuteRequest.immediate_caller_id:type_name -> query.VTGateCallerID + 12, // 81: query.BeginStreamExecuteRequest.target:type_name -> query.Target + 17, // 82: query.BeginStreamExecuteRequest.query:type_name -> query.BoundQuery + 18, // 83: query.BeginStreamExecuteRequest.options:type_name -> query.ExecuteOptions + 84, // 84: query.BeginStreamExecuteResponse.error:type_name -> vtrpc.RPCError + 21, // 85: query.BeginStreamExecuteResponse.result:type_name -> query.QueryResult + 85, // 86: query.BeginStreamExecuteResponse.tablet_alias:type_name -> topodata.TabletAlias + 83, // 87: query.MessageStreamRequest.effective_caller_id:type_name -> vtrpc.CallerID + 13, // 88: query.MessageStreamRequest.immediate_caller_id:type_name -> query.VTGateCallerID + 12, // 89: query.MessageStreamRequest.target:type_name -> query.Target + 21, // 90: query.MessageStreamResponse.result:type_name -> query.QueryResult + 83, // 91: query.MessageAckRequest.effective_caller_id:type_name -> vtrpc.CallerID + 13, // 92: query.MessageAckRequest.immediate_caller_id:type_name -> query.VTGateCallerID + 12, // 93: query.MessageAckRequest.target:type_name -> query.Target + 15, // 94: query.MessageAckRequest.ids:type_name -> query.Value + 21, // 95: query.MessageAckResponse.result:type_name -> query.QueryResult + 83, // 96: query.ReserveExecuteRequest.effective_caller_id:type_name -> vtrpc.CallerID + 13, // 97: query.ReserveExecuteRequest.immediate_caller_id:type_name -> query.VTGateCallerID + 12, // 98: query.ReserveExecuteRequest.target:type_name -> query.Target + 17, // 99: query.ReserveExecuteRequest.query:type_name -> query.BoundQuery + 18, // 100: query.ReserveExecuteRequest.options:type_name -> query.ExecuteOptions + 84, // 101: query.ReserveExecuteResponse.error:type_name -> vtrpc.RPCError + 21, // 102: query.ReserveExecuteResponse.result:type_name -> query.QueryResult + 85, // 103: query.ReserveExecuteResponse.tablet_alias:type_name -> topodata.TabletAlias + 83, // 104: query.ReserveStreamExecuteRequest.effective_caller_id:type_name -> vtrpc.CallerID + 13, // 105: query.ReserveStreamExecuteRequest.immediate_caller_id:type_name -> query.VTGateCallerID + 12, // 106: query.ReserveStreamExecuteRequest.target:type_name -> query.Target + 17, // 107: query.ReserveStreamExecuteRequest.query:type_name -> query.BoundQuery + 18, // 108: query.ReserveStreamExecuteRequest.options:type_name -> query.ExecuteOptions + 84, // 109: query.ReserveStreamExecuteResponse.error:type_name -> vtrpc.RPCError + 21, // 110: query.ReserveStreamExecuteResponse.result:type_name -> query.QueryResult + 85, // 111: query.ReserveStreamExecuteResponse.tablet_alias:type_name -> topodata.TabletAlias + 83, // 112: query.ReserveBeginExecuteRequest.effective_caller_id:type_name -> vtrpc.CallerID + 13, // 113: query.ReserveBeginExecuteRequest.immediate_caller_id:type_name -> query.VTGateCallerID + 12, // 114: query.ReserveBeginExecuteRequest.target:type_name -> query.Target + 17, // 115: query.ReserveBeginExecuteRequest.query:type_name -> query.BoundQuery + 18, // 116: query.ReserveBeginExecuteRequest.options:type_name -> query.ExecuteOptions + 84, // 117: query.ReserveBeginExecuteResponse.error:type_name -> vtrpc.RPCError + 21, // 118: query.ReserveBeginExecuteResponse.result:type_name -> query.QueryResult + 85, // 119: query.ReserveBeginExecuteResponse.tablet_alias:type_name -> topodata.TabletAlias + 83, // 120: query.ReserveBeginStreamExecuteRequest.effective_caller_id:type_name -> vtrpc.CallerID + 13, // 121: query.ReserveBeginStreamExecuteRequest.immediate_caller_id:type_name -> query.VTGateCallerID + 12, // 122: query.ReserveBeginStreamExecuteRequest.target:type_name -> query.Target + 17, // 123: query.ReserveBeginStreamExecuteRequest.query:type_name -> query.BoundQuery + 18, // 124: query.ReserveBeginStreamExecuteRequest.options:type_name -> query.ExecuteOptions + 84, // 125: query.ReserveBeginStreamExecuteResponse.error:type_name -> vtrpc.RPCError + 21, // 126: query.ReserveBeginStreamExecuteResponse.result:type_name -> query.QueryResult + 85, // 127: query.ReserveBeginStreamExecuteResponse.tablet_alias:type_name -> topodata.TabletAlias + 83, // 128: query.ReleaseRequest.effective_caller_id:type_name -> vtrpc.CallerID + 13, // 129: query.ReleaseRequest.immediate_caller_id:type_name -> query.VTGateCallerID + 12, // 130: query.ReleaseRequest.target:type_name -> query.Target + 12, // 131: query.StreamHealthResponse.target:type_name -> query.Target + 72, // 132: query.StreamHealthResponse.realtime_stats:type_name -> query.RealtimeStats + 85, // 133: query.StreamHealthResponse.tablet_alias:type_name -> topodata.TabletAlias + 3, // 134: query.TransactionMetadata.state:type_name -> query.TransactionState + 12, // 135: query.TransactionMetadata.participants:type_name -> query.Target + 12, // 136: query.GetSchemaRequest.target:type_name -> query.Target + 4, // 137: query.GetSchemaRequest.table_type:type_name -> query.SchemaTableType + 2, // 138: query.UDFInfo.return_type:type_name -> query.Type + 77, // 139: query.GetSchemaResponse.udfs:type_name -> query.UDFInfo + 81, // 140: query.GetSchemaResponse.table_definition:type_name -> query.GetSchemaResponse.TableDefinitionEntry + 16, // 141: query.BoundQuery.BindVariablesEntry.value:type_name -> query.BindVariable + 11, // 142: query.StreamEvent.Statement.category:type_name -> query.StreamEvent.Statement.Category + 19, // 143: query.StreamEvent.Statement.primary_key_fields:type_name -> query.Field + 20, // 144: query.StreamEvent.Statement.primary_key_values:type_name -> query.Row + 145, // [145:145] is the sub-list for method output_type + 145, // [145:145] is the sub-list for method input_type + 145, // [145:145] is the sub-list for extension type_name + 145, // [145:145] is the sub-list for extension extendee + 0, // [0:145] is the sub-list for field type_name } func init() { file_query_proto_init() } @@ -7372,7 +7526,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[39].Exporter = func(v any, i int) any { - switch v := v.(*BeginExecuteRequest); i { + switch v := v.(*UnresolvedTransactionsRequest); i { case 0: return &v.state case 1: @@ -7384,7 +7538,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[40].Exporter = func(v any, i int) any { - switch v := v.(*BeginExecuteResponse); i { + switch v := v.(*UnresolvedTransactionsResponse); i { case 0: return &v.state case 1: @@ -7396,7 +7550,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[41].Exporter = func(v any, i int) any { - switch v := v.(*BeginStreamExecuteRequest); i { + switch v := v.(*BeginExecuteRequest); i { case 0: return &v.state case 1: @@ -7408,7 +7562,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[42].Exporter = func(v any, i int) any { - switch v := v.(*BeginStreamExecuteResponse); i { + switch v := v.(*BeginExecuteResponse); i { case 0: return &v.state case 1: @@ -7420,7 +7574,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[43].Exporter = func(v any, i int) any { - switch v := v.(*MessageStreamRequest); i { + switch v := v.(*BeginStreamExecuteRequest); i { case 0: return &v.state case 1: @@ -7432,7 +7586,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[44].Exporter = func(v any, i int) any { - switch v := v.(*MessageStreamResponse); i { + switch v := v.(*BeginStreamExecuteResponse); i { case 0: return &v.state case 1: @@ -7444,7 +7598,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[45].Exporter = func(v any, i int) any { - switch v := v.(*MessageAckRequest); i { + switch v := v.(*MessageStreamRequest); i { case 0: return &v.state case 1: @@ -7456,7 +7610,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[46].Exporter = func(v any, i int) any { - switch v := v.(*MessageAckResponse); i { + switch v := v.(*MessageStreamResponse); i { case 0: return &v.state case 1: @@ -7468,7 +7622,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[47].Exporter = func(v any, i int) any { - switch v := v.(*ReserveExecuteRequest); i { + switch v := v.(*MessageAckRequest); i { case 0: return &v.state case 1: @@ -7480,7 +7634,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[48].Exporter = func(v any, i int) any { - switch v := v.(*ReserveExecuteResponse); i { + switch v := v.(*MessageAckResponse); i { case 0: return &v.state case 1: @@ -7492,7 +7646,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[49].Exporter = func(v any, i int) any { - switch v := v.(*ReserveStreamExecuteRequest); i { + switch v := v.(*ReserveExecuteRequest); i { case 0: return &v.state case 1: @@ -7504,7 +7658,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[50].Exporter = func(v any, i int) any { - switch v := v.(*ReserveStreamExecuteResponse); i { + switch v := v.(*ReserveExecuteResponse); i { case 0: return &v.state case 1: @@ -7516,7 +7670,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[51].Exporter = func(v any, i int) any { - switch v := v.(*ReserveBeginExecuteRequest); i { + switch v := v.(*ReserveStreamExecuteRequest); i { case 0: return &v.state case 1: @@ -7528,7 +7682,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[52].Exporter = func(v any, i int) any { - switch v := v.(*ReserveBeginExecuteResponse); i { + switch v := v.(*ReserveStreamExecuteResponse); i { case 0: return &v.state case 1: @@ -7540,7 +7694,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[53].Exporter = func(v any, i int) any { - switch v := v.(*ReserveBeginStreamExecuteRequest); i { + switch v := v.(*ReserveBeginExecuteRequest); i { case 0: return &v.state case 1: @@ -7552,7 +7706,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[54].Exporter = func(v any, i int) any { - switch v := v.(*ReserveBeginStreamExecuteResponse); i { + switch v := v.(*ReserveBeginExecuteResponse); i { case 0: return &v.state case 1: @@ -7564,7 +7718,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[55].Exporter = func(v any, i int) any { - switch v := v.(*ReleaseRequest); i { + switch v := v.(*ReserveBeginStreamExecuteRequest); i { case 0: return &v.state case 1: @@ -7576,7 +7730,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[56].Exporter = func(v any, i int) any { - switch v := v.(*ReleaseResponse); i { + switch v := v.(*ReserveBeginStreamExecuteResponse); i { case 0: return &v.state case 1: @@ -7588,7 +7742,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[57].Exporter = func(v any, i int) any { - switch v := v.(*StreamHealthRequest); i { + switch v := v.(*ReleaseRequest); i { case 0: return &v.state case 1: @@ -7600,7 +7754,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[58].Exporter = func(v any, i int) any { - switch v := v.(*RealtimeStats); i { + switch v := v.(*ReleaseResponse); i { case 0: return &v.state case 1: @@ -7612,7 +7766,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[59].Exporter = func(v any, i int) any { - switch v := v.(*AggregateStats); i { + switch v := v.(*StreamHealthRequest); i { case 0: return &v.state case 1: @@ -7624,7 +7778,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[60].Exporter = func(v any, i int) any { - switch v := v.(*StreamHealthResponse); i { + switch v := v.(*RealtimeStats); i { case 0: return &v.state case 1: @@ -7636,7 +7790,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[61].Exporter = func(v any, i int) any { - switch v := v.(*TransactionMetadata); i { + switch v := v.(*AggregateStats); i { case 0: return &v.state case 1: @@ -7648,7 +7802,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[62].Exporter = func(v any, i int) any { - switch v := v.(*GetSchemaRequest); i { + switch v := v.(*StreamHealthResponse); i { case 0: return &v.state case 1: @@ -7660,7 +7814,7 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[63].Exporter = func(v any, i int) any { - switch v := v.(*UDFInfo); i { + switch v := v.(*TransactionMetadata); i { case 0: return &v.state case 1: @@ -7672,7 +7826,19 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[64].Exporter = func(v any, i int) any { - switch v := v.(*GetSchemaResponse); i { + switch v := v.(*GetSchemaRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_query_proto_msgTypes[65].Exporter = func(v any, i int) any { + switch v := v.(*UDFInfo); i { case 0: return &v.state case 1: @@ -7684,6 +7850,18 @@ func file_query_proto_init() { } } file_query_proto_msgTypes[66].Exporter = func(v any, i int) any { + switch v := v.(*GetSchemaResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_query_proto_msgTypes[68].Exporter = func(v any, i int) any { switch v := v.(*StreamEvent_Statement); i { case 0: return &v.state @@ -7702,7 +7880,7 @@ func file_query_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_query_proto_rawDesc, NumEnums: 12, - NumMessages: 68, + NumMessages: 70, NumExtensions: 0, NumServices: 0, }, diff --git a/go/vt/proto/query/query_vtproto.pb.go b/go/vt/proto/query/query_vtproto.pb.go index 636c950642d..c7069cfd6d7 100644 --- a/go/vt/proto/query/query_vtproto.pb.go +++ b/go/vt/proto/query/query_vtproto.pb.go @@ -901,6 +901,49 @@ func (m *ReadTransactionResponse) CloneMessageVT() proto.Message { return m.CloneVT() } +func (m *UnresolvedTransactionsRequest) CloneVT() *UnresolvedTransactionsRequest { + if m == nil { + return (*UnresolvedTransactionsRequest)(nil) + } + r := &UnresolvedTransactionsRequest{ + EffectiveCallerId: m.EffectiveCallerId.CloneVT(), + ImmediateCallerId: m.ImmediateCallerId.CloneVT(), + Target: m.Target.CloneVT(), + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *UnresolvedTransactionsRequest) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *UnresolvedTransactionsResponse) CloneVT() *UnresolvedTransactionsResponse { + if m == nil { + return (*UnresolvedTransactionsResponse)(nil) + } + r := &UnresolvedTransactionsResponse{} + if rhs := m.Transactions; rhs != nil { + tmpContainer := make([]*TransactionMetadata, len(rhs)) + for k, v := range rhs { + tmpContainer[k] = v.CloneVT() + } + r.Transactions = tmpContainer + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *UnresolvedTransactionsResponse) CloneMessageVT() proto.Message { + return m.CloneVT() +} + func (m *BeginExecuteRequest) CloneVT() *BeginExecuteRequest { if m == nil { return (*BeginExecuteRequest)(nil) @@ -1360,6 +1403,7 @@ func (m *RealtimeStats) CloneVT() *RealtimeStats { CpuUsage: m.CpuUsage, Qps: m.Qps, UdfsChanged: m.UdfsChanged, + TxUnresolved: m.TxUnresolved, } if rhs := m.TableSchemaChanged; rhs != nil { tmpContainer := make([]string, len(rhs)) @@ -3929,6 +3973,114 @@ func (m *ReadTransactionResponse) MarshalToSizedBufferVT(dAtA []byte) (int, erro return len(dAtA) - i, nil } +func (m *UnresolvedTransactionsRequest) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *UnresolvedTransactionsRequest) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *UnresolvedTransactionsRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Target != nil { + size, err := m.Target.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x1a + } + if m.ImmediateCallerId != nil { + size, err := m.ImmediateCallerId.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + } + if m.EffectiveCallerId != nil { + size, err := m.EffectiveCallerId.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *UnresolvedTransactionsResponse) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *UnresolvedTransactionsResponse) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *UnresolvedTransactionsResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.Transactions) > 0 { + for iNdEx := len(m.Transactions) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Transactions[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + func (m *BeginExecuteRequest) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil @@ -5372,6 +5524,16 @@ func (m *RealtimeStats) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.TxUnresolved { + i-- + if m.TxUnresolved { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x50 + } if m.UdfsChanged { i-- if m.UdfsChanged { @@ -6752,6 +6914,44 @@ func (m *ReadTransactionResponse) SizeVT() (n int) { return n } +func (m *UnresolvedTransactionsRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.EffectiveCallerId != nil { + l = m.EffectiveCallerId.SizeVT() + n += 1 + l + sov(uint64(l)) + } + if m.ImmediateCallerId != nil { + l = m.ImmediateCallerId.SizeVT() + n += 1 + l + sov(uint64(l)) + } + if m.Target != nil { + l = m.Target.SizeVT() + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *UnresolvedTransactionsResponse) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Transactions) > 0 { + for _, e := range m.Transactions { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } + n += len(m.unknownFields) + return n +} + func (m *BeginExecuteRequest) SizeVT() (n int) { if m == nil { return 0 @@ -7338,6 +7538,9 @@ func (m *RealtimeStats) SizeVT() (n int) { if m.UdfsChanged { n += 2 } + if m.TxUnresolved { + n += 2 + } n += len(m.unknownFields) return n } @@ -13613,6 +13816,250 @@ func (m *ReadTransactionResponse) UnmarshalVT(dAtA []byte) error { } return nil } +func (m *UnresolvedTransactionsRequest) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: UnresolvedTransactionsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: UnresolvedTransactionsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EffectiveCallerId", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.EffectiveCallerId == nil { + m.EffectiveCallerId = &vtrpc.CallerID{} + } + if err := m.EffectiveCallerId.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ImmediateCallerId", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ImmediateCallerId == nil { + m.ImmediateCallerId = &VTGateCallerID{} + } + if err := m.ImmediateCallerId.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Target", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Target == nil { + m.Target = &Target{} + } + if err := m.Target.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *UnresolvedTransactionsResponse) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: UnresolvedTransactionsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: UnresolvedTransactionsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Transactions", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Transactions = append(m.Transactions, &TransactionMetadata{}) + if err := m.Transactions[len(m.Transactions)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *BeginExecuteRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -17678,6 +18125,26 @@ func (m *RealtimeStats) UnmarshalVT(dAtA []byte) error { } } m.UdfsChanged = bool(v != 0) + case 10: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TxUnresolved", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.TxUnresolved = bool(v != 0) default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) diff --git a/go/vt/proto/queryservice/queryservice.pb.go b/go/vt/proto/queryservice/queryservice.pb.go index 34e8003415d..3ef39575e60 100644 --- a/go/vt/proto/queryservice/queryservice.pb.go +++ b/go/vt/proto/queryservice/queryservice.pb.go @@ -45,7 +45,7 @@ var file_queryservice_proto_rawDesc = []byte{ 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x71, 0x75, 0x65, 0x72, 0x79, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x1a, 0x0b, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x10, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x32, 0xac, 0x11, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x3a, 0x0a, 0x07, 0x45, + 0x6f, 0x32, 0x95, 0x12, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x3a, 0x0a, 0x07, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x15, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, @@ -105,89 +105,95 @@ var file_queryservice_proto_rawDesc = []byte{ 0x65, 0x61, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x49, 0x0a, 0x0c, 0x42, 0x65, 0x67, 0x69, 0x6e, - 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x1a, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, - 0x42, 0x65, 0x67, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x42, 0x65, 0x67, 0x69, - 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x5d, 0x0a, 0x12, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x20, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, - 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x71, 0x75, 0x65, - 0x72, 0x79, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, - 0x01, 0x12, 0x4e, 0x0a, 0x0d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x74, 0x72, 0x65, - 0x61, 0x6d, 0x12, 0x1b, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1c, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, - 0x01, 0x12, 0x43, 0x0a, 0x0a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x41, 0x63, 0x6b, 0x12, - 0x18, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x41, - 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x71, 0x75, 0x65, 0x72, - 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x41, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4f, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x1c, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, - 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x52, - 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5e, 0x0a, 0x13, 0x52, 0x65, 0x73, 0x65, 0x72, - 0x76, 0x65, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x21, - 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x42, 0x65, - 0x67, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x22, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x63, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x65, 0x72, - 0x76, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, - 0x22, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x53, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x67, 0x0a, 0x16, 0x55, 0x6e, 0x72, 0x65, 0x73, + 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x24, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x55, 0x6e, 0x72, 0x65, 0x73, 0x6f, + 0x6c, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, + 0x55, 0x6e, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x12, 0x49, 0x0a, 0x0c, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, + 0x12, 0x1a, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x45, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x71, + 0x75, 0x65, 0x72, 0x79, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5d, 0x0a, 0x12, 0x42, + 0x65, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x65, 0x12, 0x20, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x72, 0x0a, 0x19, - 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x65, - 0x61, 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x27, 0x2e, 0x71, 0x75, 0x65, 0x72, - 0x79, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x53, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, + 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x42, 0x65, 0x67, 0x69, + 0x6e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x4e, 0x0a, 0x0d, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1b, 0x2e, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x43, 0x0a, 0x0a, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x41, 0x63, 0x6b, 0x12, 0x18, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x41, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x41, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x4f, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x65, 0x12, 0x1c, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1d, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x45, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x12, 0x5e, 0x0a, 0x13, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x42, 0x65, 0x67, 0x69, 0x6e, + 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x21, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, + 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x71, 0x75, 0x65, + 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x45, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x12, 0x63, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x22, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x71, + 0x75, 0x65, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x53, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x72, 0x0a, 0x19, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x42, 0x65, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x65, 0x12, 0x27, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, - 0x12, 0x3a, 0x0a, 0x07, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x15, 0x2e, 0x71, 0x75, - 0x65, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, - 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0c, - 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x1a, 0x2e, 0x71, - 0x75, 0x65, 0x72, 0x79, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, - 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x46, 0x0a, 0x07, 0x56, 0x53, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1a, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1b, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, - 0x01, 0x12, 0x52, 0x0a, 0x0b, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x6f, 0x77, 0x73, - 0x12, 0x1e, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1f, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x58, 0x0a, 0x0d, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x61, 0x62, 0x6c, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, - 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x61, 0x62, - 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, - 0x5b, 0x0a, 0x0e, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x73, 0x12, 0x21, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, - 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x09, - 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x17, 0x2e, 0x71, 0x75, 0x65, 0x72, - 0x79, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x63, - 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, - 0x42, 0x2b, 0x5a, 0x29, 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, 0x71, 0x75, 0x65, 0x72, 0x79, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x42, 0x65, 0x67, 0x69, 0x6e, + 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x3a, 0x0a, 0x07, 0x52, 0x65, 0x6c, + 0x65, 0x61, 0x73, 0x65, 0x12, 0x15, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x6c, + 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x48, + 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x1a, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1b, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x30, 0x01, 0x12, 0x46, 0x0a, 0x07, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1a, 0x2e, + 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x53, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x62, 0x69, 0x6e, 0x6c, + 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x52, 0x0a, 0x0b, 0x56, 0x53, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x6f, 0x77, 0x73, 0x12, 0x1e, 0x2e, 0x62, 0x69, 0x6e, 0x6c, + 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x6f, + 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x62, 0x69, 0x6e, 0x6c, + 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x6f, + 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x58, + 0x0a, 0x0d, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, + 0x20, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x21, 0x2e, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, + 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x5b, 0x0a, 0x0e, 0x56, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x21, 0x2e, 0x62, 0x69, 0x6e, + 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, + 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x53, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x12, 0x17, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x42, 0x2b, 0x5a, 0x29, 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, 0x71, 0x75, 0x65, 0x72, 0x79, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var file_queryservice_proto_goTypes = []any{ @@ -204,49 +210,51 @@ var file_queryservice_proto_goTypes = []any{ (*query.SetRollbackRequest)(nil), // 10: query.SetRollbackRequest (*query.ConcludeTransactionRequest)(nil), // 11: query.ConcludeTransactionRequest (*query.ReadTransactionRequest)(nil), // 12: query.ReadTransactionRequest - (*query.BeginExecuteRequest)(nil), // 13: query.BeginExecuteRequest - (*query.BeginStreamExecuteRequest)(nil), // 14: query.BeginStreamExecuteRequest - (*query.MessageStreamRequest)(nil), // 15: query.MessageStreamRequest - (*query.MessageAckRequest)(nil), // 16: query.MessageAckRequest - (*query.ReserveExecuteRequest)(nil), // 17: query.ReserveExecuteRequest - (*query.ReserveBeginExecuteRequest)(nil), // 18: query.ReserveBeginExecuteRequest - (*query.ReserveStreamExecuteRequest)(nil), // 19: query.ReserveStreamExecuteRequest - (*query.ReserveBeginStreamExecuteRequest)(nil), // 20: query.ReserveBeginStreamExecuteRequest - (*query.ReleaseRequest)(nil), // 21: query.ReleaseRequest - (*query.StreamHealthRequest)(nil), // 22: query.StreamHealthRequest - (*binlogdata.VStreamRequest)(nil), // 23: binlogdata.VStreamRequest - (*binlogdata.VStreamRowsRequest)(nil), // 24: binlogdata.VStreamRowsRequest - (*binlogdata.VStreamTablesRequest)(nil), // 25: binlogdata.VStreamTablesRequest - (*binlogdata.VStreamResultsRequest)(nil), // 26: binlogdata.VStreamResultsRequest - (*query.GetSchemaRequest)(nil), // 27: query.GetSchemaRequest - (*query.ExecuteResponse)(nil), // 28: query.ExecuteResponse - (*query.StreamExecuteResponse)(nil), // 29: query.StreamExecuteResponse - (*query.BeginResponse)(nil), // 30: query.BeginResponse - (*query.CommitResponse)(nil), // 31: query.CommitResponse - (*query.RollbackResponse)(nil), // 32: query.RollbackResponse - (*query.PrepareResponse)(nil), // 33: query.PrepareResponse - (*query.CommitPreparedResponse)(nil), // 34: query.CommitPreparedResponse - (*query.RollbackPreparedResponse)(nil), // 35: query.RollbackPreparedResponse - (*query.CreateTransactionResponse)(nil), // 36: query.CreateTransactionResponse - (*query.StartCommitResponse)(nil), // 37: query.StartCommitResponse - (*query.SetRollbackResponse)(nil), // 38: query.SetRollbackResponse - (*query.ConcludeTransactionResponse)(nil), // 39: query.ConcludeTransactionResponse - (*query.ReadTransactionResponse)(nil), // 40: query.ReadTransactionResponse - (*query.BeginExecuteResponse)(nil), // 41: query.BeginExecuteResponse - (*query.BeginStreamExecuteResponse)(nil), // 42: query.BeginStreamExecuteResponse - (*query.MessageStreamResponse)(nil), // 43: query.MessageStreamResponse - (*query.MessageAckResponse)(nil), // 44: query.MessageAckResponse - (*query.ReserveExecuteResponse)(nil), // 45: query.ReserveExecuteResponse - (*query.ReserveBeginExecuteResponse)(nil), // 46: query.ReserveBeginExecuteResponse - (*query.ReserveStreamExecuteResponse)(nil), // 47: query.ReserveStreamExecuteResponse - (*query.ReserveBeginStreamExecuteResponse)(nil), // 48: query.ReserveBeginStreamExecuteResponse - (*query.ReleaseResponse)(nil), // 49: query.ReleaseResponse - (*query.StreamHealthResponse)(nil), // 50: query.StreamHealthResponse - (*binlogdata.VStreamResponse)(nil), // 51: binlogdata.VStreamResponse - (*binlogdata.VStreamRowsResponse)(nil), // 52: binlogdata.VStreamRowsResponse - (*binlogdata.VStreamTablesResponse)(nil), // 53: binlogdata.VStreamTablesResponse - (*binlogdata.VStreamResultsResponse)(nil), // 54: binlogdata.VStreamResultsResponse - (*query.GetSchemaResponse)(nil), // 55: query.GetSchemaResponse + (*query.UnresolvedTransactionsRequest)(nil), // 13: query.UnresolvedTransactionsRequest + (*query.BeginExecuteRequest)(nil), // 14: query.BeginExecuteRequest + (*query.BeginStreamExecuteRequest)(nil), // 15: query.BeginStreamExecuteRequest + (*query.MessageStreamRequest)(nil), // 16: query.MessageStreamRequest + (*query.MessageAckRequest)(nil), // 17: query.MessageAckRequest + (*query.ReserveExecuteRequest)(nil), // 18: query.ReserveExecuteRequest + (*query.ReserveBeginExecuteRequest)(nil), // 19: query.ReserveBeginExecuteRequest + (*query.ReserveStreamExecuteRequest)(nil), // 20: query.ReserveStreamExecuteRequest + (*query.ReserveBeginStreamExecuteRequest)(nil), // 21: query.ReserveBeginStreamExecuteRequest + (*query.ReleaseRequest)(nil), // 22: query.ReleaseRequest + (*query.StreamHealthRequest)(nil), // 23: query.StreamHealthRequest + (*binlogdata.VStreamRequest)(nil), // 24: binlogdata.VStreamRequest + (*binlogdata.VStreamRowsRequest)(nil), // 25: binlogdata.VStreamRowsRequest + (*binlogdata.VStreamTablesRequest)(nil), // 26: binlogdata.VStreamTablesRequest + (*binlogdata.VStreamResultsRequest)(nil), // 27: binlogdata.VStreamResultsRequest + (*query.GetSchemaRequest)(nil), // 28: query.GetSchemaRequest + (*query.ExecuteResponse)(nil), // 29: query.ExecuteResponse + (*query.StreamExecuteResponse)(nil), // 30: query.StreamExecuteResponse + (*query.BeginResponse)(nil), // 31: query.BeginResponse + (*query.CommitResponse)(nil), // 32: query.CommitResponse + (*query.RollbackResponse)(nil), // 33: query.RollbackResponse + (*query.PrepareResponse)(nil), // 34: query.PrepareResponse + (*query.CommitPreparedResponse)(nil), // 35: query.CommitPreparedResponse + (*query.RollbackPreparedResponse)(nil), // 36: query.RollbackPreparedResponse + (*query.CreateTransactionResponse)(nil), // 37: query.CreateTransactionResponse + (*query.StartCommitResponse)(nil), // 38: query.StartCommitResponse + (*query.SetRollbackResponse)(nil), // 39: query.SetRollbackResponse + (*query.ConcludeTransactionResponse)(nil), // 40: query.ConcludeTransactionResponse + (*query.ReadTransactionResponse)(nil), // 41: query.ReadTransactionResponse + (*query.UnresolvedTransactionsResponse)(nil), // 42: query.UnresolvedTransactionsResponse + (*query.BeginExecuteResponse)(nil), // 43: query.BeginExecuteResponse + (*query.BeginStreamExecuteResponse)(nil), // 44: query.BeginStreamExecuteResponse + (*query.MessageStreamResponse)(nil), // 45: query.MessageStreamResponse + (*query.MessageAckResponse)(nil), // 46: query.MessageAckResponse + (*query.ReserveExecuteResponse)(nil), // 47: query.ReserveExecuteResponse + (*query.ReserveBeginExecuteResponse)(nil), // 48: query.ReserveBeginExecuteResponse + (*query.ReserveStreamExecuteResponse)(nil), // 49: query.ReserveStreamExecuteResponse + (*query.ReserveBeginStreamExecuteResponse)(nil), // 50: query.ReserveBeginStreamExecuteResponse + (*query.ReleaseResponse)(nil), // 51: query.ReleaseResponse + (*query.StreamHealthResponse)(nil), // 52: query.StreamHealthResponse + (*binlogdata.VStreamResponse)(nil), // 53: binlogdata.VStreamResponse + (*binlogdata.VStreamRowsResponse)(nil), // 54: binlogdata.VStreamRowsResponse + (*binlogdata.VStreamTablesResponse)(nil), // 55: binlogdata.VStreamTablesResponse + (*binlogdata.VStreamResultsResponse)(nil), // 56: binlogdata.VStreamResultsResponse + (*query.GetSchemaResponse)(nil), // 57: query.GetSchemaResponse } var file_queryservice_proto_depIdxs = []int32{ 0, // 0: queryservice.Query.Execute:input_type -> query.ExecuteRequest @@ -262,51 +270,53 @@ var file_queryservice_proto_depIdxs = []int32{ 10, // 10: queryservice.Query.SetRollback:input_type -> query.SetRollbackRequest 11, // 11: queryservice.Query.ConcludeTransaction:input_type -> query.ConcludeTransactionRequest 12, // 12: queryservice.Query.ReadTransaction:input_type -> query.ReadTransactionRequest - 13, // 13: queryservice.Query.BeginExecute:input_type -> query.BeginExecuteRequest - 14, // 14: queryservice.Query.BeginStreamExecute:input_type -> query.BeginStreamExecuteRequest - 15, // 15: queryservice.Query.MessageStream:input_type -> query.MessageStreamRequest - 16, // 16: queryservice.Query.MessageAck:input_type -> query.MessageAckRequest - 17, // 17: queryservice.Query.ReserveExecute:input_type -> query.ReserveExecuteRequest - 18, // 18: queryservice.Query.ReserveBeginExecute:input_type -> query.ReserveBeginExecuteRequest - 19, // 19: queryservice.Query.ReserveStreamExecute:input_type -> query.ReserveStreamExecuteRequest - 20, // 20: queryservice.Query.ReserveBeginStreamExecute:input_type -> query.ReserveBeginStreamExecuteRequest - 21, // 21: queryservice.Query.Release:input_type -> query.ReleaseRequest - 22, // 22: queryservice.Query.StreamHealth:input_type -> query.StreamHealthRequest - 23, // 23: queryservice.Query.VStream:input_type -> binlogdata.VStreamRequest - 24, // 24: queryservice.Query.VStreamRows:input_type -> binlogdata.VStreamRowsRequest - 25, // 25: queryservice.Query.VStreamTables:input_type -> binlogdata.VStreamTablesRequest - 26, // 26: queryservice.Query.VStreamResults:input_type -> binlogdata.VStreamResultsRequest - 27, // 27: queryservice.Query.GetSchema:input_type -> query.GetSchemaRequest - 28, // 28: queryservice.Query.Execute:output_type -> query.ExecuteResponse - 29, // 29: queryservice.Query.StreamExecute:output_type -> query.StreamExecuteResponse - 30, // 30: queryservice.Query.Begin:output_type -> query.BeginResponse - 31, // 31: queryservice.Query.Commit:output_type -> query.CommitResponse - 32, // 32: queryservice.Query.Rollback:output_type -> query.RollbackResponse - 33, // 33: queryservice.Query.Prepare:output_type -> query.PrepareResponse - 34, // 34: queryservice.Query.CommitPrepared:output_type -> query.CommitPreparedResponse - 35, // 35: queryservice.Query.RollbackPrepared:output_type -> query.RollbackPreparedResponse - 36, // 36: queryservice.Query.CreateTransaction:output_type -> query.CreateTransactionResponse - 37, // 37: queryservice.Query.StartCommit:output_type -> query.StartCommitResponse - 38, // 38: queryservice.Query.SetRollback:output_type -> query.SetRollbackResponse - 39, // 39: queryservice.Query.ConcludeTransaction:output_type -> query.ConcludeTransactionResponse - 40, // 40: queryservice.Query.ReadTransaction:output_type -> query.ReadTransactionResponse - 41, // 41: queryservice.Query.BeginExecute:output_type -> query.BeginExecuteResponse - 42, // 42: queryservice.Query.BeginStreamExecute:output_type -> query.BeginStreamExecuteResponse - 43, // 43: queryservice.Query.MessageStream:output_type -> query.MessageStreamResponse - 44, // 44: queryservice.Query.MessageAck:output_type -> query.MessageAckResponse - 45, // 45: queryservice.Query.ReserveExecute:output_type -> query.ReserveExecuteResponse - 46, // 46: queryservice.Query.ReserveBeginExecute:output_type -> query.ReserveBeginExecuteResponse - 47, // 47: queryservice.Query.ReserveStreamExecute:output_type -> query.ReserveStreamExecuteResponse - 48, // 48: queryservice.Query.ReserveBeginStreamExecute:output_type -> query.ReserveBeginStreamExecuteResponse - 49, // 49: queryservice.Query.Release:output_type -> query.ReleaseResponse - 50, // 50: queryservice.Query.StreamHealth:output_type -> query.StreamHealthResponse - 51, // 51: queryservice.Query.VStream:output_type -> binlogdata.VStreamResponse - 52, // 52: queryservice.Query.VStreamRows:output_type -> binlogdata.VStreamRowsResponse - 53, // 53: queryservice.Query.VStreamTables:output_type -> binlogdata.VStreamTablesResponse - 54, // 54: queryservice.Query.VStreamResults:output_type -> binlogdata.VStreamResultsResponse - 55, // 55: queryservice.Query.GetSchema:output_type -> query.GetSchemaResponse - 28, // [28:56] is the sub-list for method output_type - 0, // [0:28] is the sub-list for method input_type + 13, // 13: queryservice.Query.UnresolvedTransactions:input_type -> query.UnresolvedTransactionsRequest + 14, // 14: queryservice.Query.BeginExecute:input_type -> query.BeginExecuteRequest + 15, // 15: queryservice.Query.BeginStreamExecute:input_type -> query.BeginStreamExecuteRequest + 16, // 16: queryservice.Query.MessageStream:input_type -> query.MessageStreamRequest + 17, // 17: queryservice.Query.MessageAck:input_type -> query.MessageAckRequest + 18, // 18: queryservice.Query.ReserveExecute:input_type -> query.ReserveExecuteRequest + 19, // 19: queryservice.Query.ReserveBeginExecute:input_type -> query.ReserveBeginExecuteRequest + 20, // 20: queryservice.Query.ReserveStreamExecute:input_type -> query.ReserveStreamExecuteRequest + 21, // 21: queryservice.Query.ReserveBeginStreamExecute:input_type -> query.ReserveBeginStreamExecuteRequest + 22, // 22: queryservice.Query.Release:input_type -> query.ReleaseRequest + 23, // 23: queryservice.Query.StreamHealth:input_type -> query.StreamHealthRequest + 24, // 24: queryservice.Query.VStream:input_type -> binlogdata.VStreamRequest + 25, // 25: queryservice.Query.VStreamRows:input_type -> binlogdata.VStreamRowsRequest + 26, // 26: queryservice.Query.VStreamTables:input_type -> binlogdata.VStreamTablesRequest + 27, // 27: queryservice.Query.VStreamResults:input_type -> binlogdata.VStreamResultsRequest + 28, // 28: queryservice.Query.GetSchema:input_type -> query.GetSchemaRequest + 29, // 29: queryservice.Query.Execute:output_type -> query.ExecuteResponse + 30, // 30: queryservice.Query.StreamExecute:output_type -> query.StreamExecuteResponse + 31, // 31: queryservice.Query.Begin:output_type -> query.BeginResponse + 32, // 32: queryservice.Query.Commit:output_type -> query.CommitResponse + 33, // 33: queryservice.Query.Rollback:output_type -> query.RollbackResponse + 34, // 34: queryservice.Query.Prepare:output_type -> query.PrepareResponse + 35, // 35: queryservice.Query.CommitPrepared:output_type -> query.CommitPreparedResponse + 36, // 36: queryservice.Query.RollbackPrepared:output_type -> query.RollbackPreparedResponse + 37, // 37: queryservice.Query.CreateTransaction:output_type -> query.CreateTransactionResponse + 38, // 38: queryservice.Query.StartCommit:output_type -> query.StartCommitResponse + 39, // 39: queryservice.Query.SetRollback:output_type -> query.SetRollbackResponse + 40, // 40: queryservice.Query.ConcludeTransaction:output_type -> query.ConcludeTransactionResponse + 41, // 41: queryservice.Query.ReadTransaction:output_type -> query.ReadTransactionResponse + 42, // 42: queryservice.Query.UnresolvedTransactions:output_type -> query.UnresolvedTransactionsResponse + 43, // 43: queryservice.Query.BeginExecute:output_type -> query.BeginExecuteResponse + 44, // 44: queryservice.Query.BeginStreamExecute:output_type -> query.BeginStreamExecuteResponse + 45, // 45: queryservice.Query.MessageStream:output_type -> query.MessageStreamResponse + 46, // 46: queryservice.Query.MessageAck:output_type -> query.MessageAckResponse + 47, // 47: queryservice.Query.ReserveExecute:output_type -> query.ReserveExecuteResponse + 48, // 48: queryservice.Query.ReserveBeginExecute:output_type -> query.ReserveBeginExecuteResponse + 49, // 49: queryservice.Query.ReserveStreamExecute:output_type -> query.ReserveStreamExecuteResponse + 50, // 50: queryservice.Query.ReserveBeginStreamExecute:output_type -> query.ReserveBeginStreamExecuteResponse + 51, // 51: queryservice.Query.Release:output_type -> query.ReleaseResponse + 52, // 52: queryservice.Query.StreamHealth:output_type -> query.StreamHealthResponse + 53, // 53: queryservice.Query.VStream:output_type -> binlogdata.VStreamResponse + 54, // 54: queryservice.Query.VStreamRows:output_type -> binlogdata.VStreamRowsResponse + 55, // 55: queryservice.Query.VStreamTables:output_type -> binlogdata.VStreamTablesResponse + 56, // 56: queryservice.Query.VStreamResults:output_type -> binlogdata.VStreamResultsResponse + 57, // 57: queryservice.Query.GetSchema:output_type -> query.GetSchemaResponse + 29, // [29:58] is the sub-list for method output_type + 0, // [0:29] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name diff --git a/go/vt/proto/queryservice/queryservice_grpc.pb.go b/go/vt/proto/queryservice/queryservice_grpc.pb.go index c05ea4f83a3..ebf52ce4dcf 100644 --- a/go/vt/proto/queryservice/queryservice_grpc.pb.go +++ b/go/vt/proto/queryservice/queryservice_grpc.pb.go @@ -54,6 +54,8 @@ type QueryClient interface { ConcludeTransaction(ctx context.Context, in *query.ConcludeTransactionRequest, opts ...grpc.CallOption) (*query.ConcludeTransactionResponse, error) // ReadTransaction returns the 2pc transaction info. ReadTransaction(ctx context.Context, in *query.ReadTransactionRequest, opts ...grpc.CallOption) (*query.ReadTransactionResponse, error) + // UnresolvedTransactions returns the 2pc transaction info. + UnresolvedTransactions(ctx context.Context, in *query.UnresolvedTransactionsRequest, opts ...grpc.CallOption) (*query.UnresolvedTransactionsResponse, error) // BeginExecute executes a begin and the specified SQL query. BeginExecute(ctx context.Context, in *query.BeginExecuteRequest, opts ...grpc.CallOption) (*query.BeginExecuteResponse, error) // BeginStreamExecute executes a begin and the specified SQL query. @@ -235,6 +237,15 @@ func (c *queryClient) ReadTransaction(ctx context.Context, in *query.ReadTransac return out, nil } +func (c *queryClient) UnresolvedTransactions(ctx context.Context, in *query.UnresolvedTransactionsRequest, opts ...grpc.CallOption) (*query.UnresolvedTransactionsResponse, error) { + out := new(query.UnresolvedTransactionsResponse) + err := c.cc.Invoke(ctx, "/queryservice.Query/UnresolvedTransactions", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *queryClient) BeginExecute(ctx context.Context, in *query.BeginExecuteRequest, opts ...grpc.CallOption) (*query.BeginExecuteResponse, error) { out := new(query.BeginExecuteResponse) err := c.cc.Invoke(ctx, "/queryservice.Query/BeginExecute", in, out, opts...) @@ -634,6 +645,8 @@ type QueryServer interface { ConcludeTransaction(context.Context, *query.ConcludeTransactionRequest) (*query.ConcludeTransactionResponse, error) // ReadTransaction returns the 2pc transaction info. ReadTransaction(context.Context, *query.ReadTransactionRequest) (*query.ReadTransactionResponse, error) + // UnresolvedTransactions returns the 2pc transaction info. + UnresolvedTransactions(context.Context, *query.UnresolvedTransactionsRequest) (*query.UnresolvedTransactionsResponse, error) // BeginExecute executes a begin and the specified SQL query. BeginExecute(context.Context, *query.BeginExecuteRequest) (*query.BeginExecuteResponse, error) // BeginStreamExecute executes a begin and the specified SQL query. @@ -711,6 +724,9 @@ func (UnimplementedQueryServer) ConcludeTransaction(context.Context, *query.Conc func (UnimplementedQueryServer) ReadTransaction(context.Context, *query.ReadTransactionRequest) (*query.ReadTransactionResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ReadTransaction not implemented") } +func (UnimplementedQueryServer) UnresolvedTransactions(context.Context, *query.UnresolvedTransactionsRequest) (*query.UnresolvedTransactionsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UnresolvedTransactions not implemented") +} func (UnimplementedQueryServer) BeginExecute(context.Context, *query.BeginExecuteRequest) (*query.BeginExecuteResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method BeginExecute not implemented") } @@ -1006,6 +1022,24 @@ func _Query_ReadTransaction_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } +func _Query_UnresolvedTransactions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(query.UnresolvedTransactionsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).UnresolvedTransactions(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/queryservice.Query/UnresolvedTransactions", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).UnresolvedTransactions(ctx, req.(*query.UnresolvedTransactionsRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Query_BeginExecute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(query.BeginExecuteRequest) if err := dec(in); err != nil { @@ -1361,6 +1395,10 @@ var Query_ServiceDesc = grpc.ServiceDesc{ MethodName: "ReadTransaction", Handler: _Query_ReadTransaction_Handler, }, + { + MethodName: "UnresolvedTransactions", + Handler: _Query_UnresolvedTransactions_Handler, + }, { MethodName: "BeginExecute", Handler: _Query_BeginExecute_Handler, diff --git a/go/vt/proto/vschema/vschema.pb.go b/go/vt/proto/vschema/vschema.pb.go index 5cb14d3a522..131622aaf5b 100644 --- a/go/vt/proto/vschema/vschema.pb.go +++ b/go/vt/proto/vschema/vschema.pb.go @@ -784,6 +784,7 @@ type SrvVSchema struct { RoutingRules *RoutingRules `protobuf:"bytes,2,opt,name=routing_rules,json=routingRules,proto3" json:"routing_rules,omitempty"` // table routing rules ShardRoutingRules *ShardRoutingRules `protobuf:"bytes,3,opt,name=shard_routing_rules,json=shardRoutingRules,proto3" json:"shard_routing_rules,omitempty"` KeyspaceRoutingRules *KeyspaceRoutingRules `protobuf:"bytes,4,opt,name=keyspace_routing_rules,json=keyspaceRoutingRules,proto3" json:"keyspace_routing_rules,omitempty"` + MirrorRules *MirrorRules `protobuf:"bytes,5,opt,name=mirror_rules,json=mirrorRules,proto3" json:"mirror_rules,omitempty"` // mirror rules } func (x *SrvVSchema) Reset() { @@ -846,6 +847,13 @@ func (x *SrvVSchema) GetKeyspaceRoutingRules() *KeyspaceRoutingRules { return nil } +func (x *SrvVSchema) GetMirrorRules() *MirrorRules { + if x != nil { + return x.MirrorRules + } + return nil +} + // ShardRoutingRules specify the shard routing rules for the VSchema. type ShardRoutingRules struct { state protoimpl.MessageState @@ -1060,6 +1068,121 @@ func (x *KeyspaceRoutingRule) GetToKeyspace() string { return "" } +// MirrorRules specify the high level mirror rules for the VSchema. +type MirrorRules struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // rules should ideally be a map. However protos dont't allow + // repeated fields as elements of a map. So, we use a list + // instead. + Rules []*MirrorRule `protobuf:"bytes,1,rep,name=rules,proto3" json:"rules,omitempty"` +} + +func (x *MirrorRules) Reset() { + *x = MirrorRules{} + if protoimpl.UnsafeEnabled { + mi := &file_vschema_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MirrorRules) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MirrorRules) ProtoMessage() {} + +func (x *MirrorRules) ProtoReflect() protoreflect.Message { + mi := &file_vschema_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MirrorRules.ProtoReflect.Descriptor instead. +func (*MirrorRules) Descriptor() ([]byte, []int) { + return file_vschema_proto_rawDescGZIP(), []int{14} +} + +func (x *MirrorRules) GetRules() []*MirrorRule { + if x != nil { + return x.Rules + } + return nil +} + +// MirrorRule specifies a mirror rule. +type MirrorRule struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + FromTable string `protobuf:"bytes,1,opt,name=from_table,json=fromTable,proto3" json:"from_table,omitempty"` + ToTable string `protobuf:"bytes,2,opt,name=to_table,json=toTable,proto3" json:"to_table,omitempty"` + Percent float32 `protobuf:"fixed32,3,opt,name=percent,proto3" json:"percent,omitempty"` +} + +func (x *MirrorRule) Reset() { + *x = MirrorRule{} + if protoimpl.UnsafeEnabled { + mi := &file_vschema_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MirrorRule) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MirrorRule) ProtoMessage() {} + +func (x *MirrorRule) ProtoReflect() protoreflect.Message { + mi := &file_vschema_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MirrorRule.ProtoReflect.Descriptor instead. +func (*MirrorRule) Descriptor() ([]byte, []int) { + return file_vschema_proto_rawDescGZIP(), []int{15} +} + +func (x *MirrorRule) GetFromTable() string { + if x != nil { + return x.FromTable + } + return "" +} + +func (x *MirrorRule) GetToTable() string { + if x != nil { + return x.ToTable + } + return "" +} + +func (x *MirrorRule) GetPercent() float32 { + if x != nil { + return x.Percent + } + return 0 +} + var File_vschema_proto protoreflect.FileDescriptor var file_vschema_proto_rawDesc = []byte{ @@ -1175,7 +1298,7 @@ var file_vschema_proto_rawDesc = []byte{ 0x00, 0x52, 0x08, 0x6e, 0x75, 0x6c, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x88, 0x01, 0x01, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6e, 0x75, 0x6c, 0x6c, 0x61, - 0x62, 0x6c, 0x65, 0x22, 0xfc, 0x02, 0x0a, 0x0a, 0x53, 0x72, 0x76, 0x56, 0x53, 0x63, 0x68, 0x65, + 0x62, 0x6c, 0x65, 0x22, 0xb5, 0x03, 0x0a, 0x0a, 0x53, 0x72, 0x76, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x40, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x76, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x53, 0x72, 0x76, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, @@ -1194,37 +1317,50 @@ var file_vschema_proto_rawDesc = []byte{ 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x14, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, - 0x73, 0x1a, 0x4f, 0x0a, 0x0e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 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, 0x27, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x76, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x4b, - 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x22, 0x44, 0x0a, 0x11, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x69, - 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x2f, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x76, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, - 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, - 0x65, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x6e, 0x0a, 0x10, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x23, 0x0a, 0x0d, - 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x72, 0x6f, 0x6d, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x6f, 0x4b, 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, 0x22, 0x4a, 0x0a, 0x14, 0x4b, 0x65, 0x79, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, - 0x12, 0x32, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x76, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, - 0x75, 0x6c, 0x65, 0x73, 0x22, 0x5b, 0x0a, 0x13, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x66, - 0x72, 0x6f, 0x6d, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0c, 0x66, 0x72, 0x6f, 0x6d, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x6f, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x42, 0x26, 0x5a, 0x24, 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, 0x76, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x73, 0x12, 0x37, 0x0a, 0x0c, 0x6d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x72, 0x75, 0x6c, 0x65, + 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x73, 0x63, 0x68, 0x65, 0x6d, + 0x61, 0x2e, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x0b, 0x6d, + 0x69, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x1a, 0x4f, 0x0a, 0x0e, 0x4b, 0x65, + 0x79, 0x73, 0x70, 0x61, 0x63, 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, 0x27, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, + 0x76, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x44, 0x0a, 0x11, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, + 0x12, 0x2f, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x76, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, + 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, + 0x73, 0x22, 0x6e, 0x0a, 0x10, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, + 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x6b, 0x65, + 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x72, + 0x6f, 0x6d, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, + 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x74, 0x6f, 0x4b, 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, 0x22, 0x4a, 0x0a, 0x14, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x6f, 0x75, + 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x32, 0x0a, 0x05, 0x72, 0x75, 0x6c, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x76, 0x73, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, + 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x5b, 0x0a, + 0x13, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, + 0x52, 0x75, 0x6c, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x6b, 0x65, 0x79, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x72, 0x6f, + 0x6d, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x5f, + 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x74, 0x6f, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x38, 0x0a, 0x0b, 0x4d, 0x69, + 0x72, 0x72, 0x6f, 0x72, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x29, 0x0a, 0x05, 0x72, 0x75, 0x6c, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x76, 0x73, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x2e, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, + 0x75, 0x6c, 0x65, 0x73, 0x22, 0x60, 0x0a, 0x0a, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x75, + 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x72, 0x6f, 0x6d, 0x54, 0x61, 0x62, 0x6c, + 0x65, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x6f, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x6f, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, + 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x07, 0x70, + 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x42, 0x26, 0x5a, 0x24, 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, 0x76, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1240,7 +1376,7 @@ func file_vschema_proto_rawDescGZIP() []byte { } var file_vschema_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_vschema_proto_msgTypes = make([]protoimpl.MessageInfo, 18) +var file_vschema_proto_msgTypes = make([]protoimpl.MessageInfo, 20) var file_vschema_proto_goTypes = []any{ (Keyspace_ForeignKeyMode)(0), // 0: vschema.Keyspace.ForeignKeyMode (*RoutingRules)(nil), // 1: vschema.RoutingRules @@ -1257,38 +1393,42 @@ var file_vschema_proto_goTypes = []any{ (*ShardRoutingRule)(nil), // 12: vschema.ShardRoutingRule (*KeyspaceRoutingRules)(nil), // 13: vschema.KeyspaceRoutingRules (*KeyspaceRoutingRule)(nil), // 14: vschema.KeyspaceRoutingRule - nil, // 15: vschema.Keyspace.VindexesEntry - nil, // 16: vschema.Keyspace.TablesEntry - nil, // 17: vschema.Vindex.ParamsEntry - nil, // 18: vschema.SrvVSchema.KeyspacesEntry - (query.Type)(0), // 19: query.Type + (*MirrorRules)(nil), // 15: vschema.MirrorRules + (*MirrorRule)(nil), // 16: vschema.MirrorRule + nil, // 17: vschema.Keyspace.VindexesEntry + nil, // 18: vschema.Keyspace.TablesEntry + nil, // 19: vschema.Vindex.ParamsEntry + nil, // 20: vschema.SrvVSchema.KeyspacesEntry + (query.Type)(0), // 21: query.Type } var file_vschema_proto_depIdxs = []int32{ 2, // 0: vschema.RoutingRules.rules:type_name -> vschema.RoutingRule - 15, // 1: vschema.Keyspace.vindexes:type_name -> vschema.Keyspace.VindexesEntry - 16, // 2: vschema.Keyspace.tables:type_name -> vschema.Keyspace.TablesEntry + 17, // 1: vschema.Keyspace.vindexes:type_name -> vschema.Keyspace.VindexesEntry + 18, // 2: vschema.Keyspace.tables:type_name -> vschema.Keyspace.TablesEntry 0, // 3: vschema.Keyspace.foreign_key_mode:type_name -> vschema.Keyspace.ForeignKeyMode 4, // 4: vschema.Keyspace.multi_tenant_spec:type_name -> vschema.MultiTenantSpec - 19, // 5: vschema.MultiTenantSpec.tenant_id_column_type:type_name -> query.Type - 17, // 6: vschema.Vindex.params:type_name -> vschema.Vindex.ParamsEntry + 21, // 5: vschema.MultiTenantSpec.tenant_id_column_type:type_name -> query.Type + 19, // 6: vschema.Vindex.params:type_name -> vschema.Vindex.ParamsEntry 7, // 7: vschema.Table.column_vindexes:type_name -> vschema.ColumnVindex 8, // 8: vschema.Table.auto_increment:type_name -> vschema.AutoIncrement 9, // 9: vschema.Table.columns:type_name -> vschema.Column - 19, // 10: vschema.Column.type:type_name -> query.Type - 18, // 11: vschema.SrvVSchema.keyspaces:type_name -> vschema.SrvVSchema.KeyspacesEntry + 21, // 10: vschema.Column.type:type_name -> query.Type + 20, // 11: vschema.SrvVSchema.keyspaces:type_name -> vschema.SrvVSchema.KeyspacesEntry 1, // 12: vschema.SrvVSchema.routing_rules:type_name -> vschema.RoutingRules 11, // 13: vschema.SrvVSchema.shard_routing_rules:type_name -> vschema.ShardRoutingRules 13, // 14: vschema.SrvVSchema.keyspace_routing_rules:type_name -> vschema.KeyspaceRoutingRules - 12, // 15: vschema.ShardRoutingRules.rules:type_name -> vschema.ShardRoutingRule - 14, // 16: vschema.KeyspaceRoutingRules.rules:type_name -> vschema.KeyspaceRoutingRule - 5, // 17: vschema.Keyspace.VindexesEntry.value:type_name -> vschema.Vindex - 6, // 18: vschema.Keyspace.TablesEntry.value:type_name -> vschema.Table - 3, // 19: vschema.SrvVSchema.KeyspacesEntry.value:type_name -> vschema.Keyspace - 20, // [20:20] is the sub-list for method output_type - 20, // [20:20] is the sub-list for method input_type - 20, // [20:20] is the sub-list for extension type_name - 20, // [20:20] is the sub-list for extension extendee - 0, // [0:20] is the sub-list for field type_name + 15, // 15: vschema.SrvVSchema.mirror_rules:type_name -> vschema.MirrorRules + 12, // 16: vschema.ShardRoutingRules.rules:type_name -> vschema.ShardRoutingRule + 14, // 17: vschema.KeyspaceRoutingRules.rules:type_name -> vschema.KeyspaceRoutingRule + 16, // 18: vschema.MirrorRules.rules:type_name -> vschema.MirrorRule + 5, // 19: vschema.Keyspace.VindexesEntry.value:type_name -> vschema.Vindex + 6, // 20: vschema.Keyspace.TablesEntry.value:type_name -> vschema.Table + 3, // 21: vschema.SrvVSchema.KeyspacesEntry.value:type_name -> vschema.Keyspace + 22, // [22:22] is the sub-list for method output_type + 22, // [22:22] is the sub-list for method input_type + 22, // [22:22] is the sub-list for extension type_name + 22, // [22:22] is the sub-list for extension extendee + 0, // [0:22] is the sub-list for field type_name } func init() { file_vschema_proto_init() } @@ -1465,6 +1605,30 @@ func file_vschema_proto_init() { return nil } } + file_vschema_proto_msgTypes[14].Exporter = func(v any, i int) any { + switch v := v.(*MirrorRules); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_vschema_proto_msgTypes[15].Exporter = func(v any, i int) any { + switch v := v.(*MirrorRule); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_vschema_proto_msgTypes[8].OneofWrappers = []any{} type x struct{} @@ -1473,7 +1637,7 @@ func file_vschema_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_vschema_proto_rawDesc, NumEnums: 1, - NumMessages: 18, + NumMessages: 20, NumExtensions: 0, NumServices: 0, }, diff --git a/go/vt/proto/vschema/vschema_vtproto.pb.go b/go/vt/proto/vschema/vschema_vtproto.pb.go index 8cf523f4009..1951f430a15 100644 --- a/go/vt/proto/vschema/vschema_vtproto.pb.go +++ b/go/vt/proto/vschema/vschema_vtproto.pb.go @@ -5,10 +5,12 @@ package vschema import ( + binary "encoding/binary" fmt "fmt" proto "google.golang.org/protobuf/proto" protoimpl "google.golang.org/protobuf/runtime/protoimpl" io "io" + math "math" bits "math/bits" query "vitess.io/vitess/go/vt/proto/query" ) @@ -266,6 +268,7 @@ func (m *SrvVSchema) CloneVT() *SrvVSchema { RoutingRules: m.RoutingRules.CloneVT(), ShardRoutingRules: m.ShardRoutingRules.CloneVT(), KeyspaceRoutingRules: m.KeyspaceRoutingRules.CloneVT(), + MirrorRules: m.MirrorRules.CloneVT(), } if rhs := m.Keyspaces; rhs != nil { tmpContainer := make(map[string]*Keyspace, len(rhs)) @@ -370,6 +373,49 @@ func (m *KeyspaceRoutingRule) CloneMessageVT() proto.Message { return m.CloneVT() } +func (m *MirrorRules) CloneVT() *MirrorRules { + if m == nil { + return (*MirrorRules)(nil) + } + r := &MirrorRules{} + if rhs := m.Rules; rhs != nil { + tmpContainer := make([]*MirrorRule, len(rhs)) + for k, v := range rhs { + tmpContainer[k] = v.CloneVT() + } + r.Rules = tmpContainer + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *MirrorRules) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *MirrorRule) CloneVT() *MirrorRule { + if m == nil { + return (*MirrorRule)(nil) + } + r := &MirrorRule{ + FromTable: m.FromTable, + ToTable: m.ToTable, + Percent: m.Percent, + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *MirrorRule) CloneMessageVT() proto.Message { + return m.CloneVT() +} + func (m *RoutingRules) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil @@ -1016,6 +1062,16 @@ func (m *SrvVSchema) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.MirrorRules != nil { + size, err := m.MirrorRules.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x2a + } if m.KeyspaceRoutingRules != nil { size, err := m.KeyspaceRoutingRules.MarshalToSizedBufferVT(dAtA[:i]) if err != nil { @@ -1262,6 +1318,104 @@ func (m *KeyspaceRoutingRule) MarshalToSizedBufferVT(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *MirrorRules) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MirrorRules) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *MirrorRules) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.Rules) > 0 { + for iNdEx := len(m.Rules) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Rules[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *MirrorRule) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MirrorRule) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *MirrorRule) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Percent != 0 { + i -= 4 + binary.LittleEndian.PutUint32(dAtA[i:], uint32(math.Float32bits(float32(m.Percent)))) + i-- + dAtA[i] = 0x1d + } + if len(m.ToTable) > 0 { + i -= len(m.ToTable) + copy(dAtA[i:], m.ToTable) + i = encodeVarint(dAtA, i, uint64(len(m.ToTable))) + i-- + dAtA[i] = 0x12 + } + if len(m.FromTable) > 0 { + i -= len(m.FromTable) + copy(dAtA[i:], m.FromTable) + i = encodeVarint(dAtA, i, uint64(len(m.FromTable))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarint(dAtA []byte, offset int, v uint64) int { offset -= sov(v) base := offset @@ -1558,6 +1712,10 @@ func (m *SrvVSchema) SizeVT() (n int) { l = m.KeyspaceRoutingRules.SizeVT() n += 1 + l + sov(uint64(l)) } + if m.MirrorRules != nil { + l = m.MirrorRules.SizeVT() + n += 1 + l + sov(uint64(l)) + } n += len(m.unknownFields) return n } @@ -1634,6 +1792,43 @@ func (m *KeyspaceRoutingRule) SizeVT() (n int) { return n } +func (m *MirrorRules) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Rules) > 0 { + for _, e := range m.Rules { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } + n += len(m.unknownFields) + return n +} + +func (m *MirrorRule) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.FromTable) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.ToTable) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if m.Percent != 0 { + n += 5 + } + n += len(m.unknownFields) + return n +} + func sov(x uint64) (n int) { return (bits.Len64(x|1) + 6) / 7 } @@ -3664,6 +3859,42 @@ func (m *SrvVSchema) UnmarshalVT(dAtA []byte) error { return err } iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MirrorRules", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.MirrorRules == nil { + m.MirrorRules = &MirrorRules{} + } + if err := m.MirrorRules.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -4118,6 +4349,217 @@ func (m *KeyspaceRoutingRule) UnmarshalVT(dAtA []byte) error { } return nil } +func (m *MirrorRules) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MirrorRules: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MirrorRules: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Rules", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Rules = append(m.Rules, &MirrorRule{}) + if err := m.Rules[len(m.Rules)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MirrorRule) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MirrorRule: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MirrorRule: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FromTable", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FromTable = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ToTable", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ToTable = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 5 { + return fmt.Errorf("proto: wrong wireType = %d for field Percent", wireType) + } + var v uint32 + if (iNdEx + 4) > l { + return io.ErrUnexpectedEOF + } + v = uint32(binary.LittleEndian.Uint32(dAtA[iNdEx:])) + iNdEx += 4 + m.Percent = float32(math.Float32frombits(v)) + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skip(dAtA []byte) (n int, err error) { l := len(dAtA) diff --git a/go/vt/proto/vtctldata/vtctldata.pb.go b/go/vt/proto/vtctldata/vtctldata.pb.go index 4a6f9e25f2e..a79acd29dab 100644 --- a/go/vt/proto/vtctldata/vtctldata.pb.go +++ b/go/vt/proto/vtctldata/vtctldata.pb.go @@ -2840,22 +2840,8 @@ type CheckThrottlerResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // StatusCode is HTTP compliant response code (e.g. 200 for OK) - StatusCode int32 `protobuf:"varint,1,opt,name=status_code,json=statusCode,proto3" json:"status_code,omitempty"` - // Value is the metric value collected by the tablet - Value float64 `protobuf:"fixed64,2,opt,name=value,proto3" json:"value,omitempty"` - // Threshold is the throttling threshold the table was comparing the value with - Threshold float64 `protobuf:"fixed64,3,opt,name=threshold,proto3" json:"threshold,omitempty"` - // Error indicates an error retrieving the value - Error string `protobuf:"bytes,4,opt,name=error,proto3" json:"error,omitempty"` - // Message - Message string `protobuf:"bytes,5,opt,name=message,proto3" json:"message,omitempty"` - // RecentlyChecked indicates that the tablet has been hit with a user-facing check, which can then imply - // that heartbeats lease should be renwed. - RecentlyChecked bool `protobuf:"varint,6,opt,name=recently_checked,json=recentlyChecked,proto3" json:"recently_checked,omitempty"` - // Metrics is a map (metric name -> metric value/error) so that the client has as much - // information as possible about all the checked metrics. - Metrics map[string]*CheckThrottlerResponse_Metric `protobuf:"bytes,7,rep,name=metrics,proto3" json:"metrics,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + TabletAlias *topodata.TabletAlias `protobuf:"bytes,1,opt,name=tablet_alias,json=tabletAlias,proto3" json:"tablet_alias,omitempty"` + Check *tabletmanagerdata.CheckThrottlerResponse `protobuf:"bytes,2,opt,name=Check,proto3" json:"Check,omitempty"` } func (x *CheckThrottlerResponse) Reset() { @@ -2890,51 +2876,16 @@ func (*CheckThrottlerResponse) Descriptor() ([]byte, []int) { return file_vtctldata_proto_rawDescGZIP(), []int{31} } -func (x *CheckThrottlerResponse) GetStatusCode() int32 { +func (x *CheckThrottlerResponse) GetTabletAlias() *topodata.TabletAlias { if x != nil { - return x.StatusCode - } - return 0 -} - -func (x *CheckThrottlerResponse) GetValue() float64 { - if x != nil { - return x.Value - } - return 0 -} - -func (x *CheckThrottlerResponse) GetThreshold() float64 { - if x != nil { - return x.Threshold - } - return 0 -} - -func (x *CheckThrottlerResponse) GetError() string { - if x != nil { - return x.Error - } - return "" -} - -func (x *CheckThrottlerResponse) GetMessage() string { - if x != nil { - return x.Message - } - return "" -} - -func (x *CheckThrottlerResponse) GetRecentlyChecked() bool { - if x != nil { - return x.RecentlyChecked + return x.TabletAlias } - return false + return nil } -func (x *CheckThrottlerResponse) GetMetrics() map[string]*CheckThrottlerResponse_Metric { +func (x *CheckThrottlerResponse) GetCheck() *tabletmanagerdata.CheckThrottlerResponse { if x != nil { - return x.Metrics + return x.Check } return nil } @@ -7347,42 +7298,7 @@ type GetThrottlerStatusResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // TabletAlias is the alias of probed tablet - TabletAlias string `protobuf:"bytes,1,opt,name=tablet_alias,json=tabletAlias,proto3" json:"tablet_alias,omitempty"` - Keyspace string `protobuf:"bytes,2,opt,name=keyspace,proto3" json:"keyspace,omitempty"` - Shard string `protobuf:"bytes,3,opt,name=shard,proto3" json:"shard,omitempty"` - // IsLeader indicates if the tablet is the leader of the shard, ie. the primary - IsLeader bool `protobuf:"varint,4,opt,name=is_leader,json=isLeader,proto3" json:"is_leader,omitempty"` - // IsOpen per stateManager - IsOpen bool `protobuf:"varint,5,opt,name=is_open,json=isOpen,proto3" json:"is_open,omitempty"` - // IsEnabled per throttler configuration - IsEnabled bool `protobuf:"varint,6,opt,name=is_enabled,json=isEnabled,proto3" json:"is_enabled,omitempty"` - // IsDormant: whether the throttler is dormant, ie has not received any checks in a while - // and goes into low-frequency probing mode. - IsDormant bool `protobuf:"varint,7,opt,name=is_dormant,json=isDormant,proto3" json:"is_dormant,omitempty"` - // LagMetricQuery is the query used to check the lag metric, a constant used by the throttler. - LagMetricQuery string `protobuf:"bytes,8,opt,name=lag_metric_query,json=lagMetricQuery,proto3" json:"lag_metric_query,omitempty"` - // CustomMetricQuery is the query used to check the custom metric, supplied by the user. - CustomMetricQuery string `protobuf:"bytes,9,opt,name=custom_metric_query,json=customMetricQuery,proto3" json:"custom_metric_query,omitempty"` - // DefaultThreshold is the threshold used by the throttler for the default metric (lag or custom in single-metric throttlers) - DefaultThreshold float64 `protobuf:"fixed64,10,opt,name=default_threshold,json=defaultThreshold,proto3" json:"default_threshold,omitempty"` - // MetricNameUsedAsDefault is the name of the metric used as the default metric: "lag" or "custom", for backwards compatibility - // with single-metric throttlers - MetricNameUsedAsDefault string `protobuf:"bytes,11,opt,name=metric_name_used_as_default,json=metricNameUsedAsDefault,proto3" json:"metric_name_used_as_default,omitempty"` - // AggregatedMetrics is a map of metric names to their values/errors - // Names are, for example, "self", "self/lag", "shard/lag", "shard/loadavg", etc. - AggregatedMetrics map[string]*GetThrottlerStatusResponse_MetricResult `protobuf:"bytes,12,rep,name=aggregated_metrics,json=aggregatedMetrics,proto3" json:"aggregated_metrics,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // MetricThresholds is a map of metric names to their thresholds. - MetricThresholds map[string]float64 `protobuf:"bytes,13,rep,name=metric_thresholds,json=metricThresholds,proto3" json:"metric_thresholds,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"fixed64,2,opt,name=value,proto3"` - // MetricsHealth is a map of metric names to their health status. - MetricsHealth map[string]*GetThrottlerStatusResponse_MetricHealth `protobuf:"bytes,14,rep,name=metrics_health,json=metricsHealth,proto3" json:"metrics_health,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // ThrottledApps is a map of app names to their throttling rules - ThrottledApps map[string]*topodata.ThrottledAppRule `protobuf:"bytes,15,rep,name=throttled_apps,json=throttledApps,proto3" json:"throttled_apps,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // AppCheckedMetrics is a map of app names to their assigned metrics - AppCheckedMetrics map[string]string `protobuf:"bytes,16,rep,name=app_checked_metrics,json=appCheckedMetrics,proto3" json:"app_checked_metrics,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - RecentlyChecked bool `protobuf:"varint,17,opt,name=recently_checked,json=recentlyChecked,proto3" json:"recently_checked,omitempty"` - // RecentApps is a map of app names to their recent check status - RecentApps map[string]*GetThrottlerStatusResponse_RecentApp `protobuf:"bytes,18,rep,name=recent_apps,json=recentApps,proto3" json:"recent_apps,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Status *tabletmanagerdata.GetThrottlerStatusResponse `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"` } func (x *GetThrottlerStatusResponse) Reset() { @@ -7417,128 +7333,9 @@ func (*GetThrottlerStatusResponse) Descriptor() ([]byte, []int) { return file_vtctldata_proto_rawDescGZIP(), []int{111} } -func (x *GetThrottlerStatusResponse) GetTabletAlias() string { - if x != nil { - return x.TabletAlias - } - return "" -} - -func (x *GetThrottlerStatusResponse) GetKeyspace() string { - if x != nil { - return x.Keyspace - } - return "" -} - -func (x *GetThrottlerStatusResponse) GetShard() string { - if x != nil { - return x.Shard - } - return "" -} - -func (x *GetThrottlerStatusResponse) GetIsLeader() bool { - if x != nil { - return x.IsLeader - } - return false -} - -func (x *GetThrottlerStatusResponse) GetIsOpen() bool { - if x != nil { - return x.IsOpen - } - return false -} - -func (x *GetThrottlerStatusResponse) GetIsEnabled() bool { - if x != nil { - return x.IsEnabled - } - return false -} - -func (x *GetThrottlerStatusResponse) GetIsDormant() bool { +func (x *GetThrottlerStatusResponse) GetStatus() *tabletmanagerdata.GetThrottlerStatusResponse { if x != nil { - return x.IsDormant - } - return false -} - -func (x *GetThrottlerStatusResponse) GetLagMetricQuery() string { - if x != nil { - return x.LagMetricQuery - } - return "" -} - -func (x *GetThrottlerStatusResponse) GetCustomMetricQuery() string { - if x != nil { - return x.CustomMetricQuery - } - return "" -} - -func (x *GetThrottlerStatusResponse) GetDefaultThreshold() float64 { - if x != nil { - return x.DefaultThreshold - } - return 0 -} - -func (x *GetThrottlerStatusResponse) GetMetricNameUsedAsDefault() string { - if x != nil { - return x.MetricNameUsedAsDefault - } - return "" -} - -func (x *GetThrottlerStatusResponse) GetAggregatedMetrics() map[string]*GetThrottlerStatusResponse_MetricResult { - if x != nil { - return x.AggregatedMetrics - } - return nil -} - -func (x *GetThrottlerStatusResponse) GetMetricThresholds() map[string]float64 { - if x != nil { - return x.MetricThresholds - } - return nil -} - -func (x *GetThrottlerStatusResponse) GetMetricsHealth() map[string]*GetThrottlerStatusResponse_MetricHealth { - if x != nil { - return x.MetricsHealth - } - return nil -} - -func (x *GetThrottlerStatusResponse) GetThrottledApps() map[string]*topodata.ThrottledAppRule { - if x != nil { - return x.ThrottledApps - } - return nil -} - -func (x *GetThrottlerStatusResponse) GetAppCheckedMetrics() map[string]string { - if x != nil { - return x.AppCheckedMetrics - } - return nil -} - -func (x *GetThrottlerStatusResponse) GetRecentlyChecked() bool { - if x != nil { - return x.RecentlyChecked - } - return false -} - -func (x *GetThrottlerStatusResponse) GetRecentApps() map[string]*GetThrottlerStatusResponse_RecentApp { - if x != nil { - return x.RecentApps + return x.Status } return nil } @@ -15568,32 +15365,29 @@ func (x *WorkflowUpdateResponse) GetDetails() []*WorkflowUpdateResponse_TabletIn return nil } -type Workflow_ReplicationLocation struct { +type GetMirrorRulesRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - - Keyspace string `protobuf:"bytes,1,opt,name=keyspace,proto3" json:"keyspace,omitempty"` - Shards []string `protobuf:"bytes,2,rep,name=shards,proto3" json:"shards,omitempty"` } -func (x *Workflow_ReplicationLocation) Reset() { - *x = Workflow_ReplicationLocation{} +func (x *GetMirrorRulesRequest) Reset() { + *x = GetMirrorRulesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[246] + mi := &file_vtctldata_proto_msgTypes[245] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *Workflow_ReplicationLocation) String() string { +func (x *GetMirrorRulesRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Workflow_ReplicationLocation) ProtoMessage() {} +func (*GetMirrorRulesRequest) ProtoMessage() {} -func (x *Workflow_ReplicationLocation) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[246] +func (x *GetMirrorRulesRequest) ProtoReflect() protoreflect.Message { + mi := &file_vtctldata_proto_msgTypes[245] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15604,37 +15398,71 @@ func (x *Workflow_ReplicationLocation) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Workflow_ReplicationLocation.ProtoReflect.Descriptor instead. -func (*Workflow_ReplicationLocation) Descriptor() ([]byte, []int) { - return file_vtctldata_proto_rawDescGZIP(), []int{8, 1} +// Deprecated: Use GetMirrorRulesRequest.ProtoReflect.Descriptor instead. +func (*GetMirrorRulesRequest) Descriptor() ([]byte, []int) { + return file_vtctldata_proto_rawDescGZIP(), []int{245} } -func (x *Workflow_ReplicationLocation) GetKeyspace() string { - if x != nil { - return x.Keyspace +type GetMirrorRulesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MirrorRules *vschema.MirrorRules `protobuf:"bytes,1,opt,name=mirror_rules,json=mirrorRules,proto3" json:"mirror_rules,omitempty"` +} + +func (x *GetMirrorRulesResponse) Reset() { + *x = GetMirrorRulesResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_vtctldata_proto_msgTypes[246] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } - return "" } -func (x *Workflow_ReplicationLocation) GetShards() []string { +func (x *GetMirrorRulesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetMirrorRulesResponse) ProtoMessage() {} + +func (x *GetMirrorRulesResponse) ProtoReflect() protoreflect.Message { + mi := &file_vtctldata_proto_msgTypes[246] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetMirrorRulesResponse.ProtoReflect.Descriptor instead. +func (*GetMirrorRulesResponse) Descriptor() ([]byte, []int) { + return file_vtctldata_proto_rawDescGZIP(), []int{246} +} + +func (x *GetMirrorRulesResponse) GetMirrorRules() *vschema.MirrorRules { if x != nil { - return x.Shards + return x.MirrorRules } return nil } -type Workflow_ShardStream struct { +type WorkflowMirrorTrafficRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Streams []*Workflow_Stream `protobuf:"bytes,1,rep,name=streams,proto3" json:"streams,omitempty"` - TabletControls []*topodata.Shard_TabletControl `protobuf:"bytes,2,rep,name=tablet_controls,json=tabletControls,proto3" json:"tablet_controls,omitempty"` - IsPrimaryServing bool `protobuf:"varint,3,opt,name=is_primary_serving,json=isPrimaryServing,proto3" json:"is_primary_serving,omitempty"` + Keyspace string `protobuf:"bytes,1,opt,name=keyspace,proto3" json:"keyspace,omitempty"` + Workflow string `protobuf:"bytes,2,opt,name=workflow,proto3" json:"workflow,omitempty"` + TabletTypes []topodata.TabletType `protobuf:"varint,3,rep,packed,name=tablet_types,json=tabletTypes,proto3,enum=topodata.TabletType" json:"tablet_types,omitempty"` + Percent float32 `protobuf:"fixed32,4,opt,name=percent,proto3" json:"percent,omitempty"` } -func (x *Workflow_ShardStream) Reset() { - *x = Workflow_ShardStream{} +func (x *WorkflowMirrorTrafficRequest) Reset() { + *x = WorkflowMirrorTrafficRequest{} if protoimpl.UnsafeEnabled { mi := &file_vtctldata_proto_msgTypes[247] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -15642,13 +15470,13 @@ func (x *Workflow_ShardStream) Reset() { } } -func (x *Workflow_ShardStream) String() string { +func (x *WorkflowMirrorTrafficRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Workflow_ShardStream) ProtoMessage() {} +func (*WorkflowMirrorTrafficRequest) ProtoMessage() {} -func (x *Workflow_ShardStream) ProtoReflect() protoreflect.Message { +func (x *WorkflowMirrorTrafficRequest) ProtoReflect() protoreflect.Message { mi := &file_vtctldata_proto_msgTypes[247] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -15660,69 +15488,51 @@ func (x *Workflow_ShardStream) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Workflow_ShardStream.ProtoReflect.Descriptor instead. -func (*Workflow_ShardStream) Descriptor() ([]byte, []int) { - return file_vtctldata_proto_rawDescGZIP(), []int{8, 2} +// Deprecated: Use WorkflowMirrorTrafficRequest.ProtoReflect.Descriptor instead. +func (*WorkflowMirrorTrafficRequest) Descriptor() ([]byte, []int) { + return file_vtctldata_proto_rawDescGZIP(), []int{247} } -func (x *Workflow_ShardStream) GetStreams() []*Workflow_Stream { +func (x *WorkflowMirrorTrafficRequest) GetKeyspace() string { if x != nil { - return x.Streams + return x.Keyspace } - return nil + return "" } -func (x *Workflow_ShardStream) GetTabletControls() []*topodata.Shard_TabletControl { +func (x *WorkflowMirrorTrafficRequest) GetWorkflow() string { if x != nil { - return x.TabletControls + return x.Workflow + } + return "" +} + +func (x *WorkflowMirrorTrafficRequest) GetTabletTypes() []topodata.TabletType { + if x != nil { + return x.TabletTypes } return nil } -func (x *Workflow_ShardStream) GetIsPrimaryServing() bool { +func (x *WorkflowMirrorTrafficRequest) GetPercent() float32 { if x != nil { - return x.IsPrimaryServing + return x.Percent } - return false + return 0 } -type Workflow_Stream struct { +type WorkflowMirrorTrafficResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` - Shard string `protobuf:"bytes,2,opt,name=shard,proto3" json:"shard,omitempty"` - Tablet *topodata.TabletAlias `protobuf:"bytes,3,opt,name=tablet,proto3" json:"tablet,omitempty"` - BinlogSource *binlogdata.BinlogSource `protobuf:"bytes,4,opt,name=binlog_source,json=binlogSource,proto3" json:"binlog_source,omitempty"` - Position string `protobuf:"bytes,5,opt,name=position,proto3" json:"position,omitempty"` - StopPosition string `protobuf:"bytes,6,opt,name=stop_position,json=stopPosition,proto3" json:"stop_position,omitempty"` - State string `protobuf:"bytes,7,opt,name=state,proto3" json:"state,omitempty"` - DbName string `protobuf:"bytes,8,opt,name=db_name,json=dbName,proto3" json:"db_name,omitempty"` - TransactionTimestamp *vttime.Time `protobuf:"bytes,9,opt,name=transaction_timestamp,json=transactionTimestamp,proto3" json:"transaction_timestamp,omitempty"` - TimeUpdated *vttime.Time `protobuf:"bytes,10,opt,name=time_updated,json=timeUpdated,proto3" json:"time_updated,omitempty"` - Message string `protobuf:"bytes,11,opt,name=message,proto3" json:"message,omitempty"` - CopyStates []*Workflow_Stream_CopyState `protobuf:"bytes,12,rep,name=copy_states,json=copyStates,proto3" json:"copy_states,omitempty"` - Logs []*Workflow_Stream_Log `protobuf:"bytes,13,rep,name=logs,proto3" json:"logs,omitempty"` - // LogFetchError is set if we fail to fetch some logs for this stream. We - // will never fail to fetch workflows because we cannot fetch the logs, but - // we will still forward log-fetch errors to the caller, should that be - // relevant to the context in which they are fetching workflows. - // - // Note that this field being set does not necessarily mean that Logs is nil; - // if there are N logs that exist for the stream, and we fail to fetch the - // ith log, we will still return logs in [0, i) + (i, N]. - LogFetchError string `protobuf:"bytes,14,opt,name=log_fetch_error,json=logFetchError,proto3" json:"log_fetch_error,omitempty"` - Tags []string `protobuf:"bytes,15,rep,name=tags,proto3" json:"tags,omitempty"` - RowsCopied int64 `protobuf:"varint,16,opt,name=rows_copied,json=rowsCopied,proto3" json:"rows_copied,omitempty"` - ThrottlerStatus *Workflow_Stream_ThrottlerStatus `protobuf:"bytes,17,opt,name=throttler_status,json=throttlerStatus,proto3" json:"throttler_status,omitempty"` - TabletTypes []topodata.TabletType `protobuf:"varint,18,rep,packed,name=tablet_types,json=tabletTypes,proto3,enum=topodata.TabletType" json:"tablet_types,omitempty"` - TabletSelectionPreference tabletmanagerdata.TabletSelectionPreference `protobuf:"varint,19,opt,name=tablet_selection_preference,json=tabletSelectionPreference,proto3,enum=tabletmanagerdata.TabletSelectionPreference" json:"tablet_selection_preference,omitempty"` - Cells []string `protobuf:"bytes,20,rep,name=cells,proto3" json:"cells,omitempty"` + Summary string `protobuf:"bytes,1,opt,name=summary,proto3" json:"summary,omitempty"` + StartState string `protobuf:"bytes,2,opt,name=start_state,json=startState,proto3" json:"start_state,omitempty"` + CurrentState string `protobuf:"bytes,3,opt,name=current_state,json=currentState,proto3" json:"current_state,omitempty"` } -func (x *Workflow_Stream) Reset() { - *x = Workflow_Stream{} +func (x *WorkflowMirrorTrafficResponse) Reset() { + *x = WorkflowMirrorTrafficResponse{} if protoimpl.UnsafeEnabled { mi := &file_vtctldata_proto_msgTypes[248] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -15730,13 +15540,13 @@ func (x *Workflow_Stream) Reset() { } } -func (x *Workflow_Stream) String() string { +func (x *WorkflowMirrorTrafficResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Workflow_Stream) ProtoMessage() {} +func (*WorkflowMirrorTrafficResponse) ProtoMessage() {} -func (x *Workflow_Stream) ProtoReflect() protoreflect.Message { +func (x *WorkflowMirrorTrafficResponse) ProtoReflect() protoreflect.Message { mi := &file_vtctldata_proto_msgTypes[248] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -15748,37 +15558,243 @@ func (x *Workflow_Stream) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Workflow_Stream.ProtoReflect.Descriptor instead. -func (*Workflow_Stream) Descriptor() ([]byte, []int) { - return file_vtctldata_proto_rawDescGZIP(), []int{8, 3} -} - -func (x *Workflow_Stream) GetId() int64 { - if x != nil { - return x.Id - } - return 0 +// Deprecated: Use WorkflowMirrorTrafficResponse.ProtoReflect.Descriptor instead. +func (*WorkflowMirrorTrafficResponse) Descriptor() ([]byte, []int) { + return file_vtctldata_proto_rawDescGZIP(), []int{248} } -func (x *Workflow_Stream) GetShard() string { +func (x *WorkflowMirrorTrafficResponse) GetSummary() string { if x != nil { - return x.Shard + return x.Summary } return "" } -func (x *Workflow_Stream) GetTablet() *topodata.TabletAlias { +func (x *WorkflowMirrorTrafficResponse) GetStartState() string { if x != nil { - return x.Tablet + return x.StartState } - return nil + return "" } -func (x *Workflow_Stream) GetBinlogSource() *binlogdata.BinlogSource { +func (x *WorkflowMirrorTrafficResponse) GetCurrentState() string { if x != nil { - return x.BinlogSource + return x.CurrentState } - return nil + return "" +} + +type Workflow_ReplicationLocation struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Keyspace string `protobuf:"bytes,1,opt,name=keyspace,proto3" json:"keyspace,omitempty"` + Shards []string `protobuf:"bytes,2,rep,name=shards,proto3" json:"shards,omitempty"` +} + +func (x *Workflow_ReplicationLocation) Reset() { + *x = Workflow_ReplicationLocation{} + if protoimpl.UnsafeEnabled { + mi := &file_vtctldata_proto_msgTypes[250] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Workflow_ReplicationLocation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Workflow_ReplicationLocation) ProtoMessage() {} + +func (x *Workflow_ReplicationLocation) ProtoReflect() protoreflect.Message { + mi := &file_vtctldata_proto_msgTypes[250] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Workflow_ReplicationLocation.ProtoReflect.Descriptor instead. +func (*Workflow_ReplicationLocation) Descriptor() ([]byte, []int) { + return file_vtctldata_proto_rawDescGZIP(), []int{8, 1} +} + +func (x *Workflow_ReplicationLocation) GetKeyspace() string { + if x != nil { + return x.Keyspace + } + return "" +} + +func (x *Workflow_ReplicationLocation) GetShards() []string { + if x != nil { + return x.Shards + } + return nil +} + +type Workflow_ShardStream struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Streams []*Workflow_Stream `protobuf:"bytes,1,rep,name=streams,proto3" json:"streams,omitempty"` + TabletControls []*topodata.Shard_TabletControl `protobuf:"bytes,2,rep,name=tablet_controls,json=tabletControls,proto3" json:"tablet_controls,omitempty"` + IsPrimaryServing bool `protobuf:"varint,3,opt,name=is_primary_serving,json=isPrimaryServing,proto3" json:"is_primary_serving,omitempty"` +} + +func (x *Workflow_ShardStream) Reset() { + *x = Workflow_ShardStream{} + if protoimpl.UnsafeEnabled { + mi := &file_vtctldata_proto_msgTypes[251] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Workflow_ShardStream) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Workflow_ShardStream) ProtoMessage() {} + +func (x *Workflow_ShardStream) ProtoReflect() protoreflect.Message { + mi := &file_vtctldata_proto_msgTypes[251] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Workflow_ShardStream.ProtoReflect.Descriptor instead. +func (*Workflow_ShardStream) Descriptor() ([]byte, []int) { + return file_vtctldata_proto_rawDescGZIP(), []int{8, 2} +} + +func (x *Workflow_ShardStream) GetStreams() []*Workflow_Stream { + if x != nil { + return x.Streams + } + return nil +} + +func (x *Workflow_ShardStream) GetTabletControls() []*topodata.Shard_TabletControl { + if x != nil { + return x.TabletControls + } + return nil +} + +func (x *Workflow_ShardStream) GetIsPrimaryServing() bool { + if x != nil { + return x.IsPrimaryServing + } + return false +} + +type Workflow_Stream struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Shard string `protobuf:"bytes,2,opt,name=shard,proto3" json:"shard,omitempty"` + Tablet *topodata.TabletAlias `protobuf:"bytes,3,opt,name=tablet,proto3" json:"tablet,omitempty"` + BinlogSource *binlogdata.BinlogSource `protobuf:"bytes,4,opt,name=binlog_source,json=binlogSource,proto3" json:"binlog_source,omitempty"` + Position string `protobuf:"bytes,5,opt,name=position,proto3" json:"position,omitempty"` + StopPosition string `protobuf:"bytes,6,opt,name=stop_position,json=stopPosition,proto3" json:"stop_position,omitempty"` + State string `protobuf:"bytes,7,opt,name=state,proto3" json:"state,omitempty"` + DbName string `protobuf:"bytes,8,opt,name=db_name,json=dbName,proto3" json:"db_name,omitempty"` + TransactionTimestamp *vttime.Time `protobuf:"bytes,9,opt,name=transaction_timestamp,json=transactionTimestamp,proto3" json:"transaction_timestamp,omitempty"` + TimeUpdated *vttime.Time `protobuf:"bytes,10,opt,name=time_updated,json=timeUpdated,proto3" json:"time_updated,omitempty"` + Message string `protobuf:"bytes,11,opt,name=message,proto3" json:"message,omitempty"` + CopyStates []*Workflow_Stream_CopyState `protobuf:"bytes,12,rep,name=copy_states,json=copyStates,proto3" json:"copy_states,omitempty"` + Logs []*Workflow_Stream_Log `protobuf:"bytes,13,rep,name=logs,proto3" json:"logs,omitempty"` + // LogFetchError is set if we fail to fetch some logs for this stream. We + // will never fail to fetch workflows because we cannot fetch the logs, but + // we will still forward log-fetch errors to the caller, should that be + // relevant to the context in which they are fetching workflows. + // + // Note that this field being set does not necessarily mean that Logs is nil; + // if there are N logs that exist for the stream, and we fail to fetch the + // ith log, we will still return logs in [0, i) + (i, N]. + LogFetchError string `protobuf:"bytes,14,opt,name=log_fetch_error,json=logFetchError,proto3" json:"log_fetch_error,omitempty"` + Tags []string `protobuf:"bytes,15,rep,name=tags,proto3" json:"tags,omitempty"` + RowsCopied int64 `protobuf:"varint,16,opt,name=rows_copied,json=rowsCopied,proto3" json:"rows_copied,omitempty"` + ThrottlerStatus *Workflow_Stream_ThrottlerStatus `protobuf:"bytes,17,opt,name=throttler_status,json=throttlerStatus,proto3" json:"throttler_status,omitempty"` + TabletTypes []topodata.TabletType `protobuf:"varint,18,rep,packed,name=tablet_types,json=tabletTypes,proto3,enum=topodata.TabletType" json:"tablet_types,omitempty"` + TabletSelectionPreference tabletmanagerdata.TabletSelectionPreference `protobuf:"varint,19,opt,name=tablet_selection_preference,json=tabletSelectionPreference,proto3,enum=tabletmanagerdata.TabletSelectionPreference" json:"tablet_selection_preference,omitempty"` + Cells []string `protobuf:"bytes,20,rep,name=cells,proto3" json:"cells,omitempty"` +} + +func (x *Workflow_Stream) Reset() { + *x = Workflow_Stream{} + if protoimpl.UnsafeEnabled { + mi := &file_vtctldata_proto_msgTypes[252] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Workflow_Stream) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Workflow_Stream) ProtoMessage() {} + +func (x *Workflow_Stream) ProtoReflect() protoreflect.Message { + mi := &file_vtctldata_proto_msgTypes[252] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Workflow_Stream.ProtoReflect.Descriptor instead. +func (*Workflow_Stream) Descriptor() ([]byte, []int) { + return file_vtctldata_proto_rawDescGZIP(), []int{8, 3} +} + +func (x *Workflow_Stream) GetId() int64 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *Workflow_Stream) GetShard() string { + if x != nil { + return x.Shard + } + return "" +} + +func (x *Workflow_Stream) GetTablet() *topodata.TabletAlias { + if x != nil { + return x.Tablet + } + return nil +} + +func (x *Workflow_Stream) GetBinlogSource() *binlogdata.BinlogSource { + if x != nil { + return x.BinlogSource + } + return nil } func (x *Workflow_Stream) GetPosition() string { @@ -15906,7 +15922,7 @@ type Workflow_Stream_CopyState struct { func (x *Workflow_Stream_CopyState) Reset() { *x = Workflow_Stream_CopyState{} if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[249] + mi := &file_vtctldata_proto_msgTypes[253] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15919,7 +15935,7 @@ func (x *Workflow_Stream_CopyState) String() string { func (*Workflow_Stream_CopyState) ProtoMessage() {} func (x *Workflow_Stream_CopyState) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[249] + mi := &file_vtctldata_proto_msgTypes[253] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15974,7 +15990,7 @@ type Workflow_Stream_Log struct { func (x *Workflow_Stream_Log) Reset() { *x = Workflow_Stream_Log{} if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[250] + mi := &file_vtctldata_proto_msgTypes[254] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15987,7 +16003,7 @@ func (x *Workflow_Stream_Log) String() string { func (*Workflow_Stream_Log) ProtoMessage() {} func (x *Workflow_Stream_Log) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[250] + mi := &file_vtctldata_proto_msgTypes[254] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16071,7 +16087,7 @@ type Workflow_Stream_ThrottlerStatus struct { func (x *Workflow_Stream_ThrottlerStatus) Reset() { *x = Workflow_Stream_ThrottlerStatus{} if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[251] + mi := &file_vtctldata_proto_msgTypes[255] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16084,7 +16100,7 @@ func (x *Workflow_Stream_ThrottlerStatus) String() string { func (*Workflow_Stream_ThrottlerStatus) ProtoMessage() {} func (x *Workflow_Stream_ThrottlerStatus) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[251] + mi := &file_vtctldata_proto_msgTypes[255] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16125,7 +16141,7 @@ type ApplyVSchemaResponse_ParamList struct { func (x *ApplyVSchemaResponse_ParamList) Reset() { *x = ApplyVSchemaResponse_ParamList{} if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[254] + mi := &file_vtctldata_proto_msgTypes[258] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16138,7 +16154,7 @@ func (x *ApplyVSchemaResponse_ParamList) String() string { func (*ApplyVSchemaResponse_ParamList) ProtoMessage() {} func (x *ApplyVSchemaResponse_ParamList) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[254] + mi := &file_vtctldata_proto_msgTypes[258] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16161,108 +16177,6 @@ func (x *ApplyVSchemaResponse_ParamList) GetParams() []string { return nil } -type CheckThrottlerResponse_Metric struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Name of the metric - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // StatusCode is HTTP compliant response code (e.g. 200 for OK) - StatusCode int32 `protobuf:"varint,2,opt,name=status_code,json=statusCode,proto3" json:"status_code,omitempty"` - // Value is the metric value collected by the tablet - Value float64 `protobuf:"fixed64,3,opt,name=value,proto3" json:"value,omitempty"` - // Threshold is the throttling threshold the table was comparing the value with - Threshold float64 `protobuf:"fixed64,4,opt,name=threshold,proto3" json:"threshold,omitempty"` - // Error indicates an error retrieving the value - Error string `protobuf:"bytes,5,opt,name=error,proto3" json:"error,omitempty"` - // Message - Message string `protobuf:"bytes,6,opt,name=message,proto3" json:"message,omitempty"` - // Scope used in this check - Scope string `protobuf:"bytes,7,opt,name=scope,proto3" json:"scope,omitempty"` -} - -func (x *CheckThrottlerResponse_Metric) Reset() { - *x = CheckThrottlerResponse_Metric{} - if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[256] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CheckThrottlerResponse_Metric) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CheckThrottlerResponse_Metric) ProtoMessage() {} - -func (x *CheckThrottlerResponse_Metric) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[256] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CheckThrottlerResponse_Metric.ProtoReflect.Descriptor instead. -func (*CheckThrottlerResponse_Metric) Descriptor() ([]byte, []int) { - return file_vtctldata_proto_rawDescGZIP(), []int{31, 0} -} - -func (x *CheckThrottlerResponse_Metric) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *CheckThrottlerResponse_Metric) GetStatusCode() int32 { - if x != nil { - return x.StatusCode - } - return 0 -} - -func (x *CheckThrottlerResponse_Metric) GetValue() float64 { - if x != nil { - return x.Value - } - return 0 -} - -func (x *CheckThrottlerResponse_Metric) GetThreshold() float64 { - if x != nil { - return x.Threshold - } - return 0 -} - -func (x *CheckThrottlerResponse_Metric) GetError() string { - if x != nil { - return x.Error - } - return "" -} - -func (x *CheckThrottlerResponse_Metric) GetMessage() string { - if x != nil { - return x.Message - } - return "" -} - -func (x *CheckThrottlerResponse_Metric) GetScope() string { - if x != nil { - return x.Scope - } - return "" -} - type GetSrvKeyspaceNamesResponse_NameList struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -16274,7 +16188,7 @@ type GetSrvKeyspaceNamesResponse_NameList struct { func (x *GetSrvKeyspaceNamesResponse_NameList) Reset() { *x = GetSrvKeyspaceNamesResponse_NameList{} if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[265] + mi := &file_vtctldata_proto_msgTypes[267] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16287,165 +16201,7 @@ func (x *GetSrvKeyspaceNamesResponse_NameList) String() string { func (*GetSrvKeyspaceNamesResponse_NameList) ProtoMessage() {} func (x *GetSrvKeyspaceNamesResponse_NameList) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[265] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetSrvKeyspaceNamesResponse_NameList.ProtoReflect.Descriptor instead. -func (*GetSrvKeyspaceNamesResponse_NameList) Descriptor() ([]byte, []int) { - return file_vtctldata_proto_rawDescGZIP(), []int{97, 1} -} - -func (x *GetSrvKeyspaceNamesResponse_NameList) GetNames() []string { - if x != nil { - return x.Names - } - return nil -} - -type GetThrottlerStatusResponse_MetricResult struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value float64 `protobuf:"fixed64,1,opt,name=value,proto3" json:"value,omitempty"` - Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` -} - -func (x *GetThrottlerStatusResponse_MetricResult) Reset() { - *x = GetThrottlerStatusResponse_MetricResult{} - if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[268] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetThrottlerStatusResponse_MetricResult) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetThrottlerStatusResponse_MetricResult) ProtoMessage() {} - -func (x *GetThrottlerStatusResponse_MetricResult) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[268] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetThrottlerStatusResponse_MetricResult.ProtoReflect.Descriptor instead. -func (*GetThrottlerStatusResponse_MetricResult) Descriptor() ([]byte, []int) { - return file_vtctldata_proto_rawDescGZIP(), []int{111, 0} -} - -func (x *GetThrottlerStatusResponse_MetricResult) GetValue() float64 { - if x != nil { - return x.Value - } - return 0 -} - -func (x *GetThrottlerStatusResponse_MetricResult) GetError() string { - if x != nil { - return x.Error - } - return "" -} - -type GetThrottlerStatusResponse_MetricHealth struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - LastHealthyAt *vttime.Time `protobuf:"bytes,1,opt,name=last_healthy_at,json=lastHealthyAt,proto3" json:"last_healthy_at,omitempty"` - SecondsSinceLastHealthy int64 `protobuf:"varint,2,opt,name=seconds_since_last_healthy,json=secondsSinceLastHealthy,proto3" json:"seconds_since_last_healthy,omitempty"` -} - -func (x *GetThrottlerStatusResponse_MetricHealth) Reset() { - *x = GetThrottlerStatusResponse_MetricHealth{} - if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[271] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetThrottlerStatusResponse_MetricHealth) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetThrottlerStatusResponse_MetricHealth) ProtoMessage() {} - -func (x *GetThrottlerStatusResponse_MetricHealth) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[271] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetThrottlerStatusResponse_MetricHealth.ProtoReflect.Descriptor instead. -func (*GetThrottlerStatusResponse_MetricHealth) Descriptor() ([]byte, []int) { - return file_vtctldata_proto_rawDescGZIP(), []int{111, 3} -} - -func (x *GetThrottlerStatusResponse_MetricHealth) GetLastHealthyAt() *vttime.Time { - if x != nil { - return x.LastHealthyAt - } - return nil -} - -func (x *GetThrottlerStatusResponse_MetricHealth) GetSecondsSinceLastHealthy() int64 { - if x != nil { - return x.SecondsSinceLastHealthy - } - return 0 -} - -type GetThrottlerStatusResponse_RecentApp struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - CheckedAt *vttime.Time `protobuf:"bytes,1,opt,name=checked_at,json=checkedAt,proto3" json:"checked_at,omitempty"` - StatusCode int32 `protobuf:"varint,2,opt,name=status_code,json=statusCode,proto3" json:"status_code,omitempty"` -} - -func (x *GetThrottlerStatusResponse_RecentApp) Reset() { - *x = GetThrottlerStatusResponse_RecentApp{} - if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[275] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetThrottlerStatusResponse_RecentApp) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetThrottlerStatusResponse_RecentApp) ProtoMessage() {} - -func (x *GetThrottlerStatusResponse_RecentApp) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[275] + mi := &file_vtctldata_proto_msgTypes[267] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16456,25 +16212,18 @@ func (x *GetThrottlerStatusResponse_RecentApp) ProtoReflect() protoreflect.Messa return mi.MessageOf(x) } -// Deprecated: Use GetThrottlerStatusResponse_RecentApp.ProtoReflect.Descriptor instead. -func (*GetThrottlerStatusResponse_RecentApp) Descriptor() ([]byte, []int) { - return file_vtctldata_proto_rawDescGZIP(), []int{111, 7} +// Deprecated: Use GetSrvKeyspaceNamesResponse_NameList.ProtoReflect.Descriptor instead. +func (*GetSrvKeyspaceNamesResponse_NameList) Descriptor() ([]byte, []int) { + return file_vtctldata_proto_rawDescGZIP(), []int{97, 1} } -func (x *GetThrottlerStatusResponse_RecentApp) GetCheckedAt() *vttime.Time { +func (x *GetSrvKeyspaceNamesResponse_NameList) GetNames() []string { if x != nil { - return x.CheckedAt + return x.Names } return nil } -func (x *GetThrottlerStatusResponse_RecentApp) GetStatusCode() int32 { - if x != nil { - return x.StatusCode - } - return 0 -} - type MoveTablesCreateResponse_TabletInfo struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -16488,7 +16237,7 @@ type MoveTablesCreateResponse_TabletInfo struct { func (x *MoveTablesCreateResponse_TabletInfo) Reset() { *x = MoveTablesCreateResponse_TabletInfo{} if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[278] + mi := &file_vtctldata_proto_msgTypes[271] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16501,7 +16250,7 @@ func (x *MoveTablesCreateResponse_TabletInfo) String() string { func (*MoveTablesCreateResponse_TabletInfo) ProtoMessage() {} func (x *MoveTablesCreateResponse_TabletInfo) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[278] + mi := &file_vtctldata_proto_msgTypes[271] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16544,7 +16293,7 @@ type WorkflowDeleteResponse_TabletInfo struct { func (x *WorkflowDeleteResponse_TabletInfo) Reset() { *x = WorkflowDeleteResponse_TabletInfo{} if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[288] + mi := &file_vtctldata_proto_msgTypes[281] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16557,7 +16306,7 @@ func (x *WorkflowDeleteResponse_TabletInfo) String() string { func (*WorkflowDeleteResponse_TabletInfo) ProtoMessage() {} func (x *WorkflowDeleteResponse_TabletInfo) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[288] + mi := &file_vtctldata_proto_msgTypes[281] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16603,7 +16352,7 @@ type WorkflowStatusResponse_TableCopyState struct { func (x *WorkflowStatusResponse_TableCopyState) Reset() { *x = WorkflowStatusResponse_TableCopyState{} if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[289] + mi := &file_vtctldata_proto_msgTypes[282] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16616,7 +16365,7 @@ func (x *WorkflowStatusResponse_TableCopyState) String() string { func (*WorkflowStatusResponse_TableCopyState) ProtoMessage() {} func (x *WorkflowStatusResponse_TableCopyState) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[289] + mi := &file_vtctldata_proto_msgTypes[282] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16690,7 +16439,7 @@ type WorkflowStatusResponse_ShardStreamState struct { func (x *WorkflowStatusResponse_ShardStreamState) Reset() { *x = WorkflowStatusResponse_ShardStreamState{} if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[290] + mi := &file_vtctldata_proto_msgTypes[283] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16703,7 +16452,7 @@ func (x *WorkflowStatusResponse_ShardStreamState) String() string { func (*WorkflowStatusResponse_ShardStreamState) ProtoMessage() {} func (x *WorkflowStatusResponse_ShardStreamState) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[290] + mi := &file_vtctldata_proto_msgTypes[283] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16772,7 +16521,7 @@ type WorkflowStatusResponse_ShardStreams struct { func (x *WorkflowStatusResponse_ShardStreams) Reset() { *x = WorkflowStatusResponse_ShardStreams{} if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[291] + mi := &file_vtctldata_proto_msgTypes[284] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16785,7 +16534,7 @@ func (x *WorkflowStatusResponse_ShardStreams) String() string { func (*WorkflowStatusResponse_ShardStreams) ProtoMessage() {} func (x *WorkflowStatusResponse_ShardStreams) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[291] + mi := &file_vtctldata_proto_msgTypes[284] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16822,7 +16571,7 @@ type WorkflowUpdateResponse_TabletInfo struct { func (x *WorkflowUpdateResponse_TabletInfo) Reset() { *x = WorkflowUpdateResponse_TabletInfo{} if protoimpl.UnsafeEnabled { - mi := &file_vtctldata_proto_msgTypes[294] + mi := &file_vtctldata_proto_msgTypes[287] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16835,7 +16584,7 @@ func (x *WorkflowUpdateResponse_TabletInfo) String() string { func (*WorkflowUpdateResponse_TabletInfo) ProtoMessage() {} func (x *WorkflowUpdateResponse_TabletInfo) ProtoReflect() protoreflect.Message { - mi := &file_vtctldata_proto_msgTypes[294] + mi := &file_vtctldata_proto_msgTypes[287] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17490,1621 +17239,1449 @@ var file_vtctldata_proto_rawDesc = []byte{ 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, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x6f, 0x6b, 0x49, 0x66, 0x4e, 0x6f, 0x74, 0x45, 0x78, 0x69, 0x73, 0x74, - 0x73, 0x22, 0xb2, 0x04, 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, 0x1f, 0x0a, 0x0b, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 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, 0x48, 0x0a, 0x07, - 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, - 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, + 0x73, 0x22, 0x93, 0x01, 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, 0x38, 0x0a, 0x0c, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x3f, 0x0a, 0x05, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 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, 0x1a, 0xb7, 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, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, - 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x43, 0x6f, 0x64, 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, - 0x1a, 0x64, 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x05, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x22, 0x4f, 0x0a, 0x1d, 0x43, 0x6c, 0x65, 0x61, 0x6e, + 0x75, 0x70, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 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, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x22, 0xe1, 0x01, 0x0a, 0x1e, 0x43, 0x6c, 0x65, + 0x61, 0x6e, 0x75, 0x70, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x16, 0x72, + 0x6f, 0x77, 0x73, 0x5f, 0x61, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, + 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x76, 0x74, + 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x53, + 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x6f, 0x77, 0x73, 0x41, 0x66, 0x66, 0x65, 0x63, + 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x13, 0x72, 0x6f, 0x77, 0x73, 0x41, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x1a, 0x46, 0x0a, 0x18, 0x52, 0x6f, 0x77, 0x73, 0x41, 0x66, 0x66, 0x65, + 0x63, 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x12, 0x3e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x28, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 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, 0x22, 0x4f, 0x0a, 0x1d, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, - 0x70, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 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, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x22, 0xe1, 0x01, 0x0a, 0x1e, 0x43, 0x6c, 0x65, 0x61, - 0x6e, 0x75, 0x70, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x16, 0x72, 0x6f, - 0x77, 0x73, 0x5f, 0x61, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x73, - 0x68, 0x61, 0x72, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x76, 0x74, 0x63, - 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x53, 0x63, - 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x6f, 0x77, 0x73, 0x41, 0x66, 0x66, 0x65, 0x63, 0x74, - 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x13, - 0x72, 0x6f, 0x77, 0x73, 0x41, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x1a, 0x46, 0x0a, 0x18, 0x52, 0x6f, 0x77, 0x73, 0x41, 0x66, 0x66, 0x65, 0x63, - 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 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, 0x04, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x50, 0x0a, 0x1e, 0x43, + 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x50, 0x0a, 0x1e, + 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, + 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x12, 0x0a, 0x04, 0x75, 0x75, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x22, 0xe3, + 0x01, 0x0a, 0x1f, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, + 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x78, 0x0a, 0x16, 0x72, 0x6f, 0x77, 0x73, 0x5f, 0x61, 0x66, 0x66, 0x65, 0x63, + 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x22, 0xe3, 0x01, - 0x0a, 0x1f, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, - 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x78, 0x0a, 0x16, 0x72, 0x6f, 0x77, 0x73, 0x5f, 0x61, 0x66, 0x66, 0x65, 0x63, 0x74, - 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x43, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6f, - 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x6f, - 0x77, 0x73, 0x41, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x13, 0x72, 0x6f, 0x77, 0x73, 0x41, 0x66, 0x66, 0x65, - 0x63, 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x1a, 0x46, 0x0a, 0x18, 0x52, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x6f, 0x77, 0x73, 0x41, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, 0x61, - 0x72, 0x64, 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, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x22, 0xdd, 0x02, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, - 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x2f, 0x0a, 0x14, 0x61, 0x6c, 0x6c, 0x6f, 0x77, - 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x5f, 0x76, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x2a, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x6b, 0x65, 0x79, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x62, 0x61, 0x73, - 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x31, 0x0a, 0x0d, 0x73, 0x6e, 0x61, - 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0c, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x0c, - 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x11, - 0x64, 0x75, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x64, 0x75, 0x72, 0x61, 0x62, 0x69, 0x6c, - 0x69, 0x74, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x69, 0x64, - 0x65, 0x63, 0x61, 0x72, 0x5f, 0x64, 0x62, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0d, 0x73, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x44, 0x62, 0x4e, 0x61, 0x6d, - 0x65, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x4a, 0x04, 0x08, - 0x06, 0x10, 0x07, 0x22, 0x49, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, - 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x13, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x8c, - 0x01, 0x0a, 0x12, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 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, 0x1d, 0x0a, 0x0a, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x68, 0x61, 0x72, 0x64, 0x4e, 0x61, 0x6d, 0x65, - 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, - 0x65, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, - 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x22, 0xa0, 0x01, - 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x08, 0x6b, 0x65, - 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x26, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x30, - 0x0a, 0x14, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, - 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x73, 0x68, - 0x61, 0x72, 0x64, 0x41, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, - 0x22, 0x41, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, - 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, - 0x72, 0x63, 0x65, 0x22, 0x18, 0x0a, 0x16, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x65, 0x6c, - 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2d, 0x0a, - 0x17, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x41, 0x6c, 0x69, 0x61, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x1a, 0x0a, 0x18, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x41, 0x6c, 0x69, 0x61, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x67, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 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, 0x1c, 0x0a, - 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x66, - 0x6f, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, - 0x65, 0x22, 0x18, 0x0a, 0x16, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x9b, 0x01, 0x0a, 0x13, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1c, 0x0a, - 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x65, - 0x76, 0x65, 0x6e, 0x5f, 0x69, 0x66, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, 0x49, 0x66, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x6e, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x22, 0x16, 0x0a, 0x14, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x2d, 0x0a, 0x17, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x72, 0x76, 0x56, 0x53, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, - 0x63, 0x65, 0x6c, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x65, 0x6c, 0x6c, - 0x22, 0x1a, 0x0a, 0x18, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x72, 0x76, 0x56, 0x53, 0x63, - 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x79, 0x0a, 0x14, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x0e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, - 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 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, 0x0d, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, - 0x65, 0x73, 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, 0x22, 0x17, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x81, 0x03, 0x0a, 0x1d, 0x45, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, - 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x72, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x13, 0x72, 0x6f, 0x77, 0x73, 0x41, 0x66, 0x66, + 0x65, 0x63, 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x1a, 0x46, 0x0a, 0x18, + 0x52, 0x6f, 0x77, 0x73, 0x41, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, + 0x61, 0x72, 0x64, 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, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x22, 0xdd, 0x02, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, + 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x2f, 0x0a, 0x14, 0x61, 0x6c, 0x6c, 0x6f, + 0x77, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x5f, 0x76, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x2a, 0x0a, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, + 0x74, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x6b, 0x65, + 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x62, 0x61, + 0x73, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x31, 0x0a, 0x0d, 0x73, 0x6e, + 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0c, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x52, + 0x0c, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x2b, 0x0a, + 0x11, 0x64, 0x75, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x64, 0x75, 0x72, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x69, + 0x64, 0x65, 0x63, 0x61, 0x72, 0x5f, 0x64, 0x62, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x44, 0x62, 0x4e, 0x61, + 0x6d, 0x65, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x4a, 0x04, + 0x08, 0x06, 0x10, 0x07, 0x22, 0x49, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, + 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, + 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x13, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4b, 0x65, 0x79, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, + 0x8c, 0x01, 0x0a, 0x12, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 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, 0x1d, 0x0a, 0x0a, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x68, 0x61, 0x72, 0x64, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x22, 0xa0, + 0x01, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, + 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x08, 0x6b, + 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x26, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, + 0x74, 0x61, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, + 0x30, 0x0a, 0x14, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, + 0x5f, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x73, + 0x68, 0x61, 0x72, 0x64, 0x41, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x45, 0x78, 0x69, 0x73, 0x74, + 0x73, 0x22, 0x41, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, + 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, + 0x6f, 0x72, 0x63, 0x65, 0x22, 0x18, 0x0a, 0x16, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x65, + 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2d, + 0x0a, 0x17, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x41, 0x6c, 0x69, + 0x61, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x1a, 0x0a, + 0x18, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x41, 0x6c, 0x69, 0x61, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x67, 0x0a, 0x15, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 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, 0x14, - 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, - 0x68, 0x61, 0x72, 0x64, 0x12, 0x36, 0x0a, 0x0b, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x72, 0x69, 0x6d, - 0x61, 0x72, 0x79, 0x18, 0x03, 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, 0x0a, 0x6e, 0x65, 0x77, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x3e, 0x0a, 0x0f, - 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x18, - 0x04, 0x20, 0x03, 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, 0x0e, 0x69, 0x67, - 0x6e, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x12, 0x44, 0x0a, 0x15, - 0x77, 0x61, 0x69, 0x74, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x5f, 0x74, 0x69, - 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, - 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x77, - 0x61, 0x69, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x54, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x12, 0x3f, 0x0a, 0x1c, 0x70, 0x72, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x72, - 0x6f, 0x73, 0x73, 0x5f, 0x63, 0x65, 0x6c, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x19, 0x70, 0x72, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x65, 0x6c, 0x6c, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x14, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x66, 0x6f, 0x72, 0x5f, - 0x61, 0x6c, 0x6c, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x11, 0x77, 0x61, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x41, 0x6c, 0x6c, 0x54, 0x61, 0x62, - 0x6c, 0x65, 0x74, 0x73, 0x22, 0xbc, 0x01, 0x0a, 0x1e, 0x45, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x6e, - 0x63, 0x79, 0x52, 0x65, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x40, 0x0a, 0x10, 0x70, 0x72, 0x6f, - 0x6d, 0x6f, 0x74, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x03, 0x20, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, + 0x0a, 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, + 0x63, 0x65, 0x22, 0x18, 0x0a, 0x16, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x9b, 0x01, 0x0a, + 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, + 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1c, + 0x0a, 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x12, 0x26, 0x0a, 0x0f, + 0x65, 0x76, 0x65, 0x6e, 0x5f, 0x69, 0x66, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, 0x49, 0x66, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x6e, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x22, 0x16, 0x0a, 0x14, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x2d, 0x0a, 0x17, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x72, 0x76, 0x56, + 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, + 0x04, 0x63, 0x65, 0x6c, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x65, 0x6c, + 0x6c, 0x22, 0x1a, 0x0a, 0x18, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x72, 0x76, 0x56, 0x53, + 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x79, 0x0a, + 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x0e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, + 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 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, 0x0d, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, + 0x73, 0x65, 0x73, 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, 0x22, 0x17, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x81, 0x03, 0x0a, 0x1d, 0x45, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, + 0x65, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 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, + 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x36, 0x0a, 0x0b, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x72, 0x69, + 0x6d, 0x61, 0x72, 0x79, 0x18, 0x03, 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, 0x0a, 0x6e, 0x65, 0x77, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x3e, 0x0a, + 0x0f, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, + 0x18, 0x04, 0x20, 0x03, 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, 0x0e, 0x69, + 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x12, 0x44, 0x0a, + 0x15, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, + 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, + 0x77, 0x61, 0x69, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x54, 0x69, 0x6d, 0x65, + 0x6f, 0x75, 0x74, 0x12, 0x3f, 0x0a, 0x1c, 0x70, 0x72, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x63, + 0x72, 0x6f, 0x73, 0x73, 0x5f, 0x63, 0x65, 0x6c, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x19, 0x70, 0x72, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x65, 0x6c, 0x6c, 0x50, 0x72, 0x6f, 0x6d, 0x6f, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x14, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x66, 0x6f, 0x72, + 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x11, 0x77, 0x61, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x41, 0x6c, 0x6c, 0x54, 0x61, + 0x62, 0x6c, 0x65, 0x74, 0x73, 0x22, 0xbc, 0x01, 0x0a, 0x1e, 0x45, 0x6d, 0x65, 0x72, 0x67, 0x65, + 0x6e, 0x63, 0x79, 0x52, 0x65, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x40, 0x0a, 0x10, 0x70, 0x72, + 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x03, + 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, 0x0f, 0x70, 0x72, 0x6f, + 0x6d, 0x6f, 0x74, 0x65, 0x64, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x26, 0x0a, 0x06, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6c, + 0x6f, 0x67, 0x75, 0x74, 0x69, 0x6c, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x73, 0x22, 0xa0, 0x01, 0x0a, 0x18, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, + 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, + 0x73, 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, 0x0b, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x71, + 0x75, 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 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, 0x19, 0x0a, 0x08, + 0x75, 0x73, 0x65, 0x5f, 0x70, 0x6f, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, + 0x75, 0x73, 0x65, 0x50, 0x6f, 0x6f, 0x6c, 0x22, 0x47, 0x0a, 0x19, 0x45, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x65, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x41, 0x70, 0x70, 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, 0xd3, 0x01, 0x0a, 0x18, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x46, 0x65, 0x74, 0x63, + 0x68, 0x41, 0x73, 0x44, 0x42, 0x41, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, + 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0f, 0x70, 0x72, 0x6f, 0x6d, - 0x6f, 0x74, 0x65, 0x64, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x26, 0x0a, 0x06, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6c, 0x6f, - 0x67, 0x75, 0x74, 0x69, 0x6c, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x73, 0x22, 0xa0, 0x01, 0x0a, 0x18, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x46, - 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, - 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, 0x0b, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, - 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 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, 0x19, 0x0a, 0x08, 0x75, - 0x73, 0x65, 0x5f, 0x70, 0x6f, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x75, - 0x73, 0x65, 0x50, 0x6f, 0x6f, 0x6c, 0x22, 0x47, 0x0a, 0x19, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x65, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x41, 0x70, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x52, 0x0b, 0x74, 0x61, 0x62, 0x6c, + 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 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, 0x27, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, + 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0e, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x69, 0x6e, 0x6c, 0x6f, 0x67, + 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x73, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x72, 0x65, 0x6c, 0x6f, 0x61, 0x64, + 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0x47, 0x0a, 0x19, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x65, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x44, 0x42, 0x41, 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, - 0xd3, 0x01, 0x0a, 0x18, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x46, 0x65, 0x74, 0x63, 0x68, - 0x41, 0x73, 0x44, 0x42, 0x41, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0c, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, - 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 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, 0x27, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, - 0x6c, 0x65, 0x5f, 0x62, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0e, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x73, - 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, - 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x72, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0x47, 0x0a, 0x19, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, - 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x44, 0x42, 0x41, 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, 0xa5, - 0x01, 0x0a, 0x12, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x52, 0x65, + 0xa5, 0x01, 0x0a, 0x12, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, + 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, + 0x12, 0x55, 0x0a, 0x13, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x68, 0x6f, 0x6f, 0x6b, 0x5f, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 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, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x52, 0x11, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x48, 0x6f, 0x6f, 0x6b, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x5e, 0x0a, 0x13, 0x45, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, + 0x0a, 0x0b, 0x68, 0x6f, 0x6f, 0x6b, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, + 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x48, + 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x68, 0x6f, 0x6f, + 0x6b, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0xd4, 0x01, 0x0a, 0x1d, 0x45, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x65, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x44, + 0x42, 0x41, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, + 0x69, 0x61, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x71, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x73, 0x71, 0x6c, 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, 0x27, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x69, 0x6e, 0x6c, + 0x6f, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x64, 0x69, 0x73, 0x61, 0x62, + 0x6c, 0x65, 0x42, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x6c, + 0x6f, 0x61, 0x64, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0c, 0x72, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0x4e, + 0x0a, 0x1e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x46, 0x65, + 0x74, 0x63, 0x68, 0x41, 0x73, 0x44, 0x42, 0x41, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x2c, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0x3c, + 0x0a, 0x1e, 0x46, 0x69, 0x6e, 0x64, 0x41, 0x6c, 0x6c, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x49, + 0x6e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 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, 0x22, 0xbe, 0x01, 0x0a, + 0x1f, 0x46, 0x69, 0x6e, 0x64, 0x41, 0x6c, 0x6c, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x49, 0x6e, + 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x4e, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x36, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x46, 0x69, 0x6e, + 0x64, 0x41, 0x6c, 0x6c, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x49, 0x6e, 0x4b, 0x65, 0x79, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, + 0x1a, 0x4b, 0x0a, 0x0b, 0x53, 0x68, 0x61, 0x72, 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, 0x26, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x10, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x54, 0x0a, + 0x22, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x43, 0x75, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x53, 0x63, 0x68, + 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, + 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, + 0x75, 0x69, 0x64, 0x22, 0xeb, 0x01, 0x0a, 0x23, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x43, 0x75, 0x74, + 0x4f, 0x76, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7c, 0x0a, 0x16, 0x72, + 0x6f, 0x77, 0x73, 0x5f, 0x61, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, + 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x47, 0x2e, 0x76, 0x74, + 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x43, 0x75, 0x74, + 0x4f, 0x76, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x6f, 0x77, 0x73, + 0x41, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x13, 0x72, 0x6f, 0x77, 0x73, 0x41, 0x66, 0x66, 0x65, 0x63, 0x74, + 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x1a, 0x46, 0x0a, 0x18, 0x52, 0x6f, 0x77, + 0x73, 0x41, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, + 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, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x22, 0x9e, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, + 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, + 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, + 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x08, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x64, + 0x65, 0x74, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4c, 0x69, 0x6d, + 0x69, 0x74, 0x22, 0x44, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x62, 0x61, 0x63, 0x6b, + 0x75, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x79, 0x73, 0x71, + 0x6c, 0x63, 0x74, 0x6c, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x07, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x22, 0x28, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x43, + 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, + 0x0a, 0x04, 0x63, 0x65, 0x6c, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x65, + 0x6c, 0x6c, 0x22, 0x46, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x43, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, + 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x63, 0x65, 0x6c, + 0x6c, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, + 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x08, 0x63, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x19, 0x0a, 0x17, 0x47, 0x65, + 0x74, 0x43, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x30, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x43, 0x65, 0x6c, 0x6c, + 0x49, 0x6e, 0x66, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x18, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x43, 0x65, + 0x6c, 0x6c, 0x73, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x22, 0xb6, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x41, 0x6c, + 0x69, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, + 0x07, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, + 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x65, + 0x6c, 0x6c, 0x73, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2e, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x07, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x1a, 0x50, 0x0a, 0x0c, 0x41, 0x6c, 0x69, 0x61, + 0x73, 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, 0x2a, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x6f, 0x70, 0x6f, + 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x50, 0x0a, 0x14, 0x47, 0x65, + 0x74, 0x46, 0x75, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, + 0x61, 0x73, 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, + 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0x4c, 0x0a, 0x15, + 0x47, 0x65, 0x74, 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, 0x15, 0x0a, 0x13, 0x47, 0x65, + 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x22, 0x49, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x09, 0x6b, 0x65, 0x79, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x76, + 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x52, 0x09, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x22, 0x30, 0x0a, 0x12, + 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 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, 0x22, 0x46, + 0x0a, 0x13, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, + 0x61, 0x74, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x08, 0x6b, 0x65, + 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x51, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x50, 0x65, 0x72, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0x5a, 0x0a, 0x16, 0x47, 0x65, 0x74, + 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x50, 0x65, 0x72, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x20, 0x0a, 0x1e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x76, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x4b, 0x65, + 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x16, 0x6b, 0x65, + 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x72, + 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x76, 0x73, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x6f, 0x75, + 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x14, 0x6b, 0x65, 0x79, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x22, + 0x18, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x55, 0x0a, 0x17, 0x47, 0x65, 0x74, + 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x0d, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, + 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x76, 0x73, + 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, + 0x65, 0x73, 0x52, 0x0c, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, + 0x22, 0xb0, 0x02, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, - 0x55, 0x0a, 0x13, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x68, 0x6f, 0x6f, 0x6b, 0x5f, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 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, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x52, 0x11, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x48, 0x6f, 0x6f, 0x6b, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x5e, 0x0a, 0x13, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x65, 0x48, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, - 0x0b, 0x68, 0x6f, 0x6f, 0x6b, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, - 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x48, 0x6f, - 0x6f, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x68, 0x6f, 0x6f, 0x6b, - 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0xd4, 0x01, 0x0a, 0x1d, 0x45, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x65, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x44, 0x42, - 0x41, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, - 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, - 0x61, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x71, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x73, 0x71, 0x6c, 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, - 0x27, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x69, 0x6e, 0x6c, 0x6f, - 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, - 0x65, 0x42, 0x69, 0x6e, 0x6c, 0x6f, 0x67, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x6f, - 0x61, 0x64, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0c, 0x72, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0x4e, 0x0a, - 0x1e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x46, 0x65, 0x74, - 0x63, 0x68, 0x41, 0x73, 0x44, 0x42, 0x41, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x2c, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0x3c, 0x0a, - 0x1e, 0x46, 0x69, 0x6e, 0x64, 0x41, 0x6c, 0x6c, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x49, 0x6e, - 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 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, 0x22, 0xbe, 0x01, 0x0a, 0x1f, - 0x46, 0x69, 0x6e, 0x64, 0x41, 0x6c, 0x6c, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x49, 0x6e, 0x4b, - 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x4e, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x36, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x46, 0x69, 0x6e, 0x64, - 0x41, 0x6c, 0x6c, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x49, 0x6e, 0x4b, 0x65, 0x79, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x1a, - 0x4b, 0x0a, 0x0b, 0x53, 0x68, 0x61, 0x72, 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, 0x26, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x10, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x54, 0x0a, 0x22, - 0x46, 0x6f, 0x72, 0x63, 0x65, 0x43, 0x75, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, - 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x12, - 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, - 0x69, 0x64, 0x22, 0xeb, 0x01, 0x0a, 0x23, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x43, 0x75, 0x74, 0x4f, - 0x76, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7c, 0x0a, 0x16, 0x72, 0x6f, - 0x77, 0x73, 0x5f, 0x61, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x73, - 0x68, 0x61, 0x72, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x47, 0x2e, 0x76, 0x74, 0x63, - 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x43, 0x75, 0x74, 0x4f, - 0x76, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x6f, 0x77, 0x73, 0x41, - 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x13, 0x72, 0x6f, 0x77, 0x73, 0x41, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, - 0x64, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x1a, 0x46, 0x0a, 0x18, 0x52, 0x6f, 0x77, 0x73, - 0x41, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 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, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x22, 0x9e, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x1a, - 0x0a, 0x08, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x08, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x65, - 0x74, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x0d, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4c, 0x69, 0x6d, 0x69, - 0x74, 0x22, 0x44, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x75, - 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x79, 0x73, 0x71, 0x6c, - 0x63, 0x74, 0x6c, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x07, - 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x22, 0x28, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x43, 0x65, - 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, - 0x04, 0x63, 0x65, 0x6c, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x65, 0x6c, - 0x6c, 0x22, 0x46, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x43, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x63, 0x65, 0x6c, 0x6c, - 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x6f, - 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x08, 0x63, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x19, 0x0a, 0x17, 0x47, 0x65, 0x74, - 0x43, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x22, 0x30, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x43, 0x65, 0x6c, 0x6c, 0x49, - 0x6e, 0x66, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x18, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x43, 0x65, 0x6c, - 0x6c, 0x73, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x22, 0xb6, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x41, 0x6c, 0x69, - 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x07, - 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, - 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x65, 0x6c, - 0x6c, 0x73, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, - 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x1a, 0x50, 0x0a, 0x0c, 0x41, 0x6c, 0x69, 0x61, 0x73, + 0x16, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x78, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0d, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x23, + 0x0a, 0x0d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x73, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x56, 0x69, + 0x65, 0x77, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x73, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x74, + 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x28, 0x0a, + 0x10, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x73, 0x5f, 0x6f, 0x6e, 0x6c, + 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x69, + 0x7a, 0x65, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4f, + 0x6e, 0x6c, 0x79, 0x22, 0x50, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x18, 0x01, 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, 0x53, 0x63, 0x68, + 0x65, 0x6d, 0x61, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x73, + 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0xb8, 0x02, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, + 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 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, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x75, 0x75, 0x69, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x10, 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x12, 0x39, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x21, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x0a, 0x06, + 0x72, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, + 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, + 0x72, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, + 0x61, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, + 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x73, 0x6b, 0x69, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x73, 0x6b, 0x69, 0x70, + 0x22, 0x59, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3a, 0x0a, 0x0a, 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, + 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x0a, 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x64, 0x0a, 0x1a, 0x47, + 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x63, + 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, 0x6c, 0x6c, + 0x73, 0x22, 0x83, 0x02, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, + 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x7d, 0x0a, 0x19, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x79, 0x5f, 0x63, 0x65, 0x6c, 0x6c, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, + 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x43, + 0x65, 0x6c, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x16, 0x73, 0x68, 0x61, 0x72, 0x64, 0x52, + 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x43, 0x65, 0x6c, 0x6c, + 0x1a, 0x65, 0x0a, 0x1b, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x43, 0x65, 0x6c, 0x6c, 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, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x4c, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x53, 0x68, + 0x61, 0x72, 0x64, 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, 0x1d, 0x0a, 0x0a, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x68, 0x61, 0x72, + 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x3a, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x05, 0x73, 0x68, 0x61, + 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, + 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, + 0x64, 0x22, 0x1d, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x6f, 0x75, + 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x22, 0x6a, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x6f, 0x75, 0x74, + 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x4a, 0x0a, 0x13, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, + 0x67, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x76, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x6f, 0x75, + 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x11, 0x73, 0x68, 0x61, 0x72, 0x64, + 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x32, 0x0a, 0x1a, + 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4e, 0x61, + 0x6d, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x65, + 0x6c, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, + 0x22, 0xf3, 0x01, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x4b, 0x65, 0x79, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x47, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x31, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x53, + 0x72, 0x76, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x69, 0x0a, 0x0a, 0x4e, 0x61, 0x6d, 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, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x50, 0x0a, 0x14, 0x47, 0x65, 0x74, - 0x46, 0x75, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, - 0x73, 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, 0x0b, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0x4c, 0x0a, 0x15, 0x47, - 0x65, 0x74, 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, 0x15, 0x0a, 0x13, 0x47, 0x65, 0x74, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x45, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, + 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x4b, 0x65, 0x79, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x20, 0x0a, 0x08, 0x4e, 0x61, 0x6d, 0x65, 0x4c, 0x69, 0x73, 0x74, + 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x4a, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x22, 0x49, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x76, 0x74, - 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x52, 0x09, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x22, 0x30, 0x0a, 0x12, 0x47, - 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 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, 0x22, 0x46, 0x0a, - 0x13, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, - 0x74, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x08, 0x6b, 0x65, 0x79, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x51, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x50, 0x65, 0x72, 0x6d, - 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, - 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0x5a, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x50, - 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, - 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x50, 0x65, 0x72, 0x6d, - 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x20, 0x0a, 0x1e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x76, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x16, 0x6b, 0x65, 0x79, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x75, - 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x76, 0x73, 0x63, 0x68, - 0x65, 0x6d, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x6f, 0x75, 0x74, - 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x14, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x18, - 0x0a, 0x16, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x55, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x52, - 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x0d, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x72, - 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x76, 0x73, 0x63, - 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, - 0x73, 0x52, 0x0c, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x22, - 0xb0, 0x02, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x71, + 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, 0x14, 0x0a, 0x05, + 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, 0x6c, + 0x6c, 0x73, 0x22, 0xcc, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x4b, 0x65, 0x79, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, + 0x0a, 0x0d, 0x73, 0x72, 0x76, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, + 0x61, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x72, 0x76, 0x4b, 0x65, 0x79, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x73, 0x72, 0x76, + 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x1a, 0x56, 0x0a, 0x11, 0x53, 0x72, 0x76, + 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 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, 0x2b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x15, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x72, 0x76, 0x4b, 0x65, + 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x22, 0xe4, 0x03, 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x68, 0x72, 0x6f, + 0x74, 0x74, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 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, 0x16, + 0x0a, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, + 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 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, 0x21, + 0x0a, 0x0c, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x63, 0x75, 0x73, + 0x74, 0x6f, 0x6d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x65, 0x74, 0x12, 0x2d, 0x0a, 0x13, 0x63, + 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x61, 0x73, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x73, 0x65, + 0x6c, 0x66, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x41, + 0x73, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x6c, 0x66, 0x12, 0x2f, 0x0a, 0x14, 0x63, 0x68, + 0x65, 0x63, 0x6b, 0x5f, 0x61, 0x73, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x73, 0x68, 0x61, + 0x72, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x41, + 0x73, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x3f, 0x0a, 0x0d, 0x74, + 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x5f, 0x61, 0x70, 0x70, 0x18, 0x09, 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, 0x0c, + 0x74, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x41, 0x70, 0x70, 0x12, 0x1f, 0x0a, 0x0b, + 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, + 0x08, 0x61, 0x70, 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x61, 0x70, 0x70, 0x5f, + 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, + 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x61, 0x70, 0x70, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x65, + 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x1f, 0x0a, 0x1d, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x0a, 0x14, 0x47, 0x65, 0x74, + 0x53, 0x72, 0x76, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x65, 0x6c, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x63, 0x65, 0x6c, 0x6c, 0x22, 0x4e, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x56, + 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, + 0x0a, 0x0c, 0x73, 0x72, 0x76, 0x5f, 0x76, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x76, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x53, + 0x72, 0x76, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x0a, 0x73, 0x72, 0x76, 0x56, 0x53, + 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0x2d, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x56, + 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, + 0x0a, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x63, + 0x65, 0x6c, 0x6c, 0x73, 0x22, 0xc5, 0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x56, + 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x56, 0x0a, 0x0d, 0x73, 0x72, 0x76, 0x5f, 0x76, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, + 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x72, 0x76, 0x56, 0x53, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x73, 0x72, 0x76, 0x56, + 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x1a, 0x53, 0x0a, 0x10, 0x53, 0x72, 0x76, 0x56, 0x53, + 0x63, 0x68, 0x65, 0x6d, 0x61, 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, 0x29, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x76, + 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x53, 0x72, 0x76, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, + 0x61, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x4c, 0x0a, 0x10, + 0x47, 0x65, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, + 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, 0x0b, 0x74, + 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0x3d, 0x0a, 0x11, 0x47, 0x65, + 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x28, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x10, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, + 0x74, 0x52, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x22, 0xe8, 0x01, 0x0a, 0x11, 0x47, 0x65, + 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 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, 0x14, 0x0a, 0x05, 0x73, + 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, + 0x64, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x72, 0x69, 0x63, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x12, + 0x3c, 0x0a, 0x0e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, + 0x73, 0x18, 0x05, 0x20, 0x03, 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, 0x0d, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x12, 0x35, 0x0a, + 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, + 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, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x22, 0x40, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, + 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x07, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x6f, + 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x07, 0x74, + 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 0x22, 0x55, 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, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, + 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0x63, 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, 0x45, 0x0a, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 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, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x22, 0x5f, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, + 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, + 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x61, 0x73, + 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x61, 0x73, 0x4a, + 0x73, 0x6f, 0x6e, 0x22, 0x46, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, + 0x67, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, + 0x0a, 0x04, 0x63, 0x65, 0x6c, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x76, + 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, + 0x79, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x04, 0x63, 0x65, 0x6c, 0x6c, 0x22, 0x80, 0x01, 0x0a, 0x0c, + 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x43, 0x65, 0x6c, 0x6c, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, + 0x64, 0x72, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, + 0x64, 0x72, 0x65, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x2f, + 0x0a, 0x11, 0x47, 0x65, 0x74, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 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, 0x22, + 0x4d, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x16, - 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, - 0x65, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, - 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x23, 0x0a, - 0x0d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x73, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x56, 0x69, 0x65, - 0x77, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x73, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x28, 0x0a, 0x10, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x73, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x69, 0x7a, - 0x65, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, - 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4f, 0x6e, - 0x6c, 0x79, 0x22, 0x50, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, - 0x61, 0x18, 0x01, 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, 0x53, 0x63, 0x68, 0x65, - 0x6d, 0x61, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x73, 0x63, - 0x68, 0x65, 0x6d, 0x61, 0x22, 0xb8, 0x02, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, - 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 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, - 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, - 0x75, 0x69, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, - 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x12, 0x39, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x21, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x63, 0x68, - 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x0a, 0x06, 0x72, - 0x65, 0x63, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, - 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x72, - 0x65, 0x63, 0x65, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x05, - 0x6f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, - 0x6b, 0x69, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x73, 0x6b, 0x69, 0x70, 0x22, - 0x59, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, - 0x0a, 0x0a, 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, - 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x64, 0x0a, 0x1a, 0x47, 0x65, - 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x73, 0x52, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0x2e, + 0x0a, 0x12, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x42, + 0x0a, 0x12, 0x47, 0x65, 0x74, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x08, 0x76, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x76, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x07, 0x76, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x22, 0xc6, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x6f, 0x77, 0x73, 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, 0x1f, 0x0a, 0x0b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, + 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x63, 0x74, + 0x69, 0x76, 0x65, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x5f, + 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6e, 0x61, 0x6d, 0x65, + 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x6c, 0x6f, 0x67, 0x73, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4c, + 0x6f, 0x67, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, 0x06, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x22, 0x49, 0x0a, 0x14, 0x47, + 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, + 0x74, 0x61, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x09, 0x77, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x22, 0xfb, 0x01, 0x0a, 0x17, 0x49, 0x6e, 0x69, 0x74, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 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, 0x14, + 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, + 0x68, 0x61, 0x72, 0x64, 0x12, 0x52, 0x0a, 0x1a, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, + 0x65, 0x6c, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, + 0x61, 0x73, 0x18, 0x03, 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, + 0x17, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x54, 0x61, 0x62, + 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x44, + 0x0a, 0x15, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, + 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x13, 0x77, 0x61, 0x69, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x54, 0x69, 0x6d, + 0x65, 0x6f, 0x75, 0x74, 0x22, 0x42, 0x0a, 0x18, 0x49, 0x6e, 0x69, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x26, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x0e, 0x2e, 0x6c, 0x6f, 0x67, 0x75, 0x74, 0x69, 0x6c, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x4e, 0x0a, 0x1c, 0x4c, 0x61, 0x75, 0x6e, + 0x63, 0x68, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x65, - 0x6c, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, - 0x22, 0x83, 0x02, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x7d, 0x0a, 0x19, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x79, 0x5f, 0x63, 0x65, 0x6c, 0x6c, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, - 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x43, 0x65, - 0x6c, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x16, 0x73, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x43, 0x65, 0x6c, 0x6c, 0x1a, - 0x65, 0x0a, 0x1b, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x43, 0x65, 0x6c, 0x6c, 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, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x4c, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, - 0x72, 0x64, 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, 0x1d, 0x0a, 0x0a, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x3a, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x22, 0x1d, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x6f, 0x75, 0x74, - 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, - 0x6a, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x69, - 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x4a, 0x0a, 0x13, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, - 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x76, - 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x6f, 0x75, 0x74, - 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x11, 0x73, 0x68, 0x61, 0x72, 0x64, 0x52, - 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x32, 0x0a, 0x1a, 0x47, - 0x65, 0x74, 0x53, 0x72, 0x76, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x65, 0x6c, - 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x22, - 0xf3, 0x01, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x47, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, - 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x72, - 0x76, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x69, 0x0a, 0x0a, 0x4e, 0x61, 0x6d, 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, 0x45, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, - 0x4e, 0x61, 0x6d, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x1a, 0x20, 0x0a, 0x08, 0x4e, 0x61, 0x6d, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, - 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, - 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x4a, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x4b, - 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 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, 0x14, 0x0a, 0x05, 0x63, - 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, 0x6c, 0x6c, - 0x73, 0x22, 0xcc, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x4b, 0x65, 0x79, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, 0x0a, - 0x0d, 0x73, 0x72, 0x76, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x72, 0x76, 0x4b, 0x65, 0x79, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x73, 0x72, 0x76, 0x4b, - 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x1a, 0x56, 0x0a, 0x11, 0x53, 0x72, 0x76, 0x4b, - 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 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, - 0x2b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, - 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x72, 0x76, 0x4b, 0x65, 0x79, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x22, 0xe4, 0x03, 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x68, 0x72, 0x6f, 0x74, - 0x74, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 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, 0x16, 0x0a, - 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x65, - 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 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, 0x21, 0x0a, - 0x0c, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x12, 0x28, 0x0a, 0x10, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, - 0x5f, 0x73, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x63, 0x75, 0x73, 0x74, - 0x6f, 0x6d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x65, 0x74, 0x12, 0x2d, 0x0a, 0x13, 0x63, 0x68, - 0x65, 0x63, 0x6b, 0x5f, 0x61, 0x73, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x6c, - 0x66, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x41, 0x73, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x6c, 0x66, 0x12, 0x2f, 0x0a, 0x14, 0x63, 0x68, 0x65, - 0x63, 0x6b, 0x5f, 0x61, 0x73, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x73, 0x68, 0x61, 0x72, - 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x41, 0x73, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x3f, 0x0a, 0x0d, 0x74, 0x68, - 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x5f, 0x61, 0x70, 0x70, 0x18, 0x09, 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, 0x0c, 0x74, - 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x41, 0x70, 0x70, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, - 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, - 0x61, 0x70, 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x61, 0x70, 0x70, 0x5f, 0x63, - 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x0c, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x61, 0x70, 0x70, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, - 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x1f, 0x0a, 0x1d, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x54, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x53, - 0x72, 0x76, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x12, 0x0a, 0x04, 0x63, 0x65, 0x6c, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x63, 0x65, 0x6c, 0x6c, 0x22, 0x4e, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x56, 0x53, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, - 0x0c, 0x73, 0x72, 0x76, 0x5f, 0x76, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x76, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x53, 0x72, - 0x76, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x0a, 0x73, 0x72, 0x76, 0x56, 0x53, 0x63, - 0x68, 0x65, 0x6d, 0x61, 0x22, 0x2d, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x56, 0x53, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, - 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, - 0x6c, 0x6c, 0x73, 0x22, 0xc5, 0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x56, 0x53, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, - 0x0a, 0x0d, 0x73, 0x72, 0x76, 0x5f, 0x76, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x72, 0x76, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x72, 0x76, 0x56, 0x53, 0x63, 0x68, - 0x65, 0x6d, 0x61, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x73, 0x72, 0x76, 0x56, 0x53, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x1a, 0x53, 0x0a, 0x10, 0x53, 0x72, 0x76, 0x56, 0x53, 0x63, - 0x68, 0x65, 0x6d, 0x61, 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, 0x29, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x76, 0x73, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x53, 0x72, 0x76, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x4c, 0x0a, 0x10, 0x47, - 0x65, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0x3d, 0x0a, 0x11, 0x47, 0x65, 0x74, - 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, - 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, - 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, - 0x52, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x22, 0xe8, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74, - 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, - 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x12, 0x14, 0x0a, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x12, 0x3c, - 0x0a, 0x0e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, - 0x18, 0x05, 0x20, 0x03, 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, 0x0d, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x12, 0x35, 0x0a, 0x0b, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 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, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x54, - 0x79, 0x70, 0x65, 0x22, 0x40, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x07, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x6f, 0x70, - 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x07, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x74, 0x73, 0x22, 0x55, 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, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, - 0x61, 0x73, 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, - 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0x98, 0x0f, 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, 0x6b, 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, 0x3c, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 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, 0x68, 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, 0x3b, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 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, 0x5f, 0x0a, 0x0e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x68, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, - 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, 0x5f, 0x0a, 0x0e, 0x74, 0x68, 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x5f, 0x61, - 0x70, 0x70, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x76, 0x74, 0x63, 0x74, - 0x6c, 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, 0x6c, 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, - 0x3c, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 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, 0x56, 0x0a, 0x0b, 0x72, - 0x65, 0x63, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x70, 0x70, 0x73, 0x18, 0x12, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x35, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 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, - 0x78, 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, 0x48, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x76, 0x74, 0x63, - 0x74, 0x6c, 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, 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, 0x74, 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, 0x48, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x76, 0x74, 0x63, 0x74, - 0x6c, 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, + 0x70, 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x22, 0xdf, 0x01, 0x0a, 0x1d, 0x4c, 0x61, 0x75, + 0x6e, 0x63, 0x68, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x76, 0x0a, 0x16, 0x72, 0x6f, + 0x77, 0x73, 0x5f, 0x61, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x73, + 0x68, 0x61, 0x72, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x76, 0x74, 0x63, + 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x53, 0x63, 0x68, + 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x6f, 0x77, 0x73, 0x41, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, + 0x64, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x13, 0x72, + 0x6f, 0x77, 0x73, 0x41, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x1a, 0x46, 0x0a, 0x18, 0x52, 0x6f, 0x77, 0x73, 0x41, 0x66, 0x66, 0x65, 0x63, 0x74, + 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 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, 0x59, 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, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x1a, 0x6e, 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, 0x45, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x76, 0x74, - 0x63, 0x74, 0x6c, 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, 0x5f, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x54, 0x6f, - 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, - 0x17, 0x0a, 0x07, 0x61, 0x73, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x06, 0x61, 0x73, 0x4a, 0x73, 0x6f, 0x6e, 0x22, 0x46, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x54, - 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x04, 0x63, 0x65, 0x6c, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x17, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x6f, - 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x04, 0x63, 0x65, 0x6c, 0x6c, - 0x22, 0x80, 0x01, 0x0a, 0x0c, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x43, 0x65, 0x6c, - 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1a, 0x0a, - 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x22, 0x2f, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, - 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x73, + 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xff, 0x02, 0x0a, 0x19, 0x4c, + 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x56, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 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, 0x22, 0x4d, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, - 0x69, 0x61, 0x73, 0x22, 0x2e, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x22, 0x42, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, - 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x08, 0x76, 0x5f, 0x73, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x76, 0x73, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x07, - 0x76, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0xc6, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x57, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 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, 0x1f, 0x0a, 0x0b, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x1b, 0x0a, 0x09, - 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x08, 0x6e, 0x61, 0x6d, 0x65, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x77, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, - 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x6e, 0x63, - 0x6c, 0x75, 0x64, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, - 0x64, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, - 0x22, 0x49, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x76, 0x74, - 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, - 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x22, 0xfb, 0x01, 0x0a, 0x17, - 0x49, 0x6e, 0x69, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, - 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x52, 0x0a, 0x1a, 0x70, 0x72, 0x69, - 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, - 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x03, 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, 0x17, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x45, 0x6c, 0x65, - 0x63, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x14, 0x0a, - 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, - 0x72, 0x63, 0x65, 0x12, 0x44, 0x0a, 0x15, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x72, 0x65, 0x70, 0x6c, - 0x69, 0x63, 0x61, 0x73, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x44, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x77, 0x61, 0x69, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x73, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0x42, 0x0a, 0x18, 0x49, 0x6e, 0x69, - 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6c, 0x6f, 0x67, 0x75, 0x74, 0x69, 0x6c, 0x2e, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x4e, 0x0a, - 0x1c, 0x4c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x22, 0xdf, 0x01, - 0x0a, 0x1d, 0x4c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, - 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x76, 0x0a, 0x16, 0x72, 0x6f, 0x77, 0x73, 0x5f, 0x61, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, - 0x5f, 0x62, 0x79, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x41, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4c, 0x61, 0x75, 0x6e, - 0x63, 0x68, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x6f, 0x77, 0x73, 0x41, 0x66, - 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x13, 0x72, 0x6f, 0x77, 0x73, 0x41, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, - 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x1a, 0x46, 0x0a, 0x18, 0x52, 0x6f, 0x77, 0x73, 0x41, - 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 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, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, - 0xff, 0x02, 0x0a, 0x19, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x56, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 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, 0x14, 0x0a, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x12, 0x29, 0x0a, 0x06, 0x76, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x76, 0x73, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x06, - 0x76, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x42, 0x0a, 0x1e, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, - 0x75, 0x65, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x5f, 0x77, 0x69, - 0x74, 0x68, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, - 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x70, - 0x79, 0x57, 0x69, 0x74, 0x68, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x0c, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x06, 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, 0x07, 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, + 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, 0x14, 0x0a, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x12, 0x29, 0x0a, 0x06, 0x76, 0x69, 0x6e, 0x64, 0x65, 0x78, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x76, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x06, 0x76, 0x69, 0x6e, 0x64, 0x65, + 0x78, 0x12, 0x42, 0x0a, 0x1e, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x5f, 0x61, 0x66, + 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x6f, 0x77, + 0x6e, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x63, 0x6f, 0x6e, 0x74, 0x69, + 0x6e, 0x75, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x70, 0x79, 0x57, 0x69, 0x74, 0x68, + 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x06, 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, 0x07, 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, 0x22, 0x1c, 0x0a, 0x1a, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x56, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x77, 0x0a, 0x1e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x56, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x45, - 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 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, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x61, 0x62, 0x6c, 0x65, - 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x4c, 0x0a, 0x1f, 0x4c, 0x6f, 0x6f, 0x6b, - 0x75, 0x70, 0x56, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x69, 0x7a, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x77, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x22, 0x56, 0x0a, 0x18, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, - 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x53, 0x65, 0x74, 0x74, - 0x69, 0x6e, 0x67, 0x73, 0x52, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x1b, - 0x0a, 0x19, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xdd, 0x05, 0x0a, 0x14, - 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 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, 0x27, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x05, 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, 0x06, 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, - 0x07, 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, 0x1d, + 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, 0x22, 0x1c, 0x0a, 0x1a, + 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x56, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x77, 0x0a, 0x1e, 0x4c, 0x6f, + 0x6f, 0x6b, 0x75, 0x70, 0x56, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x69, 0x7a, 0x65, 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, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x0e, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x22, 0x4c, 0x0a, 0x1f, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x56, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x6f, 0x77, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x64, 0x22, 0x56, 0x0a, 0x18, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, + 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1e, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4d, 0x61, 0x74, 0x65, + 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, + 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x1b, 0x0a, 0x19, 0x4d, 0x61, 0x74, + 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xdd, 0x05, 0x0a, 0x14, 0x4d, 0x69, 0x67, 0x72, 0x61, + 0x74, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 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, 0x27, 0x0a, 0x0f, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6b, + 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1d, 0x0a, + 0x0a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x05, 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, 0x06, 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, 0x07, 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, 0x1d, 0x0a, 0x0a, 0x61, 0x6c, 0x6c, + 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, + 0x6c, 0x6c, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e, 0x63, 0x6c, + 0x75, 0x64, 0x65, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, + 0x25, 0x0a, 0x0e, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x7a, 0x6f, 0x6e, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x5a, 0x6f, 0x6e, 0x65, + 0x12, 0x15, 0x0a, 0x06, 0x6f, 0x6e, 0x5f, 0x64, 0x64, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x6f, 0x6e, 0x44, 0x64, 0x6c, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x74, 0x6f, 0x70, 0x5f, + 0x61, 0x66, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0d, 0x73, 0x74, 0x6f, 0x70, 0x41, 0x66, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x70, 0x79, 0x12, + 0x2a, 0x0a, 0x11, 0x64, 0x72, 0x6f, 0x70, 0x5f, 0x66, 0x6f, 0x72, 0x65, 0x69, 0x67, 0x6e, 0x5f, + 0x6b, 0x65, 0x79, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x72, 0x6f, 0x70, + 0x46, 0x6f, 0x72, 0x65, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x73, 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, 0x0f, 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, 0x10, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x09, 0x61, 0x75, 0x74, 0x6f, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x28, 0x0a, 0x10, + 0x6e, 0x6f, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, + 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x6e, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, + 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x22, 0xe6, 0x01, 0x0a, 0x16, 0x4d, 0x69, 0x67, 0x72, 0x61, + 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 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, 0x27, 0x0a, + 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4b, 0x65, + 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x64, + 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6b, 0x65, 0x65, 0x70, 0x44, + 0x61, 0x74, 0x61, 0x12, 0x2c, 0x0a, 0x12, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, + 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x10, 0x6b, 0x65, 0x65, 0x70, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, + 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x61, 0x62, 0x6c, + 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, + 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, + 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x22, + 0x5b, 0x0a, 0x17, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, + 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, + 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x6d, + 0x6d, 0x61, 0x72, 0x79, 0x12, 0x26, 0x0a, 0x0f, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x5f, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x64, + 0x72, 0x79, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0x85, 0x01, 0x0a, + 0x14, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x6f, 0x70, 0x6f, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x6f, 0x70, 0x6f, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x70, 0x6f, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x6f, 0x70, 0x6f, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x6f, 0x70, 0x6f, 0x5f, 0x72, 0x6f, 0x6f, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x6f, 0x70, 0x6f, 0x52, 0x6f, 0x6f, 0x74, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x17, 0x0a, 0x15, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x0a, + 0x16, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x19, 0x0a, 0x17, 0x4d, + 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x0a, 0x10, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x53, + 0x68, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x82, + 0x01, 0x0a, 0x11, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x68, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x6f, 0x70, 0x6f, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x6f, 0x70, 0x6f, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x70, 0x6f, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x6f, 0x70, 0x6f, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x6f, 0x70, 0x6f, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x6f, 0x70, 0x6f, 0x52, 0x6f, 0x6f, 0x74, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x22, 0x12, 0x0a, 0x10, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x29, 0x0a, 0x11, 0x4d, 0x6f, 0x75, 0x6e, 0x74, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x61, 0x6d, + 0x65, 0x73, 0x22, 0x82, 0x07, 0x0a, 0x17, 0x4d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, + 0x73, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 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, 0x27, 0x0a, 0x0f, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6b, 0x65, + 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x04, 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, 0x05, 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, 0x06, 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, 0x23, 0x0a, 0x0d, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x6c, 0x6c, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x6c, 0x6c, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x78, - 0x63, 0x6c, 0x75, 0x64, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x7a, 0x6f, 0x6e, 0x65, 0x18, - 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x69, 0x6d, - 0x65, 0x5a, 0x6f, 0x6e, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x6f, 0x6e, 0x5f, 0x64, 0x64, 0x6c, 0x18, - 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x6e, 0x44, 0x64, 0x6c, 0x12, 0x26, 0x0a, 0x0f, - 0x73, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x18, - 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x73, 0x74, 0x6f, 0x70, 0x41, 0x66, 0x74, 0x65, 0x72, - 0x43, 0x6f, 0x70, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x64, 0x72, 0x6f, 0x70, 0x5f, 0x66, 0x6f, 0x72, - 0x65, 0x69, 0x67, 0x6e, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0f, 0x64, 0x72, 0x6f, 0x70, 0x46, 0x6f, 0x72, 0x65, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x73, - 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, 0x0f, 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, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x75, 0x74, 0x6f, 0x53, 0x74, 0x61, 0x72, - 0x74, 0x12, 0x28, 0x0a, 0x10, 0x6e, 0x6f, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, - 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x6e, 0x6f, 0x52, - 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x22, 0xe6, 0x01, 0x0a, 0x16, - 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 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, 0x27, 0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6b, 0x65, 0x79, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6b, - 0x65, 0x65, 0x70, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, - 0x6b, 0x65, 0x65, 0x70, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2c, 0x0a, 0x12, 0x6b, 0x65, 0x65, 0x70, - 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x6b, 0x65, 0x65, 0x70, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, - 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, - 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x72, - 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x64, - 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, - 0x79, 0x52, 0x75, 0x6e, 0x22, 0x5b, 0x0a, 0x17, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x43, - 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x18, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x26, 0x0a, 0x0f, 0x64, 0x72, 0x79, - 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x0d, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x73, 0x22, 0x85, 0x01, 0x0a, 0x14, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x6f, - 0x70, 0x6f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, - 0x6f, 0x70, 0x6f, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x70, 0x6f, 0x5f, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x6f, - 0x70, 0x6f, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x6f, 0x70, 0x6f, - 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x6f, 0x70, - 0x6f, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x17, 0x0a, 0x15, 0x4d, 0x6f, 0x75, - 0x6e, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x2c, 0x0a, 0x16, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x6e, 0x72, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x22, 0x19, 0x0a, 0x17, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x0a, 0x10, 0x4d, - 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x68, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x22, 0x82, 0x01, 0x0a, 0x11, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x68, 0x6f, - 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x6f, 0x70, - 0x6f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x6f, - 0x70, 0x6f, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x70, 0x6f, 0x5f, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x6f, 0x70, - 0x6f, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x6f, 0x70, 0x6f, 0x5f, - 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x6f, 0x70, 0x6f, - 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x12, 0x0a, 0x10, 0x4d, 0x6f, 0x75, 0x6e, - 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x29, 0x0a, 0x11, - 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x82, 0x07, 0x0a, 0x17, 0x4d, 0x6f, 0x76, 0x65, - 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 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, - 0x27, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x04, 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, 0x05, 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, - 0x06, 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, 0x23, - 0x0a, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, - 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x6c, 0x6c, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, - 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x6c, 0x6c, 0x54, 0x61, 0x62, 0x6c, - 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x69, 0x6e, 0x63, 0x6c, - 0x75, 0x64, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x78, 0x63, - 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0d, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, - 0x12, 0x32, 0x0a, 0x15, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x63, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x13, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, - 0x69, 0x6d, 0x65, 0x5f, 0x7a, 0x6f, 0x6e, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x5a, 0x6f, 0x6e, 0x65, 0x12, 0x15, - 0x0a, 0x06, 0x6f, 0x6e, 0x5f, 0x64, 0x64, 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x6f, 0x6e, 0x44, 0x64, 0x6c, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x66, - 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, - 0x73, 0x74, 0x6f, 0x70, 0x41, 0x66, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x70, 0x79, 0x12, 0x2a, 0x0a, - 0x11, 0x64, 0x72, 0x6f, 0x70, 0x5f, 0x66, 0x6f, 0x72, 0x65, 0x69, 0x67, 0x6e, 0x5f, 0x6b, 0x65, - 0x79, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x72, 0x6f, 0x70, 0x46, 0x6f, - 0x72, 0x65, 0x69, 0x67, 0x6e, 0x4b, 0x65, 0x79, 0x73, 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, 0x10, 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, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x09, 0x61, 0x75, 0x74, 0x6f, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x6e, 0x6f, - 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x12, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x6e, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, - 0x75, 0x6c, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x74, 0x6f, 0x6d, 0x69, 0x63, 0x5f, 0x63, - 0x6f, 0x70, 0x79, 0x18, 0x13, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x74, 0x6f, 0x6d, 0x69, - 0x63, 0x43, 0x6f, 0x70, 0x79, 0x12, 0x45, 0x0a, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, - 0x77, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x57, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0f, 0x77, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xd5, 0x01, 0x0a, - 0x18, 0x4d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x6d, - 0x6d, 0x61, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, - 0x61, 0x72, 0x79, 0x12, 0x48, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x4d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, - 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x1a, 0x55, 0x0a, - 0x0a, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2d, 0x0a, 0x06, 0x74, - 0x61, 0x62, 0x6c, 0x65, 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, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x63, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x64, 0x22, 0x81, 0x02, 0x0a, 0x19, 0x4d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x62, - 0x6c, 0x65, 0x73, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 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, 0x27, - 0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4b, - 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x5f, - 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6b, 0x65, 0x65, 0x70, - 0x44, 0x61, 0x74, 0x61, 0x12, 0x2c, 0x0a, 0x12, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x72, 0x6f, 0x75, - 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x10, 0x6b, 0x65, 0x65, 0x70, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, - 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x72, 0x65, 0x6e, 0x61, 0x6d, - 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, - 0x75, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, - 0x12, 0x16, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x22, 0x5e, 0x0a, 0x1a, 0x4d, 0x6f, 0x76, 0x65, - 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, - 0x12, 0x26, 0x0a, 0x0f, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x72, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x72, 0x79, 0x52, 0x75, - 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0x4d, 0x0a, 0x11, 0x50, 0x69, 0x6e, 0x67, - 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, - 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, - 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0x14, 0x0a, 0x12, 0x50, 0x69, 0x6e, 0x67, 0x54, - 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xd7, 0x02, - 0x0a, 0x1b, 0x50, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x52, 0x65, 0x70, 0x61, 0x72, 0x65, 0x6e, - 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, - 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, - 0x36, 0x0a, 0x0b, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x03, - 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, 0x0a, 0x6e, 0x65, 0x77, - 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x3a, 0x0a, 0x0d, 0x61, 0x76, 0x6f, 0x69, 0x64, - 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, + 0x63, 0x6c, 0x75, 0x64, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x65, + 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x65, 0x78, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x28, 0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x7a, + 0x6f, 0x6e, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x54, 0x69, 0x6d, 0x65, 0x5a, 0x6f, 0x6e, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x6f, 0x6e, 0x5f, + 0x64, 0x64, 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x6e, 0x44, 0x64, 0x6c, + 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x5f, 0x63, + 0x6f, 0x70, 0x79, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x73, 0x74, 0x6f, 0x70, 0x41, + 0x66, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x70, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x64, 0x72, 0x6f, 0x70, + 0x5f, 0x66, 0x6f, 0x72, 0x65, 0x69, 0x67, 0x6e, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x0f, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x72, 0x6f, 0x70, 0x46, 0x6f, 0x72, 0x65, 0x69, 0x67, 0x6e, + 0x4b, 0x65, 0x79, 0x73, 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, 0x10, 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, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x75, 0x74, 0x6f, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x6e, 0x6f, 0x5f, 0x72, 0x6f, 0x75, 0x74, + 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0e, 0x6e, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, + 0x1f, 0x0a, 0x0b, 0x61, 0x74, 0x6f, 0x6d, 0x69, 0x63, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x18, 0x13, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x74, 0x6f, 0x6d, 0x69, 0x63, 0x43, 0x6f, 0x70, 0x79, + 0x12, 0x45, 0x0a, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x6f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x76, 0x74, 0x63, + 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xd5, 0x01, 0x0a, 0x18, 0x4d, 0x6f, 0x76, 0x65, + 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x48, + 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x2e, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4d, 0x6f, 0x76, 0x65, + 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x1a, 0x55, 0x0a, 0x0a, 0x54, 0x61, 0x62, 0x6c, + 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2d, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 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, 0x74, + 0x61, 0x62, 0x6c, 0x65, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x22, + 0x81, 0x02, 0x0a, 0x19, 0x4d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x43, 0x6f, + 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 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, 0x27, 0x0a, 0x0f, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6b, 0x65, 0x65, 0x70, 0x44, 0x61, 0x74, 0x61, 0x12, + 0x2c, 0x0a, 0x12, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, + 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x6b, 0x65, 0x65, + 0x70, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x23, 0x0a, + 0x0d, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x54, 0x61, 0x62, 0x6c, + 0x65, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, + 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x68, 0x61, + 0x72, 0x64, 0x73, 0x22, 0x5e, 0x0a, 0x1a, 0x4d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, + 0x73, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x26, 0x0a, 0x0f, 0x64, + 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x73, 0x22, 0x4d, 0x0a, 0x11, 0x50, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, + 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0c, 0x61, 0x76, 0x6f, 0x69, 0x64, 0x50, 0x72, 0x69, 0x6d, - 0x61, 0x72, 0x79, 0x12, 0x44, 0x0a, 0x15, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x72, 0x65, 0x70, 0x6c, - 0x69, 0x63, 0x61, 0x73, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x44, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x77, 0x61, 0x69, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x73, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x4c, 0x0a, 0x19, 0x74, 0x6f, 0x6c, - 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x6c, 0x61, 0x67, 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, 0x17, - 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x61, 0x67, 0x22, 0xba, 0x01, 0x0a, 0x1c, 0x50, 0x6c, 0x61, 0x6e, - 0x6e, 0x65, 0x64, 0x52, 0x65, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x40, 0x0a, 0x10, 0x70, 0x72, - 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x03, - 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, 0x0f, 0x70, 0x72, 0x6f, - 0x6d, 0x6f, 0x74, 0x65, 0x64, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x26, 0x0a, 0x06, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6c, - 0x6f, 0x67, 0x75, 0x74, 0x69, 0x6c, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x73, 0x22, 0x74, 0x0a, 0x1b, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x4b, - 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, + 0x41, 0x6c, 0x69, 0x61, 0x73, 0x52, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, + 0x61, 0x73, 0x22, 0x14, 0x0a, 0x12, 0x50, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xd7, 0x02, 0x0a, 0x1b, 0x50, 0x6c, 0x61, + 0x6e, 0x6e, 0x65, 0x64, 0x52, 0x65, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x64, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x36, 0x0a, 0x0b, 0x6e, 0x65, + 0x77, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x03, 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, 0x0a, 0x6e, 0x65, 0x77, 0x50, 0x72, 0x69, 0x6d, 0x61, + 0x72, 0x79, 0x12, 0x3a, 0x0a, 0x0d, 0x61, 0x76, 0x6f, 0x69, 0x64, 0x5f, 0x70, 0x72, 0x69, 0x6d, + 0x61, 0x72, 0x79, 0x18, 0x04, 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, 0x0c, 0x61, 0x76, 0x6f, 0x69, 0x64, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x44, + 0x0a, 0x15, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, + 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x13, 0x77, 0x61, 0x69, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x54, 0x69, 0x6d, + 0x65, 0x6f, 0x75, 0x74, 0x12, 0x4c, 0x0a, 0x19, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x62, 0x6c, + 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x61, + 0x67, 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, 0x17, 0x74, 0x6f, 0x6c, 0x65, 0x72, + 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, + 0x61, 0x67, 0x22, 0xba, 0x01, 0x0a, 0x1c, 0x50, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x52, 0x65, + 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 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, - 0x14, 0x0a, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, - 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x70, - 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x61, 0x6c, - 0x6c, 0x6f, 0x77, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x1e, 0x0a, 0x1c, 0x52, 0x65, - 0x62, 0x75, 0x69, 0x6c, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x47, 0x72, 0x61, - 0x70, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x32, 0x0a, 0x1a, 0x52, 0x65, - 0x62, 0x75, 0x69, 0x6c, 0x64, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x47, 0x72, 0x61, 0x70, - 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x65, 0x6c, 0x6c, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x22, 0x1d, - 0x0a, 0x1b, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, - 0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4f, 0x0a, - 0x13, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, + 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x40, 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, + 0x64, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x03, 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, 0x0f, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x64, + 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x26, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6c, 0x6f, 0x67, 0x75, 0x74, 0x69, + 0x6c, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, + 0x74, 0x0a, 0x1b, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x47, 0x72, 0x61, 0x70, 0x68, 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, 0x14, 0x0a, 0x05, 0x63, 0x65, + 0x6c, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, + 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, + 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x50, 0x61, + 0x72, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x1e, 0x0a, 0x1c, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, + 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x32, 0x0a, 0x1a, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, + 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x22, 0x1d, 0x0a, 0x1b, 0x52, 0x65, 0x62, + 0x75, 0x69, 0x6c, 0x64, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x47, 0x72, 0x61, 0x70, 0x68, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4f, 0x0a, 0x13, 0x52, 0x65, 0x66, 0x72, + 0x65, 0x73, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0x16, 0x0a, 0x14, 0x52, 0x65, 0x66, + 0x72, 0x65, 0x73, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x64, 0x0a, 0x1a, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 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, 0x14, 0x0a, 0x05, 0x73, + 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, + 0x64, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x22, 0x83, 0x01, 0x0a, 0x1b, 0x52, 0x65, 0x66, 0x72, + 0x65, 0x73, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x69, 0x73, 0x5f, 0x70, 0x61, + 0x72, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x10, 0x69, 0x73, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, + 0x66, 0x72, 0x65, 0x73, 0x68, 0x12, 0x36, 0x0a, 0x17, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, + 0x5f, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x52, + 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x4f, 0x0a, + 0x13, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0x16, - 0x0a, 0x14, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x64, 0x0a, 0x1a, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, - 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, - 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x22, 0x83, 0x01, 0x0a, - 0x1b, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x42, 0x79, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x12, - 0x69, 0x73, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x66, 0x72, 0x65, - 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x69, 0x73, 0x50, 0x61, 0x72, 0x74, - 0x69, 0x61, 0x6c, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x12, 0x36, 0x0a, 0x17, 0x70, 0x61, - 0x72, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, 0x64, 0x65, - 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x70, 0x61, 0x72, - 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x44, 0x65, 0x74, 0x61, 0x69, - 0x6c, 0x73, 0x22, 0x4f, 0x0a, 0x13, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, - 0x6d, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, - 0x69, 0x61, 0x73, 0x22, 0x16, 0x0a, 0x14, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, - 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa9, 0x01, 0x0a, 0x1b, - 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4b, 0x65, 0x79, 0x73, - 0x70, 0x61, 0x63, 0x65, 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, 0x23, 0x0a, 0x0d, 0x77, 0x61, 0x69, 0x74, 0x5f, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x77, 0x61, 0x69, 0x74, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, - 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x72, - 0x69, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x63, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, - 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x46, 0x0a, 0x1c, 0x52, 0x65, 0x6c, 0x6f, 0x61, + 0x0a, 0x14, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa9, 0x01, 0x0a, 0x1b, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6c, 0x6f, 0x67, 0x75, 0x74, 0x69, - 0x6c, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, - 0xbc, 0x01, 0x0a, 0x18, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, - 0x53, 0x68, 0x61, 0x72, 0x64, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x23, - 0x0a, 0x0d, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x77, 0x61, 0x69, 0x74, 0x50, 0x6f, 0x73, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x70, - 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, 0x6e, - 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x20, 0x0a, 0x0b, - 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x43, - 0x0a, 0x19, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6c, 0x6f, - 0x67, 0x75, 0x74, 0x69, 0x6c, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x73, 0x22, 0x5b, 0x0a, 0x13, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x42, 0x61, 0x63, - 0x6b, 0x75, 0x70, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x22, 0x16, 0x0a, 0x14, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x7f, 0x0a, 0x19, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x65, + 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, 0x23, 0x0a, 0x0d, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x77, 0x61, 0x69, 0x74, 0x50, + 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, + 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, + 0x63, 0x79, 0x22, 0x46, 0x0a, 0x1c, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6c, 0x6f, 0x67, 0x75, 0x74, 0x69, 0x6c, 0x2e, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xbc, 0x01, 0x0a, 0x18, 0x52, + 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x53, 0x68, 0x61, 0x72, 0x64, + 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x77, 0x61, 0x69, + 0x74, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x77, 0x61, 0x69, 0x74, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, + 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, + 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x63, 0x6f, + 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x43, 0x0a, 0x19, 0x52, 0x65, 0x6c, + 0x6f, 0x61, 0x64, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6c, 0x6f, 0x67, 0x75, 0x74, 0x69, 0x6c, + 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x5b, + 0x0a, 0x13, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 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, 0x12, 0x0a, 0x04, 0x63, 0x65, 0x6c, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x63, 0x65, 0x6c, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x72, - 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, - 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x22, 0x1c, 0x0a, 0x1a, 0x52, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x9b, 0x01, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x43, 0x65, 0x6c, 0x6c, 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, 0x1d, - 0x0a, 0x0a, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x73, 0x68, 0x61, 0x72, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x63, 0x65, 0x6c, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x65, 0x6c, - 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, - 0x73, 0x69, 0x76, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x65, 0x63, 0x75, - 0x72, 0x73, 0x69, 0x76, 0x65, 0x22, 0x19, 0x0a, 0x17, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x46, 0x0a, 0x15, 0x52, 0x65, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x54, 0x61, 0x62, 0x6c, - 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x06, 0x74, 0x61, 0x62, - 0x6c, 0x65, 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, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x22, 0x7b, 0x0a, 0x16, 0x52, 0x65, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 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, 0x14, - 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, - 0x68, 0x61, 0x72, 0x64, 0x12, 0x2f, 0x0a, 0x07, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, - 0x03, 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, 0x07, 0x70, 0x72, - 0x69, 0x6d, 0x61, 0x72, 0x79, 0x22, 0x8f, 0x04, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x68, 0x61, 0x72, - 0x64, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 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, 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, 0x23, 0x0a, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, - 0x12, 0x14, 0x0a, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x05, 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, 0x06, 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, 0x07, - 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, 0x28, 0x0a, - 0x10, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x63, 0x6f, 0x70, - 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x73, 0x6b, 0x69, 0x70, 0x53, 0x63, 0x68, - 0x65, 0x6d, 0x61, 0x43, 0x6f, 0x70, 0x79, 0x12, 0x15, 0x0a, 0x06, 0x6f, 0x6e, 0x5f, 0x64, 0x64, - 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x6e, 0x44, 0x64, 0x6c, 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, 0x30, 0x0a, 0x14, 0x64, 0x65, 0x66, 0x65, 0x72, 0x5f, - 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x0b, - 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, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x75, - 0x74, 0x6f, 0x53, 0x74, 0x61, 0x72, 0x74, 0x22, 0x82, 0x02, 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, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, - 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x2d, - 0x0a, 0x0b, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 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, - 0x03, 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, 0x04, - 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, 0x05, 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, 0x22, 0xad, 0x01, 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, 0x38, 0x0a, 0x0c, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 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, 0x24, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, - 0x04, 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, 0x4d, 0x0a, 0x1b, - 0x52, 0x65, 0x74, 0x72, 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 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, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x22, 0xdd, 0x01, 0x0a, 0x1c, - 0x52, 0x65, 0x74, 0x72, 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x75, 0x0a, 0x16, - 0x72, 0x6f, 0x77, 0x73, 0x5f, 0x61, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, - 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x76, - 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x53, 0x63, - 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x6f, 0x77, 0x73, 0x41, 0x66, 0x66, 0x65, 0x63, 0x74, - 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x13, - 0x72, 0x6f, 0x77, 0x73, 0x41, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x1a, 0x46, 0x0a, 0x18, 0x52, 0x6f, 0x77, 0x73, 0x41, 0x66, 0x66, 0x65, 0x63, - 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 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, 0x04, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x51, 0x0a, 0x15, 0x52, - 0x75, 0x6e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, - 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0x18, - 0x0a, 0x16, 0x52, 0x75, 0x6e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6d, 0x0a, 0x22, 0x53, 0x65, 0x74, 0x4b, - 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x44, 0x75, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, - 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 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, 0x2b, 0x0a, 0x11, 0x64, 0x75, - 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x64, 0x75, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, - 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x55, 0x0a, 0x23, 0x53, 0x65, 0x74, 0x4b, 0x65, - 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x44, 0x75, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, - 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x5e, - 0x0a, 0x1e, 0x53, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x16, 0x0a, 0x14, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x7f, 0x0a, 0x19, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x65, 0x6c, 0x6c, 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, 0x14, 0x0a, 0x05, + 0x28, 0x09, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, + 0x63, 0x65, 0x6c, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x65, 0x6c, 0x6c, + 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, + 0x69, 0x76, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, + 0x73, 0x69, 0x76, 0x65, 0x22, 0x1c, 0x0a, 0x1a, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, + 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x9b, 0x01, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x43, 0x65, 0x6c, 0x6c, 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, 0x1d, 0x0a, 0x0a, 0x73, 0x68, 0x61, + 0x72, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, + 0x68, 0x61, 0x72, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x65, 0x6c, 0x6c, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x65, 0x6c, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, - 0x63, 0x65, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x22, 0x51, - 0x0a, 0x1f, 0x53, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x2e, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4b, - 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x22, 0x72, 0x0a, 0x1f, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x49, 0x73, 0x50, - 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x6e, 0x67, 0x22, 0x49, 0x0a, 0x20, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x49, 0x73, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, - 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x05, 0x73, 0x68, 0x61, - 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x22, 0x8e, 0x02, 0x0a, 0x1c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x54, 0x61, 0x62, - 0x6c, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 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, 0x14, 0x0a, - 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, - 0x61, 0x72, 0x64, 0x12, 0x35, 0x0a, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 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, 0x0a, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x65, - 0x6c, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, - 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, - 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x54, - 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, - 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x22, 0x46, 0x0a, 0x1d, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x54, 0x61, 0x62, - 0x6c, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x25, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x22, 0x6a, 0x0a, 0x12, 0x53, 0x65, 0x74, - 0x57, 0x72, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, + 0x22, 0x19, 0x0a, 0x17, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x43, + 0x65, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x46, 0x0a, 0x15, 0x52, + 0x65, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 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, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x74, 0x22, 0x7b, 0x0a, 0x16, 0x52, 0x65, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x54, + 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, + 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, + 0x2f, 0x0a, 0x07, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x03, 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, 0x07, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, + 0x22, 0x8f, 0x04, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x68, 0x61, 0x72, 0x64, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 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, 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, 0x23, 0x0a, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x68, 0x61, 0x72, + 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, + 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x05, 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, 0x06, 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, 0x07, 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, 0x28, 0x0a, 0x10, 0x73, 0x6b, 0x69, 0x70, + 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0e, 0x73, 0x6b, 0x69, 0x70, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x43, 0x6f, + 0x70, 0x79, 0x12, 0x15, 0x0a, 0x06, 0x6f, 0x6e, 0x5f, 0x64, 0x64, 0x6c, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x6f, 0x6e, 0x44, 0x64, 0x6c, 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, 0x30, 0x0a, 0x14, 0x64, 0x65, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, + 0x64, 0x61, 0x72, 0x79, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x0b, 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, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x75, 0x74, 0x6f, 0x53, 0x74, 0x61, + 0x72, 0x74, 0x22, 0x82, 0x02, 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, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x77, 0x72, 0x69, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x77, 0x72, 0x69, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x15, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x57, 0x72, 0x69, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x88, 0x01, 0x0a, - 0x1a, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x41, 0x64, 0x64, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x38, 0x0a, - 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x03, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, - 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0x1d, 0x0a, 0x1b, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x64, 0x64, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x62, 0x0a, 0x1a, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, - 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x78, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x65, 0x6c, 0x6c, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x65, 0x6c, 0x6c, 0x22, 0x54, 0x0a, 0x1b, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, - 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x05, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x22, 0x54, 0x0a, 0x20, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x22, 0xaa, 0x03, 0x0a, 0x21, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x73, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x78, 0x0a, 0x14, - 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x76, 0x74, 0x63, - 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x13, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x12, 0x5a, 0x0a, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, - 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x76, 0x74, 0x63, - 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x4d, - 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x4d, - 0x61, 0x70, 0x1a, 0x5f, 0x0a, 0x18, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 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, 0x2d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x17, 0x2e, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x1a, 0x4e, 0x0a, 0x0e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x4d, 0x61, 0x70, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x22, 0x8b, 0x01, 0x0a, 0x1d, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, - 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x03, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, - 0x73, 0x22, 0x20, 0x0a, 0x1e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x7c, 0x0a, 0x12, 0x53, 0x6c, 0x65, 0x65, 0x70, 0x54, 0x61, 0x62, 0x6c, - 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, - 0x69, 0x61, 0x73, 0x12, 0x2c, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x44, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x22, 0x15, 0x0a, 0x13, 0x53, 0x6c, 0x65, 0x65, 0x70, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xf0, 0x01, 0x0a, 0x15, 0x53, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x41, 0x64, 0x64, 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, 0x14, - 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, - 0x68, 0x61, 0x72, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, - 0x21, 0x0a, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x12, 0x2f, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x52, 0x61, - 0x6e, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x07, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x22, 0x3f, 0x0a, 0x16, 0x53, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x22, 0x5e, 0x0a, 0x18, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x75, 0x69, 0x64, 0x22, 0x42, 0x0a, 0x19, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x05, 0x73, 0x68, 0x61, - 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x22, 0x53, 0x0a, 0x17, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0c, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, - 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0x1a, 0x0a, 0x18, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x52, 0x0a, 0x16, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0c, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, - 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0x19, 0x0a, 0x17, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x52, 0x0a, 0x21, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x6c, 0x79, 0x52, 0x65, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x18, + 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x2d, 0x0a, 0x0b, 0x62, 0x61, 0x63, + 0x6b, 0x75, 0x70, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 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, 0x03, 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, 0x04, 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, + 0x05, 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, 0x22, 0xad, 0x01, 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, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, + 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 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, 0x24, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x04, 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, 0x4d, 0x0a, 0x1b, 0x52, 0x65, 0x74, 0x72, 0x79, + 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x22, 0xdd, 0x01, 0x0a, 0x1c, 0x52, 0x65, 0x74, 0x72, 0x79, + 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x75, 0x0a, 0x16, 0x72, 0x6f, 0x77, 0x73, 0x5f, + 0x61, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x73, 0x68, 0x61, 0x72, + 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, + 0x61, 0x74, 0x61, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4d, + 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x52, 0x6f, 0x77, 0x73, 0x41, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x13, 0x72, 0x6f, 0x77, 0x73, 0x41, + 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x1a, 0x46, + 0x0a, 0x18, 0x52, 0x6f, 0x77, 0x73, 0x41, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x42, 0x79, + 0x53, 0x68, 0x61, 0x72, 0x64, 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, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x51, 0x0a, 0x15, 0x52, 0x75, 0x6e, 0x48, 0x65, 0x61, + 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x74, 0x22, 0xc6, 0x01, 0x0a, 0x22, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x45, - 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x52, 0x65, 0x70, 0x61, 0x72, 0x65, 0x6e, - 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6b, + 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x52, 0x0b, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0x18, 0x0a, 0x16, 0x52, 0x75, 0x6e, + 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x6d, 0x0a, 0x22, 0x53, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x44, 0x75, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 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, 0x2b, 0x0a, 0x11, 0x64, 0x75, 0x72, 0x61, 0x62, 0x69, 0x6c, + 0x69, 0x74, 0x79, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x10, 0x64, 0x75, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x22, 0x55, 0x0a, 0x23, 0x53, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x44, 0x75, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x08, 0x6b, 0x65, 0x79, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x6f, + 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, + 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x5e, 0x0a, 0x1e, 0x53, 0x65, 0x74, + 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, + 0x49, 0x6e, 0x66, 0x6f, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x36, 0x0a, - 0x0b, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x03, 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, 0x0a, 0x6e, 0x65, 0x77, 0x50, 0x72, - 0x69, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x36, 0x0a, 0x0b, 0x6f, 0x6c, 0x64, 0x5f, 0x70, 0x72, 0x69, - 0x6d, 0x61, 0x72, 0x79, 0x18, 0x04, 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, 0x0a, 0x6f, 0x6c, 0x64, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x22, 0x5c, 0x0a, - 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x63, 0x65, - 0x6c, 0x6c, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, - 0x6f, 0x52, 0x08, 0x63, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x5d, 0x0a, 0x16, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x63, 0x65, 0x6c, - 0x6c, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, - 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, - 0x52, 0x08, 0x63, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x64, 0x0a, 0x17, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x0b, 0x63, 0x65, 0x6c, - 0x6c, 0x73, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, - 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x41, - 0x6c, 0x69, 0x61, 0x73, 0x52, 0x0a, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x41, 0x6c, 0x69, 0x61, 0x73, - 0x22, 0x65, 0x0a, 0x18, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x41, - 0x6c, 0x69, 0x61, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x35, 0x0a, 0x0b, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x52, 0x0a, 0x63, 0x65, 0x6c, - 0x6c, 0x73, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0x34, 0x0a, 0x0f, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x69, - 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0b, 0x70, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 0x22, 0xfb, 0x01, - 0x0a, 0x10, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x62, 0x0a, 0x13, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x76, 0x74, 0x63, 0x74, - 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x42, 0x79, - 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x42, 0x79, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x1a, 0x69, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x42, 0x79, 0x4b, 0x65, 0x79, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x39, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x76, 0x74, - 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, - 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x58, 0x0a, 0x17, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, + 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x4a, 0x04, 0x08, + 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x22, 0x51, 0x0a, 0x1f, 0x53, 0x65, 0x74, + 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, + 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x08, + 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x72, 0x0a, 0x1f, + 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x49, 0x73, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, + 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 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, 0x14, 0x0a, 0x05, 0x73, + 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, + 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, + 0x22, 0x49, 0x0a, 0x20, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x49, 0x73, 0x50, 0x72, + 0x69, 0x6d, 0x61, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x22, 0x8e, 0x02, 0x0a, 0x1c, + 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x43, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x35, + 0x0a, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, + 0x01, 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, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x04, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x64, + 0x65, 0x6e, 0x69, 0x65, 0x64, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, + 0x12, 0x32, 0x0a, 0x15, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x13, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x22, 0x46, 0x0a, 0x1d, + 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x43, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, + 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, + 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x05, 0x73, + 0x68, 0x61, 0x72, 0x64, 0x22, 0x6a, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x57, 0x72, 0x69, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, + 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x77, 0x72, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x77, 0x72, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x22, 0x15, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x57, 0x72, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x88, 0x01, 0x0a, 0x1a, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x64, 0x64, 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, 0x21, 0x0a, 0x0c, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, - 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x70, 0x69, 0x6e, 0x67, 0x54, 0x61, - 0x62, 0x6c, 0x65, 0x74, 0x73, 0x22, 0xfc, 0x01, 0x0a, 0x18, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x61, 0x0a, 0x10, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, - 0x74, 0x61, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x73, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x0e, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x1a, - 0x63, 0x0a, 0x13, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x22, 0xd8, 0x01, 0x0a, 0x1d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, + 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x03, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, + 0x61, 0x73, 0x22, 0x1d, 0x0a, 0x1b, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x62, 0x0a, 0x1a, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x78, 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, 0x14, 0x0a, 0x05, 0x73, + 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, + 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x65, 0x6c, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x63, 0x65, 0x6c, 0x6c, 0x22, 0x54, 0x0a, 0x1b, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, + 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x78, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, + 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x54, 0x0a, 0x20, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, + 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 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, 0x14, 0x0a, 0x05, 0x73, + 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, + 0x64, 0x22, 0xaa, 0x03, 0x0a, 0x21, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x78, 0x0a, 0x14, 0x72, 0x65, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, + 0x61, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x13, 0x72, 0x65, + 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, + 0x73, 0x12, 0x5a, 0x0a, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x6d, 0x61, 0x70, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, + 0x61, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x4d, 0x61, 0x70, 0x1a, 0x5f, 0x0a, + 0x18, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 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, 0x2d, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x72, 0x65, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x4e, + 0x0a, 0x0e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x26, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, 0x62, + 0x6c, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x8b, + 0x01, 0x0a, 0x1d, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 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, 0x14, 0x0a, 0x05, + 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, + 0x72, 0x64, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, + 0x61, 0x73, 0x18, 0x03, 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, + 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0x20, 0x0a, 0x1e, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x7c, + 0x0a, 0x12, 0x53, 0x6c, 0x65, 0x65, 0x70, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x61, + 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x2c, + 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x10, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x15, 0x0a, 0x13, + 0x53, 0x6c, 0x65, 0x65, 0x70, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0xf0, 0x01, 0x0a, 0x15, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x41, 0x64, 0x64, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, + 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, + 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x75, 0x69, + 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x2f, 0x0a, + 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4b, 0x65, 0x79, 0x52, + 0x61, 0x6e, 0x67, 0x65, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x16, + 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x22, 0x3f, 0x0a, 0x16, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x25, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0f, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x22, 0x5e, 0x0a, 0x18, 0x53, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 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, + 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x03, 0x75, 0x69, 0x64, 0x22, 0x42, 0x0a, 0x19, 0x53, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x22, 0x53, 0x0a, 0x17, 0x53, + 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, + 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, + 0x22, 0x1a, 0x0a, 0x18, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x52, 0x0a, 0x16, + 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, + 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 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, 0x0b, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, + 0x22, 0x19, 0x0a, 0x17, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x52, 0x0a, 0x21, 0x54, + 0x61, 0x62, 0x6c, 0x65, 0x74, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x52, + 0x65, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x2d, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 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, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x22, + 0xc6, 0x01, 0x0a, 0x22, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x6c, 0x79, 0x52, 0x65, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 0x25, 0x0a, 0x0e, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x78, 0x63, 0x6c, - 0x75, 0x64, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x63, - 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x56, 0x69, 0x65, 0x77, 0x73, 0x12, 0x26, - 0x0a, 0x0f, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x6e, 0x6f, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, - 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x73, 0x6b, 0x69, 0x70, 0x4e, 0x6f, 0x50, - 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, - 0x65, 0x5f, 0x76, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x56, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, - 0x88, 0x02, 0x0a, 0x1e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x63, 0x68, 0x65, - 0x6d, 0x61, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x67, 0x0a, 0x10, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, - 0x74, 0x61, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, - 0x61, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x42, 0x79, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x1a, 0x63, 0x0a, 0x13, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, - 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x36, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, - 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x6b, 0x0a, 0x14, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 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, 0x14, - 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, - 0x68, 0x61, 0x72, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x70, 0x69, 0x6e, 0x67, - 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 0x22, 0x31, 0x0a, 0x15, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0x3c, 0x0a, 0x1e, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, - 0x73, 0x70, 0x61, 0x63, 0x65, 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, 0x22, 0x8a, 0x02, 0x0a, 0x1f, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x68, 0x0a, 0x10, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x3e, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x73, + 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, 0x36, 0x0a, 0x0b, 0x6e, 0x65, 0x77, 0x5f, + 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x03, 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, 0x0a, 0x6e, 0x65, 0x77, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, + 0x12, 0x36, 0x0a, 0x0b, 0x6f, 0x6c, 0x64, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, + 0x04, 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, 0x0a, 0x6f, 0x6c, + 0x64, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x22, 0x5c, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x63, 0x65, 0x6c, 0x6c, 0x5f, 0x69, 0x6e, + 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, + 0x61, 0x74, 0x61, 0x2e, 0x43, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x63, 0x65, + 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x5d, 0x0a, 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x43, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x63, 0x65, 0x6c, 0x6c, 0x5f, 0x69, 0x6e, 0x66, + 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, + 0x74, 0x61, 0x2e, 0x43, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x63, 0x65, 0x6c, + 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x64, 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, + 0x65, 0x6c, 0x6c, 0x73, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x0b, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x5f, 0x61, 0x6c, + 0x69, 0x61, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x6f, 0x70, 0x6f, + 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x52, + 0x0a, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0x65, 0x0a, 0x18, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x0b, 0x63, + 0x65, 0x6c, 0x6c, 0x73, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x14, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x65, 0x6c, 0x6c, + 0x73, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x52, 0x0a, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x41, 0x6c, 0x69, + 0x61, 0x73, 0x22, 0x34, 0x0a, 0x0f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x70, 0x69, 0x6e, + 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 0x22, 0xfb, 0x01, 0x0a, 0x10, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, + 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x62, 0x0a, 0x13, 0x72, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, + 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x42, 0x79, 0x4b, 0x65, 0x79, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x73, 0x42, 0x79, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x1a, 0x69, 0x0a, 0x16, 0x52, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x42, 0x79, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x39, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, + 0x74, 0x61, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x58, 0x0a, 0x17, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 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, 0x21, 0x0a, + 0x0c, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0b, 0x70, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, + 0x22, 0xfc, 0x01, 0x0a, 0x18, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, + 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x61, 0x0a, 0x10, 0x72, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x37, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x42, 0x79, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x72, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x73, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x1a, 0x63, 0x0a, 0x13, 0x52, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x73, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, + 0xd8, 0x01, 0x0a, 0x1d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 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, 0x25, 0x0a, + 0x0e, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x54, 0x61, + 0x62, 0x6c, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, + 0x76, 0x69, 0x65, 0x77, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x6e, 0x63, + 0x6c, 0x75, 0x64, 0x65, 0x56, 0x69, 0x65, 0x77, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x6b, 0x69, + 0x70, 0x5f, 0x6e, 0x6f, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0d, 0x73, 0x6b, 0x69, 0x70, 0x4e, 0x6f, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, + 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x76, 0x73, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, 0x6e, 0x63, 0x6c, + 0x75, 0x64, 0x65, 0x56, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0x88, 0x02, 0x0a, 0x1e, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4b, 0x65, 0x79, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, + 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x67, 0x0a, 0x10, 0x72, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x3d, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, @@ -19114,315 +18691,371 @@ var file_vtctldata_proto_rawDesc = []byte{ 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x4f, 0x0a, 0x1b, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x68, 0x61, 0x72, 0x64, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x22, 0x38, 0x0a, 0x1c, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, - 0x22, 0x98, 0x01, 0x0a, 0x16, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x56, 0x53, 0x63, - 0x68, 0x65, 0x6d, 0x61, 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, 0x16, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, - 0x25, 0x0a, 0x0e, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, - 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, - 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, - 0x65, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, - 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0xfa, 0x01, 0x0a, 0x17, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x6b, 0x0a, 0x14, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 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, 0x14, 0x0a, 0x05, 0x73, 0x68, 0x61, + 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, 0x64, 0x12, + 0x21, 0x0a, 0x0c, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x70, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, + 0x74, 0x73, 0x22, 0x31, 0x0a, 0x15, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0x3c, 0x0a, 0x1e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, + 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, 0x22, 0x8a, 0x02, 0x0a, 0x1f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x73, 0x12, 0x60, 0x0a, 0x10, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x5f, 0x62, 0x79, 0x5f, - 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x76, 0x74, + 0x73, 0x12, 0x68, 0x0a, 0x10, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x5f, 0x62, 0x79, 0x5f, + 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, - 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, - 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x0e, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x42, 0x79, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x1a, 0x63, 0x0a, 0x13, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x42, 0x79, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x76, 0x74, - 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x88, 0x07, 0x0a, 0x12, 0x56, 0x44, 0x69, - 0x66, 0x66, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x42, + 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x72, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x73, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x1a, 0x63, 0x0a, 0x13, 0x52, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x22, 0x4f, 0x0a, 0x1b, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x53, 0x68, 0x61, 0x72, 0x64, 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, 0x14, 0x0a, 0x05, 0x73, + 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x68, 0x61, 0x72, + 0x64, 0x22, 0x38, 0x0a, 0x1c, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0x98, 0x01, 0x0a, 0x16, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 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, 0x16, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x78, + 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0d, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, + 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x76, 0x69, 0x65, + 0x77, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, + 0x65, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0xfa, 0x01, 0x0a, 0x17, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x65, 0x56, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x60, 0x0a, 0x10, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, + 0x74, 0x61, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x56, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x73, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, 0x1a, 0x63, + 0x0a, 0x13, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x42, 0x79, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, + 0x74, 0x61, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, + 0x02, 0x38, 0x01, 0x22, 0x88, 0x07, 0x0a, 0x12, 0x56, 0x44, 0x69, 0x66, 0x66, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 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, 0x27, 0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, + 0x75, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x65, + 0x6c, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x5f, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x12, 0x37, 0x0a, 0x0c, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x06, 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, 0x07, 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, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, + 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x55, + 0x0a, 0x1e, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, + 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x1b, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, + 0x65, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x61, 0x69, + 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x71, + 0x75, 0x65, 0x72, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x64, 0x65, 0x62, 0x75, + 0x67, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x1a, 0x0a, 0x09, 0x6f, 0x6e, 0x6c, 0x79, 0x5f, 0x70, + 0x5f, 0x6b, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x6f, 0x6e, 0x6c, 0x79, 0x50, + 0x4b, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 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, 0x0e, 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, 0x12, 0x0a, 0x04, 0x77, 0x61, + 0x69, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x77, 0x61, 0x69, 0x74, 0x12, 0x42, + 0x0a, 0x14, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, + 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x12, + 0x77, 0x61, 0x69, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, + 0x61, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x79, + 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x75, 0x74, 0x6f, 0x52, 0x65, 0x74, 0x72, + 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x18, 0x12, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x07, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x16, 0x6d, + 0x61, 0x78, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, + 0x5f, 0x72, 0x6f, 0x77, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x6d, 0x61, 0x78, + 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x6f, 0x77, 0x73, + 0x12, 0x3c, 0x0a, 0x11, 0x6d, 0x61, 0x78, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x64, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, + 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x6d, + 0x61, 0x78, 0x44, 0x69, 0x66, 0x66, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x29, + 0x0a, 0x13, 0x56, 0x44, 0x69, 0x66, 0x66, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x55, 0x55, 0x49, 0x44, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x55, 0x55, 0x49, 0x44, 0x22, 0x6b, 0x0a, 0x12, 0x56, 0x44, 0x69, + 0x66, 0x66, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 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, 0x27, 0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x5f, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x65, 0x6c, 0x6c, 0x73, 0x12, 0x37, - 0x0a, 0x0c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x06, - 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, 0x07, 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, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, - 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, - 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, - 0x6d, 0x69, 0x74, 0x12, 0x55, 0x0a, 0x1e, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, 0x5f, - 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x77, 0x61, 0x69, 0x74, - 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, - 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x1b, 0x66, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x57, 0x61, 0x69, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, - 0x62, 0x75, 0x67, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0a, 0x64, 0x65, 0x62, 0x75, 0x67, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x1a, 0x0a, 0x09, 0x6f, - 0x6e, 0x6c, 0x79, 0x5f, 0x70, 0x5f, 0x6b, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, - 0x6f, 0x6e, 0x6c, 0x79, 0x50, 0x4b, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x75, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x0d, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x10, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, - 0x53, 0x74, 0x61, 0x74, 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, 0x0e, 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, - 0x12, 0x0a, 0x04, 0x77, 0x61, 0x69, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x77, - 0x61, 0x69, 0x74, 0x12, 0x42, 0x0a, 0x14, 0x77, 0x61, 0x69, 0x74, 0x5f, 0x75, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x10, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x12, 0x77, 0x61, 0x69, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x75, 0x74, 0x6f, 0x5f, - 0x72, 0x65, 0x74, 0x72, 0x79, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x75, 0x74, - 0x6f, 0x52, 0x65, 0x74, 0x72, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, - 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, - 0x12, 0x33, 0x0a, 0x16, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, - 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x72, 0x6f, 0x77, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x13, 0x6d, 0x61, 0x78, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x61, 0x6d, 0x70, 0x6c, - 0x65, 0x52, 0x6f, 0x77, 0x73, 0x12, 0x3c, 0x0a, 0x11, 0x6d, 0x61, 0x78, 0x5f, 0x64, 0x69, 0x66, - 0x66, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x10, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x0f, 0x6d, 0x61, 0x78, 0x44, 0x69, 0x66, 0x66, 0x44, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x22, 0x29, 0x0a, 0x13, 0x56, 0x44, 0x69, 0x66, 0x66, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x55, 0x55, - 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x55, 0x55, 0x49, 0x44, 0x22, 0x6b, - 0x0a, 0x12, 0x56, 0x44, 0x69, 0x66, 0x66, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 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, 0x27, 0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x72, 0x67, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x61, 0x72, 0x67, 0x22, 0x15, 0x0a, 0x13, 0x56, - 0x44, 0x69, 0x66, 0x66, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x6d, 0x0a, 0x12, 0x56, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x73, 0x75, 0x6d, - 0x65, 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, 0x27, 0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6b, - 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, - 0x64, 0x22, 0x15, 0x0a, 0x13, 0x56, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x69, 0x0a, 0x10, 0x56, 0x44, 0x69, 0x66, - 0x66, 0x53, 0x68, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, + 0x70, 0x61, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x72, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x61, 0x72, 0x67, 0x22, 0x15, 0x0a, 0x13, 0x56, 0x44, 0x69, 0x66, 0x66, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6d, 0x0a, + 0x12, 0x56, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 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, + 0x27, 0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x22, 0x15, 0x0a, 0x13, + 0x56, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x69, 0x0a, 0x10, 0x56, 0x44, 0x69, 0x66, 0x66, 0x53, 0x68, 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, 0x27, 0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6b, 0x65, + 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, + 0x61, 0x72, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x61, 0x72, 0x67, 0x22, 0xd7, + 0x01, 0x0a, 0x11, 0x56, 0x44, 0x69, 0x66, 0x66, 0x53, 0x68, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x10, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x72, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, + 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x56, 0x44, 0x69, 0x66, 0x66, + 0x53, 0x68, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x61, 0x62, + 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x0f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x73, 0x1a, 0x64, 0x0a, 0x14, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 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, 0x36, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 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, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x6b, 0x0a, 0x10, 0x56, 0x44, 0x69, 0x66, + 0x66, 0x53, 0x74, 0x6f, 0x70, 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, 0x27, 0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x72, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x61, 0x72, 0x67, 0x22, 0xd7, 0x01, 0x0a, 0x11, 0x56, 0x44, 0x69, 0x66, 0x66, 0x53, 0x68, 0x6f, - 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x10, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, - 0x56, 0x44, 0x69, 0x66, 0x66, 0x53, 0x68, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0x64, 0x0a, 0x14, 0x54, 0x61, 0x62, 0x6c, 0x65, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 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, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x20, 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, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x6b, 0x0a, - 0x10, 0x56, 0x44, 0x69, 0x66, 0x66, 0x53, 0x74, 0x6f, 0x70, 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, 0x27, 0x0a, - 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4b, 0x65, - 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x22, 0x13, 0x0a, 0x11, 0x56, 0x44, - 0x69, 0x66, 0x66, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0xb2, 0x01, 0x0a, 0x15, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 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, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6b, 0x65, 0x65, 0x70, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2c, - 0x0a, 0x12, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x72, - 0x75, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x6b, 0x65, 0x65, 0x70, - 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, - 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x68, - 0x61, 0x72, 0x64, 0x73, 0x22, 0xd1, 0x01, 0x0a, 0x16, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, - 0x77, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x75, 0x75, 0x69, 0x64, 0x22, 0x13, 0x0a, 0x11, 0x56, 0x44, 0x69, 0x66, 0x66, 0x53, 0x74, + 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb2, 0x01, 0x0a, 0x15, 0x57, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 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, 0x1b, 0x0a, 0x09, + 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x08, 0x6b, 0x65, 0x65, 0x70, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2c, 0x0a, 0x12, 0x6b, 0x65, 0x65, + 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x6b, 0x65, 0x65, 0x70, 0x52, 0x6f, 0x75, 0x74, 0x69, + 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, + 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x22, + 0xd1, 0x01, 0x0a, 0x16, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, + 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x6d, + 0x6d, 0x61, 0x72, 0x79, 0x12, 0x46, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, + 0x61, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x1a, 0x55, 0x0a, 0x0a, + 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2d, 0x0a, 0x06, 0x74, 0x61, + 0x62, 0x6c, 0x65, 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, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x64, 0x22, 0x67, 0x0a, 0x15, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 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, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x22, 0xe6, 0x07, 0x0a, + 0x16, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x10, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x35, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x57, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x6f, 0x70, 0x79, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x43, + 0x6f, 0x70, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x58, 0x0a, 0x0d, 0x73, 0x68, 0x61, 0x72, + 0x64, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x33, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x57, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x73, 0x68, 0x61, 0x72, 0x64, 0x53, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x73, 0x74, + 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74, 0x72, 0x61, 0x66, 0x66, + 0x69, 0x63, 0x53, 0x74, 0x61, 0x74, 0x65, 0x1a, 0xe8, 0x01, 0x0a, 0x0e, 0x54, 0x61, 0x62, 0x6c, + 0x65, 0x43, 0x6f, 0x70, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x6f, + 0x77, 0x73, 0x5f, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0a, 0x72, 0x6f, 0x77, 0x73, 0x43, 0x6f, 0x70, 0x69, 0x65, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, + 0x6f, 0x77, 0x73, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x09, 0x72, 0x6f, 0x77, 0x73, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x6f, + 0x77, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x02, 0x52, 0x0e, 0x72, 0x6f, 0x77, 0x73, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, + 0x61, 0x67, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x70, + 0x69, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x62, 0x79, 0x74, 0x65, 0x73, + 0x43, 0x6f, 0x70, 0x69, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, + 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x62, 0x79, 0x74, + 0x65, 0x73, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x29, 0x0a, 0x10, 0x62, 0x79, 0x74, 0x65, 0x73, + 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x02, 0x52, 0x0f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x61, + 0x67, 0x65, 0x1a, 0xbc, 0x01, 0x0a, 0x10, 0x53, 0x68, 0x61, 0x72, 0x64, 0x53, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2d, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x74, 0x18, 0x02, 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, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, + 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, 0x6e, 0x66, + 0x6f, 0x1a, 0x5c, 0x0a, 0x0c, 0x53, 0x68, 0x61, 0x72, 0x64, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x73, 0x12, 0x4c, 0x0a, 0x07, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x57, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x53, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x07, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x1a, + 0x73, 0x0a, 0x13, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x6f, 0x70, 0x79, 0x53, 0x74, 0x61, 0x74, + 0x65, 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, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, + 0x61, 0x74, 0x61, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, + 0x43, 0x6f, 0x70, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x6f, 0x0a, 0x11, 0x53, 0x68, 0x61, 0x72, 0x64, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 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, 0x44, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x76, 0x74, 0x63, + 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xef, 0x03, 0x0a, 0x1c, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x6f, 0x77, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 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, 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, 0x4f, 0x0a, + 0x1b, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x44, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x18, 0x6d, 0x61, 0x78, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x61, 0x67, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x12, 0x3c, + 0x0a, 0x1a, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, + 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x18, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x76, 0x65, 0x72, 0x73, + 0x65, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, + 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x07, 0x74, 0x69, + 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, + 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x74, + 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, + 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x12, + 0x3e, 0x0a, 0x1b, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x5f, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x19, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, + 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, + 0x16, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x22, 0xa7, 0x01, 0x0a, 0x1d, 0x57, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, + 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x6d, + 0x6d, 0x61, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, + 0x61, 0x72, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x64, 0x72, 0x79, + 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0d, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x73, 0x22, 0x90, 0x01, 0x0a, 0x15, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 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, 0x5b, 0x0a, 0x0e, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x34, 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, 0x52, 0x0d, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x22, 0xd1, 0x01, 0x0a, 0x16, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, + 0x77, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x46, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x76, 0x74, 0x63, - 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x61, + 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x1a, 0x55, 0x0a, 0x0a, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2d, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 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, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x12, 0x18, - 0x0a, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x22, 0x67, 0x0a, 0x15, 0x57, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 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, 0x73, 0x68, 0x61, - 0x72, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x73, 0x22, 0xe6, 0x07, 0x0a, 0x16, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x10, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, - 0x74, 0x61, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x43, - 0x6f, 0x70, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x43, 0x6f, 0x70, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x58, 0x0a, - 0x0d, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x53, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x66, 0x66, - 0x69, 0x63, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x53, 0x74, 0x61, 0x74, 0x65, 0x1a, 0xe8, 0x01, 0x0a, - 0x0e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x6f, 0x70, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, - 0x1f, 0x0a, 0x0b, 0x72, 0x6f, 0x77, 0x73, 0x5f, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x6f, 0x77, 0x73, 0x43, 0x6f, 0x70, 0x69, 0x65, 0x64, - 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x77, 0x73, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x72, 0x6f, 0x77, 0x73, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x12, - 0x27, 0x0a, 0x0f, 0x72, 0x6f, 0x77, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x61, - 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x0e, 0x72, 0x6f, 0x77, 0x73, 0x50, 0x65, - 0x72, 0x63, 0x65, 0x6e, 0x74, 0x61, 0x67, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x79, 0x74, 0x65, - 0x73, 0x5f, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, - 0x62, 0x79, 0x74, 0x65, 0x73, 0x43, 0x6f, 0x70, 0x69, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x62, - 0x79, 0x74, 0x65, 0x73, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0a, 0x62, 0x79, 0x74, 0x65, 0x73, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x29, 0x0a, 0x10, - 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x61, 0x67, 0x65, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x02, 0x52, 0x0f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x50, 0x65, 0x72, - 0x63, 0x65, 0x6e, 0x74, 0x61, 0x67, 0x65, 0x1a, 0xbc, 0x01, 0x0a, 0x10, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2d, 0x0a, 0x06, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x18, 0x02, 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, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1a, - 0x0a, 0x08, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x1a, 0x5c, 0x0a, 0x0c, 0x53, 0x68, 0x61, 0x72, 0x64, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x4c, 0x0a, 0x07, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x07, 0x73, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x73, 0x1a, 0x73, 0x0a, 0x13, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x6f, 0x70, - 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 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, 0x76, - 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, - 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, - 0x54, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x6f, 0x70, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x6f, 0x0a, 0x11, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 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, 0x44, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x2e, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x57, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xef, 0x03, 0x0a, 0x1c, 0x57, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x54, 0x72, 0x61, - 0x66, 0x66, 0x69, 0x63, 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, 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, 0x4f, 0x0a, 0x1b, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, - 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, - 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x18, 0x6d, 0x61, 0x78, 0x52, 0x65, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x61, 0x67, 0x41, 0x6c, 0x6c, 0x6f, - 0x77, 0x65, 0x64, 0x12, 0x3c, 0x0a, 0x1a, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, - 0x76, 0x65, 0x72, 0x73, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x52, - 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x2a, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x10, 0x2e, 0x76, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x64, - 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, - 0x79, 0x52, 0x75, 0x6e, 0x12, 0x3e, 0x0a, 0x1b, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, - 0x7a, 0x65, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, - 0x63, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x19, 0x69, 0x6e, 0x69, 0x74, 0x69, - 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x65, 0x71, 0x75, 0x65, - 0x6e, 0x63, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, 0x0b, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x22, 0xa7, 0x01, 0x0a, - 0x1d, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x54, - 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, - 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x72, - 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, - 0x74, 0x61, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x75, 0x72, - 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x26, - 0x0a, 0x0f, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x52, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0x90, 0x01, 0x0a, 0x15, 0x57, 0x6f, 0x72, 0x6b, 0x66, - 0x6c, 0x6f, 0x77, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 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, 0x5b, 0x0a, 0x0e, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 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, 0x52, 0x0d, 0x74, 0x61, 0x62, 0x6c, - 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xd1, 0x01, 0x0a, 0x16, 0x57, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x46, - 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x2c, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x57, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x07, 0x64, - 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x1a, 0x55, 0x0a, 0x0a, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, - 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2d, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 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, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x2a, 0x4a, 0x0a, - 0x15, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x55, 0x53, 0x54, 0x4f, 0x4d, - 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x4d, 0x4f, 0x56, 0x45, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x53, - 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x4c, 0x4f, 0x4f, 0x4b, - 0x55, 0x50, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x10, 0x02, 0x2a, 0x38, 0x0a, 0x0d, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, - 0x4e, 0x45, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x41, 0x53, 0x43, 0x45, 0x4e, 0x44, 0x49, 0x4e, - 0x47, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x44, 0x45, 0x53, 0x43, 0x45, 0x4e, 0x44, 0x49, 0x4e, - 0x47, 0x10, 0x02, 0x42, 0x28, 0x5a, 0x26, 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, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x22, 0x17, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x4d, + 0x69, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x22, 0x51, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x75, + 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0c, 0x6d, + 0x69, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x4d, 0x69, 0x72, 0x72, + 0x6f, 0x72, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x0b, 0x6d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x52, + 0x75, 0x6c, 0x65, 0x73, 0x22, 0xa9, 0x01, 0x0a, 0x1c, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, + 0x77, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 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, 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, 0x18, 0x0a, 0x07, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x02, 0x52, 0x07, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, + 0x22, 0x7f, 0x0a, 0x1d, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4d, 0x69, 0x72, 0x72, + 0x6f, 0x72, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x23, 0x0a, 0x0d, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x2a, 0x4a, 0x0a, 0x15, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x55, + 0x53, 0x54, 0x4f, 0x4d, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x4d, 0x4f, 0x56, 0x45, 0x54, 0x41, + 0x42, 0x4c, 0x45, 0x53, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, + 0x4c, 0x4f, 0x4f, 0x4b, 0x55, 0x50, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x10, 0x02, 0x2a, 0x38, 0x0a, + 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x08, + 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x41, 0x53, 0x43, 0x45, + 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x44, 0x45, 0x53, 0x43, 0x45, + 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x42, 0x28, 0x5a, 0x26, 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, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, + 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -19438,7 +19071,7 @@ func file_vtctldata_proto_rawDescGZIP() []byte { } var file_vtctldata_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_vtctldata_proto_msgTypes = make([]protoimpl.MessageInfo, 295) +var file_vtctldata_proto_msgTypes = make([]protoimpl.MessageInfo, 288) var file_vtctldata_proto_goTypes = []any{ (MaterializationIntent)(0), // 0: vtctldata.MaterializationIntent (QueryOrdering)(0), // 1: vtctldata.QueryOrdering @@ -19689,335 +19322,322 @@ var file_vtctldata_proto_goTypes = []any{ (*WorkflowSwitchTrafficResponse)(nil), // 246: vtctldata.WorkflowSwitchTrafficResponse (*WorkflowUpdateRequest)(nil), // 247: vtctldata.WorkflowUpdateRequest (*WorkflowUpdateResponse)(nil), // 248: vtctldata.WorkflowUpdateResponse - nil, // 249: vtctldata.Workflow.ShardStreamsEntry - (*Workflow_ReplicationLocation)(nil), // 250: vtctldata.Workflow.ReplicationLocation - (*Workflow_ShardStream)(nil), // 251: vtctldata.Workflow.ShardStream - (*Workflow_Stream)(nil), // 252: vtctldata.Workflow.Stream - (*Workflow_Stream_CopyState)(nil), // 253: vtctldata.Workflow.Stream.CopyState - (*Workflow_Stream_Log)(nil), // 254: vtctldata.Workflow.Stream.Log - (*Workflow_Stream_ThrottlerStatus)(nil), // 255: vtctldata.Workflow.Stream.ThrottlerStatus - nil, // 256: vtctldata.ApplySchemaResponse.RowsAffectedByShardEntry - nil, // 257: vtctldata.ApplyVSchemaResponse.UnknownVindexParamsEntry - (*ApplyVSchemaResponse_ParamList)(nil), // 258: vtctldata.ApplyVSchemaResponse.ParamList - nil, // 259: vtctldata.CancelSchemaMigrationResponse.RowsAffectedByShardEntry - (*CheckThrottlerResponse_Metric)(nil), // 260: vtctldata.CheckThrottlerResponse.Metric - nil, // 261: vtctldata.CheckThrottlerResponse.MetricsEntry - nil, // 262: vtctldata.CleanupSchemaMigrationResponse.RowsAffectedByShardEntry - nil, // 263: vtctldata.CompleteSchemaMigrationResponse.RowsAffectedByShardEntry - nil, // 264: vtctldata.FindAllShardsInKeyspaceResponse.ShardsEntry - nil, // 265: vtctldata.ForceCutOverSchemaMigrationResponse.RowsAffectedByShardEntry - nil, // 266: vtctldata.GetCellsAliasesResponse.AliasesEntry - nil, // 267: vtctldata.GetShardReplicationResponse.ShardReplicationByCellEntry - nil, // 268: vtctldata.GetSrvKeyspaceNamesResponse.NamesEntry - (*GetSrvKeyspaceNamesResponse_NameList)(nil), // 269: vtctldata.GetSrvKeyspaceNamesResponse.NameList - nil, // 270: vtctldata.GetSrvKeyspacesResponse.SrvKeyspacesEntry - nil, // 271: vtctldata.GetSrvVSchemasResponse.SrvVSchemasEntry - (*GetThrottlerStatusResponse_MetricResult)(nil), // 272: vtctldata.GetThrottlerStatusResponse.MetricResult - nil, // 273: vtctldata.GetThrottlerStatusResponse.AggregatedMetricsEntry - nil, // 274: vtctldata.GetThrottlerStatusResponse.MetricThresholdsEntry - (*GetThrottlerStatusResponse_MetricHealth)(nil), // 275: vtctldata.GetThrottlerStatusResponse.MetricHealth - nil, // 276: vtctldata.GetThrottlerStatusResponse.MetricsHealthEntry - nil, // 277: vtctldata.GetThrottlerStatusResponse.ThrottledAppsEntry - nil, // 278: vtctldata.GetThrottlerStatusResponse.AppCheckedMetricsEntry - (*GetThrottlerStatusResponse_RecentApp)(nil), // 279: vtctldata.GetThrottlerStatusResponse.RecentApp - nil, // 280: vtctldata.GetThrottlerStatusResponse.RecentAppsEntry - nil, // 281: vtctldata.LaunchSchemaMigrationResponse.RowsAffectedByShardEntry - (*MoveTablesCreateResponse_TabletInfo)(nil), // 282: vtctldata.MoveTablesCreateResponse.TabletInfo - nil, // 283: vtctldata.RetrySchemaMigrationResponse.RowsAffectedByShardEntry - nil, // 284: vtctldata.ShardReplicationPositionsResponse.ReplicationStatusesEntry - nil, // 285: vtctldata.ShardReplicationPositionsResponse.TabletMapEntry - nil, // 286: vtctldata.ValidateResponse.ResultsByKeyspaceEntry - nil, // 287: vtctldata.ValidateKeyspaceResponse.ResultsByShardEntry - nil, // 288: vtctldata.ValidateSchemaKeyspaceResponse.ResultsByShardEntry - nil, // 289: vtctldata.ValidateVersionKeyspaceResponse.ResultsByShardEntry - nil, // 290: vtctldata.ValidateVSchemaResponse.ResultsByShardEntry - nil, // 291: vtctldata.VDiffShowResponse.TabletResponsesEntry - (*WorkflowDeleteResponse_TabletInfo)(nil), // 292: vtctldata.WorkflowDeleteResponse.TabletInfo - (*WorkflowStatusResponse_TableCopyState)(nil), // 293: vtctldata.WorkflowStatusResponse.TableCopyState - (*WorkflowStatusResponse_ShardStreamState)(nil), // 294: vtctldata.WorkflowStatusResponse.ShardStreamState - (*WorkflowStatusResponse_ShardStreams)(nil), // 295: vtctldata.WorkflowStatusResponse.ShardStreams - nil, // 296: vtctldata.WorkflowStatusResponse.TableCopyStateEntry - nil, // 297: vtctldata.WorkflowStatusResponse.ShardStreamsEntry - (*WorkflowUpdateResponse_TabletInfo)(nil), // 298: vtctldata.WorkflowUpdateResponse.TabletInfo - (*logutil.Event)(nil), // 299: logutil.Event - (tabletmanagerdata.TabletSelectionPreference)(0), // 300: tabletmanagerdata.TabletSelectionPreference - (*topodata.Keyspace)(nil), // 301: topodata.Keyspace - (*vttime.Time)(nil), // 302: vttime.Time - (*topodata.TabletAlias)(nil), // 303: topodata.TabletAlias - (*vttime.Duration)(nil), // 304: vttime.Duration - (*topodata.Shard)(nil), // 305: topodata.Shard - (*topodata.CellInfo)(nil), // 306: topodata.CellInfo - (*vschema.KeyspaceRoutingRules)(nil), // 307: vschema.KeyspaceRoutingRules - (*vschema.RoutingRules)(nil), // 308: vschema.RoutingRules - (*vschema.ShardRoutingRules)(nil), // 309: vschema.ShardRoutingRules - (*vtrpc.CallerID)(nil), // 310: vtrpc.CallerID - (*vschema.Keyspace)(nil), // 311: vschema.Keyspace - (topodata.TabletType)(0), // 312: topodata.TabletType - (*topodata.Tablet)(nil), // 313: topodata.Tablet - (topodata.KeyspaceType)(0), // 314: topodata.KeyspaceType - (*query.QueryResult)(nil), // 315: query.QueryResult - (*tabletmanagerdata.ExecuteHookRequest)(nil), // 316: tabletmanagerdata.ExecuteHookRequest - (*tabletmanagerdata.ExecuteHookResponse)(nil), // 317: tabletmanagerdata.ExecuteHookResponse - (*mysqlctl.BackupInfo)(nil), // 318: mysqlctl.BackupInfo - (*replicationdata.FullStatus)(nil), // 319: replicationdata.FullStatus - (*tabletmanagerdata.Permissions)(nil), // 320: tabletmanagerdata.Permissions - (*tabletmanagerdata.SchemaDefinition)(nil), // 321: tabletmanagerdata.SchemaDefinition - (*topodata.ThrottledAppRule)(nil), // 322: topodata.ThrottledAppRule - (*vschema.SrvVSchema)(nil), // 323: vschema.SrvVSchema - (*topodata.ShardReplicationError)(nil), // 324: topodata.ShardReplicationError - (*topodata.KeyRange)(nil), // 325: topodata.KeyRange - (*topodata.CellsAlias)(nil), // 326: topodata.CellsAlias - (*tabletmanagerdata.UpdateVReplicationWorkflowRequest)(nil), // 327: tabletmanagerdata.UpdateVReplicationWorkflowRequest - (*topodata.Shard_TabletControl)(nil), // 328: topodata.Shard.TabletControl - (*binlogdata.BinlogSource)(nil), // 329: binlogdata.BinlogSource - (*topodata.ShardReplication)(nil), // 330: topodata.ShardReplication - (*topodata.SrvKeyspace)(nil), // 331: topodata.SrvKeyspace - (*replicationdata.Status)(nil), // 332: replicationdata.Status - (*tabletmanagerdata.VDiffResponse)(nil), // 333: tabletmanagerdata.VDiffResponse + (*GetMirrorRulesRequest)(nil), // 249: vtctldata.GetMirrorRulesRequest + (*GetMirrorRulesResponse)(nil), // 250: vtctldata.GetMirrorRulesResponse + (*WorkflowMirrorTrafficRequest)(nil), // 251: vtctldata.WorkflowMirrorTrafficRequest + (*WorkflowMirrorTrafficResponse)(nil), // 252: vtctldata.WorkflowMirrorTrafficResponse + nil, // 253: vtctldata.Workflow.ShardStreamsEntry + (*Workflow_ReplicationLocation)(nil), // 254: vtctldata.Workflow.ReplicationLocation + (*Workflow_ShardStream)(nil), // 255: vtctldata.Workflow.ShardStream + (*Workflow_Stream)(nil), // 256: vtctldata.Workflow.Stream + (*Workflow_Stream_CopyState)(nil), // 257: vtctldata.Workflow.Stream.CopyState + (*Workflow_Stream_Log)(nil), // 258: vtctldata.Workflow.Stream.Log + (*Workflow_Stream_ThrottlerStatus)(nil), // 259: vtctldata.Workflow.Stream.ThrottlerStatus + nil, // 260: vtctldata.ApplySchemaResponse.RowsAffectedByShardEntry + nil, // 261: vtctldata.ApplyVSchemaResponse.UnknownVindexParamsEntry + (*ApplyVSchemaResponse_ParamList)(nil), // 262: vtctldata.ApplyVSchemaResponse.ParamList + nil, // 263: vtctldata.CancelSchemaMigrationResponse.RowsAffectedByShardEntry + nil, // 264: vtctldata.CleanupSchemaMigrationResponse.RowsAffectedByShardEntry + nil, // 265: vtctldata.CompleteSchemaMigrationResponse.RowsAffectedByShardEntry + nil, // 266: vtctldata.FindAllShardsInKeyspaceResponse.ShardsEntry + nil, // 267: vtctldata.ForceCutOverSchemaMigrationResponse.RowsAffectedByShardEntry + nil, // 268: vtctldata.GetCellsAliasesResponse.AliasesEntry + nil, // 269: vtctldata.GetShardReplicationResponse.ShardReplicationByCellEntry + nil, // 270: vtctldata.GetSrvKeyspaceNamesResponse.NamesEntry + (*GetSrvKeyspaceNamesResponse_NameList)(nil), // 271: vtctldata.GetSrvKeyspaceNamesResponse.NameList + nil, // 272: vtctldata.GetSrvKeyspacesResponse.SrvKeyspacesEntry + nil, // 273: vtctldata.GetSrvVSchemasResponse.SrvVSchemasEntry + nil, // 274: vtctldata.LaunchSchemaMigrationResponse.RowsAffectedByShardEntry + (*MoveTablesCreateResponse_TabletInfo)(nil), // 275: vtctldata.MoveTablesCreateResponse.TabletInfo + nil, // 276: vtctldata.RetrySchemaMigrationResponse.RowsAffectedByShardEntry + nil, // 277: vtctldata.ShardReplicationPositionsResponse.ReplicationStatusesEntry + nil, // 278: vtctldata.ShardReplicationPositionsResponse.TabletMapEntry + nil, // 279: vtctldata.ValidateResponse.ResultsByKeyspaceEntry + nil, // 280: vtctldata.ValidateKeyspaceResponse.ResultsByShardEntry + nil, // 281: vtctldata.ValidateSchemaKeyspaceResponse.ResultsByShardEntry + nil, // 282: vtctldata.ValidateVersionKeyspaceResponse.ResultsByShardEntry + nil, // 283: vtctldata.ValidateVSchemaResponse.ResultsByShardEntry + nil, // 284: vtctldata.VDiffShowResponse.TabletResponsesEntry + (*WorkflowDeleteResponse_TabletInfo)(nil), // 285: vtctldata.WorkflowDeleteResponse.TabletInfo + (*WorkflowStatusResponse_TableCopyState)(nil), // 286: vtctldata.WorkflowStatusResponse.TableCopyState + (*WorkflowStatusResponse_ShardStreamState)(nil), // 287: vtctldata.WorkflowStatusResponse.ShardStreamState + (*WorkflowStatusResponse_ShardStreams)(nil), // 288: vtctldata.WorkflowStatusResponse.ShardStreams + nil, // 289: vtctldata.WorkflowStatusResponse.TableCopyStateEntry + nil, // 290: vtctldata.WorkflowStatusResponse.ShardStreamsEntry + (*WorkflowUpdateResponse_TabletInfo)(nil), // 291: vtctldata.WorkflowUpdateResponse.TabletInfo + (*logutil.Event)(nil), // 292: logutil.Event + (tabletmanagerdata.TabletSelectionPreference)(0), // 293: tabletmanagerdata.TabletSelectionPreference + (*topodata.Keyspace)(nil), // 294: topodata.Keyspace + (*vttime.Time)(nil), // 295: vttime.Time + (*topodata.TabletAlias)(nil), // 296: topodata.TabletAlias + (*vttime.Duration)(nil), // 297: vttime.Duration + (*topodata.Shard)(nil), // 298: topodata.Shard + (*topodata.CellInfo)(nil), // 299: topodata.CellInfo + (*vschema.KeyspaceRoutingRules)(nil), // 300: vschema.KeyspaceRoutingRules + (*vschema.RoutingRules)(nil), // 301: vschema.RoutingRules + (*vschema.ShardRoutingRules)(nil), // 302: vschema.ShardRoutingRules + (*vtrpc.CallerID)(nil), // 303: vtrpc.CallerID + (*vschema.Keyspace)(nil), // 304: vschema.Keyspace + (topodata.TabletType)(0), // 305: topodata.TabletType + (*topodata.Tablet)(nil), // 306: topodata.Tablet + (*tabletmanagerdata.CheckThrottlerResponse)(nil), // 307: tabletmanagerdata.CheckThrottlerResponse + (topodata.KeyspaceType)(0), // 308: topodata.KeyspaceType + (*query.QueryResult)(nil), // 309: query.QueryResult + (*tabletmanagerdata.ExecuteHookRequest)(nil), // 310: tabletmanagerdata.ExecuteHookRequest + (*tabletmanagerdata.ExecuteHookResponse)(nil), // 311: tabletmanagerdata.ExecuteHookResponse + (*mysqlctl.BackupInfo)(nil), // 312: mysqlctl.BackupInfo + (*replicationdata.FullStatus)(nil), // 313: replicationdata.FullStatus + (*tabletmanagerdata.Permissions)(nil), // 314: tabletmanagerdata.Permissions + (*tabletmanagerdata.SchemaDefinition)(nil), // 315: tabletmanagerdata.SchemaDefinition + (*topodata.ThrottledAppRule)(nil), // 316: topodata.ThrottledAppRule + (*vschema.SrvVSchema)(nil), // 317: vschema.SrvVSchema + (*tabletmanagerdata.GetThrottlerStatusResponse)(nil), // 318: tabletmanagerdata.GetThrottlerStatusResponse + (*topodata.ShardReplicationError)(nil), // 319: topodata.ShardReplicationError + (*topodata.KeyRange)(nil), // 320: topodata.KeyRange + (*topodata.CellsAlias)(nil), // 321: topodata.CellsAlias + (*tabletmanagerdata.UpdateVReplicationWorkflowRequest)(nil), // 322: tabletmanagerdata.UpdateVReplicationWorkflowRequest + (*vschema.MirrorRules)(nil), // 323: vschema.MirrorRules + (*topodata.Shard_TabletControl)(nil), // 324: topodata.Shard.TabletControl + (*binlogdata.BinlogSource)(nil), // 325: binlogdata.BinlogSource + (*topodata.ShardReplication)(nil), // 326: topodata.ShardReplication + (*topodata.SrvKeyspace)(nil), // 327: topodata.SrvKeyspace + (*replicationdata.Status)(nil), // 328: replicationdata.Status + (*tabletmanagerdata.VDiffResponse)(nil), // 329: tabletmanagerdata.VDiffResponse } var file_vtctldata_proto_depIdxs = []int32{ - 299, // 0: vtctldata.ExecuteVtctlCommandResponse.event:type_name -> logutil.Event + 292, // 0: vtctldata.ExecuteVtctlCommandResponse.event:type_name -> logutil.Event 6, // 1: vtctldata.MaterializeSettings.table_settings:type_name -> vtctldata.TableMaterializeSettings 0, // 2: vtctldata.MaterializeSettings.materialization_intent:type_name -> vtctldata.MaterializationIntent - 300, // 3: vtctldata.MaterializeSettings.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference + 293, // 3: vtctldata.MaterializeSettings.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference 11, // 4: vtctldata.MaterializeSettings.workflow_options:type_name -> vtctldata.WorkflowOptions - 301, // 5: vtctldata.Keyspace.keyspace:type_name -> topodata.Keyspace + 294, // 5: vtctldata.Keyspace.keyspace:type_name -> topodata.Keyspace 2, // 6: vtctldata.SchemaMigration.strategy:type_name -> vtctldata.SchemaMigration.Strategy - 302, // 7: vtctldata.SchemaMigration.added_at:type_name -> vttime.Time - 302, // 8: vtctldata.SchemaMigration.requested_at:type_name -> vttime.Time - 302, // 9: vtctldata.SchemaMigration.ready_at:type_name -> vttime.Time - 302, // 10: vtctldata.SchemaMigration.started_at:type_name -> vttime.Time - 302, // 11: vtctldata.SchemaMigration.liveness_timestamp:type_name -> vttime.Time - 302, // 12: vtctldata.SchemaMigration.completed_at:type_name -> vttime.Time - 302, // 13: vtctldata.SchemaMigration.cleaned_up_at:type_name -> vttime.Time + 295, // 7: vtctldata.SchemaMigration.added_at:type_name -> vttime.Time + 295, // 8: vtctldata.SchemaMigration.requested_at:type_name -> vttime.Time + 295, // 9: vtctldata.SchemaMigration.ready_at:type_name -> vttime.Time + 295, // 10: vtctldata.SchemaMigration.started_at:type_name -> vttime.Time + 295, // 11: vtctldata.SchemaMigration.liveness_timestamp:type_name -> vttime.Time + 295, // 12: vtctldata.SchemaMigration.completed_at:type_name -> vttime.Time + 295, // 13: vtctldata.SchemaMigration.cleaned_up_at:type_name -> vttime.Time 3, // 14: vtctldata.SchemaMigration.status:type_name -> vtctldata.SchemaMigration.Status - 303, // 15: vtctldata.SchemaMigration.tablet:type_name -> topodata.TabletAlias - 304, // 16: vtctldata.SchemaMigration.artifact_retention:type_name -> vttime.Duration - 302, // 17: vtctldata.SchemaMigration.last_throttled_at:type_name -> vttime.Time - 302, // 18: vtctldata.SchemaMigration.cancelled_at:type_name -> vttime.Time - 302, // 19: vtctldata.SchemaMigration.reviewed_at:type_name -> vttime.Time - 302, // 20: vtctldata.SchemaMigration.ready_to_complete_at:type_name -> vttime.Time - 305, // 21: vtctldata.Shard.shard:type_name -> topodata.Shard - 250, // 22: vtctldata.Workflow.source:type_name -> vtctldata.Workflow.ReplicationLocation - 250, // 23: vtctldata.Workflow.target:type_name -> vtctldata.Workflow.ReplicationLocation - 249, // 24: vtctldata.Workflow.shard_streams:type_name -> vtctldata.Workflow.ShardStreamsEntry + 296, // 15: vtctldata.SchemaMigration.tablet:type_name -> topodata.TabletAlias + 297, // 16: vtctldata.SchemaMigration.artifact_retention:type_name -> vttime.Duration + 295, // 17: vtctldata.SchemaMigration.last_throttled_at:type_name -> vttime.Time + 295, // 18: vtctldata.SchemaMigration.cancelled_at:type_name -> vttime.Time + 295, // 19: vtctldata.SchemaMigration.reviewed_at:type_name -> vttime.Time + 295, // 20: vtctldata.SchemaMigration.ready_to_complete_at:type_name -> vttime.Time + 298, // 21: vtctldata.Shard.shard:type_name -> topodata.Shard + 254, // 22: vtctldata.Workflow.source:type_name -> vtctldata.Workflow.ReplicationLocation + 254, // 23: vtctldata.Workflow.target:type_name -> vtctldata.Workflow.ReplicationLocation + 253, // 24: vtctldata.Workflow.shard_streams:type_name -> vtctldata.Workflow.ShardStreamsEntry 11, // 25: vtctldata.Workflow.options:type_name -> vtctldata.WorkflowOptions - 306, // 26: vtctldata.AddCellInfoRequest.cell_info:type_name -> topodata.CellInfo - 307, // 27: vtctldata.ApplyKeyspaceRoutingRulesRequest.keyspace_routing_rules:type_name -> vschema.KeyspaceRoutingRules - 307, // 28: vtctldata.ApplyKeyspaceRoutingRulesResponse.keyspace_routing_rules:type_name -> vschema.KeyspaceRoutingRules - 308, // 29: vtctldata.ApplyRoutingRulesRequest.routing_rules:type_name -> vschema.RoutingRules - 309, // 30: vtctldata.ApplyShardRoutingRulesRequest.shard_routing_rules:type_name -> vschema.ShardRoutingRules - 304, // 31: vtctldata.ApplySchemaRequest.wait_replicas_timeout:type_name -> vttime.Duration - 310, // 32: vtctldata.ApplySchemaRequest.caller_id:type_name -> vtrpc.CallerID - 256, // 33: vtctldata.ApplySchemaResponse.rows_affected_by_shard:type_name -> vtctldata.ApplySchemaResponse.RowsAffectedByShardEntry - 311, // 34: vtctldata.ApplyVSchemaRequest.v_schema:type_name -> vschema.Keyspace - 311, // 35: vtctldata.ApplyVSchemaResponse.v_schema:type_name -> vschema.Keyspace - 257, // 36: vtctldata.ApplyVSchemaResponse.unknown_vindex_params:type_name -> vtctldata.ApplyVSchemaResponse.UnknownVindexParamsEntry - 303, // 37: vtctldata.BackupRequest.tablet_alias:type_name -> topodata.TabletAlias - 303, // 38: vtctldata.BackupResponse.tablet_alias:type_name -> topodata.TabletAlias - 299, // 39: vtctldata.BackupResponse.event:type_name -> logutil.Event - 259, // 40: vtctldata.CancelSchemaMigrationResponse.rows_affected_by_shard:type_name -> vtctldata.CancelSchemaMigrationResponse.RowsAffectedByShardEntry - 303, // 41: vtctldata.ChangeTabletTypeRequest.tablet_alias:type_name -> topodata.TabletAlias - 312, // 42: vtctldata.ChangeTabletTypeRequest.db_type:type_name -> topodata.TabletType - 313, // 43: vtctldata.ChangeTabletTypeResponse.before_tablet:type_name -> topodata.Tablet - 313, // 44: vtctldata.ChangeTabletTypeResponse.after_tablet:type_name -> topodata.Tablet - 303, // 45: vtctldata.CheckThrottlerRequest.tablet_alias:type_name -> topodata.TabletAlias - 261, // 46: vtctldata.CheckThrottlerResponse.metrics:type_name -> vtctldata.CheckThrottlerResponse.MetricsEntry - 262, // 47: vtctldata.CleanupSchemaMigrationResponse.rows_affected_by_shard:type_name -> vtctldata.CleanupSchemaMigrationResponse.RowsAffectedByShardEntry - 263, // 48: vtctldata.CompleteSchemaMigrationResponse.rows_affected_by_shard:type_name -> vtctldata.CompleteSchemaMigrationResponse.RowsAffectedByShardEntry - 314, // 49: vtctldata.CreateKeyspaceRequest.type:type_name -> topodata.KeyspaceType - 302, // 50: vtctldata.CreateKeyspaceRequest.snapshot_time:type_name -> vttime.Time - 8, // 51: vtctldata.CreateKeyspaceResponse.keyspace:type_name -> vtctldata.Keyspace - 8, // 52: vtctldata.CreateShardResponse.keyspace:type_name -> vtctldata.Keyspace - 10, // 53: vtctldata.CreateShardResponse.shard:type_name -> vtctldata.Shard - 10, // 54: vtctldata.DeleteShardsRequest.shards:type_name -> vtctldata.Shard - 303, // 55: vtctldata.DeleteTabletsRequest.tablet_aliases:type_name -> topodata.TabletAlias - 303, // 56: vtctldata.EmergencyReparentShardRequest.new_primary:type_name -> topodata.TabletAlias - 303, // 57: vtctldata.EmergencyReparentShardRequest.ignore_replicas:type_name -> topodata.TabletAlias - 304, // 58: vtctldata.EmergencyReparentShardRequest.wait_replicas_timeout:type_name -> vttime.Duration - 303, // 59: vtctldata.EmergencyReparentShardResponse.promoted_primary:type_name -> topodata.TabletAlias - 299, // 60: vtctldata.EmergencyReparentShardResponse.events:type_name -> logutil.Event - 303, // 61: vtctldata.ExecuteFetchAsAppRequest.tablet_alias:type_name -> topodata.TabletAlias - 315, // 62: vtctldata.ExecuteFetchAsAppResponse.result:type_name -> query.QueryResult - 303, // 63: vtctldata.ExecuteFetchAsDBARequest.tablet_alias:type_name -> topodata.TabletAlias - 315, // 64: vtctldata.ExecuteFetchAsDBAResponse.result:type_name -> query.QueryResult - 303, // 65: vtctldata.ExecuteHookRequest.tablet_alias:type_name -> topodata.TabletAlias - 316, // 66: vtctldata.ExecuteHookRequest.tablet_hook_request:type_name -> tabletmanagerdata.ExecuteHookRequest - 317, // 67: vtctldata.ExecuteHookResponse.hook_result:type_name -> tabletmanagerdata.ExecuteHookResponse - 303, // 68: vtctldata.ExecuteMultiFetchAsDBARequest.tablet_alias:type_name -> topodata.TabletAlias - 315, // 69: vtctldata.ExecuteMultiFetchAsDBAResponse.results:type_name -> query.QueryResult - 264, // 70: vtctldata.FindAllShardsInKeyspaceResponse.shards:type_name -> vtctldata.FindAllShardsInKeyspaceResponse.ShardsEntry - 265, // 71: vtctldata.ForceCutOverSchemaMigrationResponse.rows_affected_by_shard:type_name -> vtctldata.ForceCutOverSchemaMigrationResponse.RowsAffectedByShardEntry - 318, // 72: vtctldata.GetBackupsResponse.backups:type_name -> mysqlctl.BackupInfo - 306, // 73: vtctldata.GetCellInfoResponse.cell_info:type_name -> topodata.CellInfo - 266, // 74: vtctldata.GetCellsAliasesResponse.aliases:type_name -> vtctldata.GetCellsAliasesResponse.AliasesEntry - 303, // 75: vtctldata.GetFullStatusRequest.tablet_alias:type_name -> topodata.TabletAlias - 319, // 76: vtctldata.GetFullStatusResponse.status:type_name -> replicationdata.FullStatus - 8, // 77: vtctldata.GetKeyspacesResponse.keyspaces:type_name -> vtctldata.Keyspace - 8, // 78: vtctldata.GetKeyspaceResponse.keyspace:type_name -> vtctldata.Keyspace - 303, // 79: vtctldata.GetPermissionsRequest.tablet_alias:type_name -> topodata.TabletAlias - 320, // 80: vtctldata.GetPermissionsResponse.permissions:type_name -> tabletmanagerdata.Permissions - 307, // 81: vtctldata.GetKeyspaceRoutingRulesResponse.keyspace_routing_rules:type_name -> vschema.KeyspaceRoutingRules - 308, // 82: vtctldata.GetRoutingRulesResponse.routing_rules:type_name -> vschema.RoutingRules - 303, // 83: vtctldata.GetSchemaRequest.tablet_alias:type_name -> topodata.TabletAlias - 321, // 84: vtctldata.GetSchemaResponse.schema:type_name -> tabletmanagerdata.SchemaDefinition - 3, // 85: vtctldata.GetSchemaMigrationsRequest.status:type_name -> vtctldata.SchemaMigration.Status - 304, // 86: vtctldata.GetSchemaMigrationsRequest.recent:type_name -> vttime.Duration - 1, // 87: vtctldata.GetSchemaMigrationsRequest.order:type_name -> vtctldata.QueryOrdering - 9, // 88: vtctldata.GetSchemaMigrationsResponse.migrations:type_name -> vtctldata.SchemaMigration - 267, // 89: vtctldata.GetShardReplicationResponse.shard_replication_by_cell:type_name -> vtctldata.GetShardReplicationResponse.ShardReplicationByCellEntry - 10, // 90: vtctldata.GetShardResponse.shard:type_name -> vtctldata.Shard - 309, // 91: vtctldata.GetShardRoutingRulesResponse.shard_routing_rules:type_name -> vschema.ShardRoutingRules - 268, // 92: vtctldata.GetSrvKeyspaceNamesResponse.names:type_name -> vtctldata.GetSrvKeyspaceNamesResponse.NamesEntry - 270, // 93: vtctldata.GetSrvKeyspacesResponse.srv_keyspaces:type_name -> vtctldata.GetSrvKeyspacesResponse.SrvKeyspacesEntry - 322, // 94: vtctldata.UpdateThrottlerConfigRequest.throttled_app:type_name -> topodata.ThrottledAppRule - 323, // 95: vtctldata.GetSrvVSchemaResponse.srv_v_schema:type_name -> vschema.SrvVSchema - 271, // 96: vtctldata.GetSrvVSchemasResponse.srv_v_schemas:type_name -> vtctldata.GetSrvVSchemasResponse.SrvVSchemasEntry - 303, // 97: vtctldata.GetTabletRequest.tablet_alias:type_name -> topodata.TabletAlias - 313, // 98: vtctldata.GetTabletResponse.tablet:type_name -> topodata.Tablet - 303, // 99: vtctldata.GetTabletsRequest.tablet_aliases:type_name -> topodata.TabletAlias - 312, // 100: vtctldata.GetTabletsRequest.tablet_type:type_name -> topodata.TabletType - 313, // 101: vtctldata.GetTabletsResponse.tablets:type_name -> topodata.Tablet - 303, // 102: vtctldata.GetThrottlerStatusRequest.tablet_alias:type_name -> topodata.TabletAlias - 273, // 103: vtctldata.GetThrottlerStatusResponse.aggregated_metrics:type_name -> vtctldata.GetThrottlerStatusResponse.AggregatedMetricsEntry - 274, // 104: vtctldata.GetThrottlerStatusResponse.metric_thresholds:type_name -> vtctldata.GetThrottlerStatusResponse.MetricThresholdsEntry - 276, // 105: vtctldata.GetThrottlerStatusResponse.metrics_health:type_name -> vtctldata.GetThrottlerStatusResponse.MetricsHealthEntry - 277, // 106: vtctldata.GetThrottlerStatusResponse.throttled_apps:type_name -> vtctldata.GetThrottlerStatusResponse.ThrottledAppsEntry - 278, // 107: vtctldata.GetThrottlerStatusResponse.app_checked_metrics:type_name -> vtctldata.GetThrottlerStatusResponse.AppCheckedMetricsEntry - 280, // 108: vtctldata.GetThrottlerStatusResponse.recent_apps:type_name -> vtctldata.GetThrottlerStatusResponse.RecentAppsEntry - 118, // 109: vtctldata.GetTopologyPathResponse.cell:type_name -> vtctldata.TopologyCell - 303, // 110: vtctldata.GetVersionRequest.tablet_alias:type_name -> topodata.TabletAlias - 311, // 111: vtctldata.GetVSchemaResponse.v_schema:type_name -> vschema.Keyspace - 12, // 112: vtctldata.GetWorkflowsResponse.workflows:type_name -> vtctldata.Workflow - 303, // 113: vtctldata.InitShardPrimaryRequest.primary_elect_tablet_alias:type_name -> topodata.TabletAlias - 304, // 114: vtctldata.InitShardPrimaryRequest.wait_replicas_timeout:type_name -> vttime.Duration - 299, // 115: vtctldata.InitShardPrimaryResponse.events:type_name -> logutil.Event - 281, // 116: vtctldata.LaunchSchemaMigrationResponse.rows_affected_by_shard:type_name -> vtctldata.LaunchSchemaMigrationResponse.RowsAffectedByShardEntry - 311, // 117: vtctldata.LookupVindexCreateRequest.vindex:type_name -> vschema.Keyspace - 312, // 118: vtctldata.LookupVindexCreateRequest.tablet_types:type_name -> topodata.TabletType - 300, // 119: vtctldata.LookupVindexCreateRequest.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference - 7, // 120: vtctldata.MaterializeCreateRequest.settings:type_name -> vtctldata.MaterializeSettings - 312, // 121: vtctldata.MigrateCreateRequest.tablet_types:type_name -> topodata.TabletType - 300, // 122: vtctldata.MigrateCreateRequest.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference - 312, // 123: vtctldata.MoveTablesCreateRequest.tablet_types:type_name -> topodata.TabletType - 300, // 124: vtctldata.MoveTablesCreateRequest.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference - 11, // 125: vtctldata.MoveTablesCreateRequest.workflow_options:type_name -> vtctldata.WorkflowOptions - 282, // 126: vtctldata.MoveTablesCreateResponse.details:type_name -> vtctldata.MoveTablesCreateResponse.TabletInfo - 303, // 127: vtctldata.PingTabletRequest.tablet_alias:type_name -> topodata.TabletAlias - 303, // 128: vtctldata.PlannedReparentShardRequest.new_primary:type_name -> topodata.TabletAlias - 303, // 129: vtctldata.PlannedReparentShardRequest.avoid_primary:type_name -> topodata.TabletAlias - 304, // 130: vtctldata.PlannedReparentShardRequest.wait_replicas_timeout:type_name -> vttime.Duration - 304, // 131: vtctldata.PlannedReparentShardRequest.tolerable_replication_lag:type_name -> vttime.Duration - 303, // 132: vtctldata.PlannedReparentShardResponse.promoted_primary:type_name -> topodata.TabletAlias - 299, // 133: vtctldata.PlannedReparentShardResponse.events:type_name -> logutil.Event - 303, // 134: vtctldata.RefreshStateRequest.tablet_alias:type_name -> topodata.TabletAlias - 303, // 135: vtctldata.ReloadSchemaRequest.tablet_alias:type_name -> topodata.TabletAlias - 299, // 136: vtctldata.ReloadSchemaKeyspaceResponse.events:type_name -> logutil.Event - 299, // 137: vtctldata.ReloadSchemaShardResponse.events:type_name -> logutil.Event - 303, // 138: vtctldata.ReparentTabletRequest.tablet:type_name -> topodata.TabletAlias - 303, // 139: vtctldata.ReparentTabletResponse.primary:type_name -> topodata.TabletAlias - 312, // 140: vtctldata.ReshardCreateRequest.tablet_types:type_name -> topodata.TabletType - 300, // 141: vtctldata.ReshardCreateRequest.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference - 303, // 142: vtctldata.RestoreFromBackupRequest.tablet_alias:type_name -> topodata.TabletAlias - 302, // 143: vtctldata.RestoreFromBackupRequest.backup_time:type_name -> vttime.Time - 302, // 144: vtctldata.RestoreFromBackupRequest.restore_to_timestamp:type_name -> vttime.Time - 303, // 145: vtctldata.RestoreFromBackupResponse.tablet_alias:type_name -> topodata.TabletAlias - 299, // 146: vtctldata.RestoreFromBackupResponse.event:type_name -> logutil.Event - 283, // 147: vtctldata.RetrySchemaMigrationResponse.rows_affected_by_shard:type_name -> vtctldata.RetrySchemaMigrationResponse.RowsAffectedByShardEntry - 303, // 148: vtctldata.RunHealthCheckRequest.tablet_alias:type_name -> topodata.TabletAlias - 301, // 149: vtctldata.SetKeyspaceDurabilityPolicyResponse.keyspace:type_name -> topodata.Keyspace - 301, // 150: vtctldata.SetKeyspaceShardingInfoResponse.keyspace:type_name -> topodata.Keyspace - 305, // 151: vtctldata.SetShardIsPrimaryServingResponse.shard:type_name -> topodata.Shard - 312, // 152: vtctldata.SetShardTabletControlRequest.tablet_type:type_name -> topodata.TabletType - 305, // 153: vtctldata.SetShardTabletControlResponse.shard:type_name -> topodata.Shard - 303, // 154: vtctldata.SetWritableRequest.tablet_alias:type_name -> topodata.TabletAlias - 303, // 155: vtctldata.ShardReplicationAddRequest.tablet_alias:type_name -> topodata.TabletAlias - 324, // 156: vtctldata.ShardReplicationFixResponse.error:type_name -> topodata.ShardReplicationError - 284, // 157: vtctldata.ShardReplicationPositionsResponse.replication_statuses:type_name -> vtctldata.ShardReplicationPositionsResponse.ReplicationStatusesEntry - 285, // 158: vtctldata.ShardReplicationPositionsResponse.tablet_map:type_name -> vtctldata.ShardReplicationPositionsResponse.TabletMapEntry - 303, // 159: vtctldata.ShardReplicationRemoveRequest.tablet_alias:type_name -> topodata.TabletAlias - 303, // 160: vtctldata.SleepTabletRequest.tablet_alias:type_name -> topodata.TabletAlias - 304, // 161: vtctldata.SleepTabletRequest.duration:type_name -> vttime.Duration - 325, // 162: vtctldata.SourceShardAddRequest.key_range:type_name -> topodata.KeyRange - 305, // 163: vtctldata.SourceShardAddResponse.shard:type_name -> topodata.Shard - 305, // 164: vtctldata.SourceShardDeleteResponse.shard:type_name -> topodata.Shard - 303, // 165: vtctldata.StartReplicationRequest.tablet_alias:type_name -> topodata.TabletAlias - 303, // 166: vtctldata.StopReplicationRequest.tablet_alias:type_name -> topodata.TabletAlias - 303, // 167: vtctldata.TabletExternallyReparentedRequest.tablet:type_name -> topodata.TabletAlias - 303, // 168: vtctldata.TabletExternallyReparentedResponse.new_primary:type_name -> topodata.TabletAlias - 303, // 169: vtctldata.TabletExternallyReparentedResponse.old_primary:type_name -> topodata.TabletAlias - 306, // 170: vtctldata.UpdateCellInfoRequest.cell_info:type_name -> topodata.CellInfo - 306, // 171: vtctldata.UpdateCellInfoResponse.cell_info:type_name -> topodata.CellInfo - 326, // 172: vtctldata.UpdateCellsAliasRequest.cells_alias:type_name -> topodata.CellsAlias - 326, // 173: vtctldata.UpdateCellsAliasResponse.cells_alias:type_name -> topodata.CellsAlias - 286, // 174: vtctldata.ValidateResponse.results_by_keyspace:type_name -> vtctldata.ValidateResponse.ResultsByKeyspaceEntry - 287, // 175: vtctldata.ValidateKeyspaceResponse.results_by_shard:type_name -> vtctldata.ValidateKeyspaceResponse.ResultsByShardEntry - 288, // 176: vtctldata.ValidateSchemaKeyspaceResponse.results_by_shard:type_name -> vtctldata.ValidateSchemaKeyspaceResponse.ResultsByShardEntry - 289, // 177: vtctldata.ValidateVersionKeyspaceResponse.results_by_shard:type_name -> vtctldata.ValidateVersionKeyspaceResponse.ResultsByShardEntry - 290, // 178: vtctldata.ValidateVSchemaResponse.results_by_shard:type_name -> vtctldata.ValidateVSchemaResponse.ResultsByShardEntry - 312, // 179: vtctldata.VDiffCreateRequest.tablet_types:type_name -> topodata.TabletType - 300, // 180: vtctldata.VDiffCreateRequest.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference - 304, // 181: vtctldata.VDiffCreateRequest.filtered_replication_wait_time:type_name -> vttime.Duration - 304, // 182: vtctldata.VDiffCreateRequest.wait_update_interval:type_name -> vttime.Duration - 304, // 183: vtctldata.VDiffCreateRequest.max_diff_duration:type_name -> vttime.Duration - 291, // 184: vtctldata.VDiffShowResponse.tablet_responses:type_name -> vtctldata.VDiffShowResponse.TabletResponsesEntry - 292, // 185: vtctldata.WorkflowDeleteResponse.details:type_name -> vtctldata.WorkflowDeleteResponse.TabletInfo - 296, // 186: vtctldata.WorkflowStatusResponse.table_copy_state:type_name -> vtctldata.WorkflowStatusResponse.TableCopyStateEntry - 297, // 187: vtctldata.WorkflowStatusResponse.shard_streams:type_name -> vtctldata.WorkflowStatusResponse.ShardStreamsEntry - 312, // 188: vtctldata.WorkflowSwitchTrafficRequest.tablet_types:type_name -> topodata.TabletType - 304, // 189: vtctldata.WorkflowSwitchTrafficRequest.max_replication_lag_allowed:type_name -> vttime.Duration - 304, // 190: vtctldata.WorkflowSwitchTrafficRequest.timeout:type_name -> vttime.Duration - 327, // 191: vtctldata.WorkflowUpdateRequest.tablet_request:type_name -> tabletmanagerdata.UpdateVReplicationWorkflowRequest - 298, // 192: vtctldata.WorkflowUpdateResponse.details:type_name -> vtctldata.WorkflowUpdateResponse.TabletInfo - 251, // 193: vtctldata.Workflow.ShardStreamsEntry.value:type_name -> vtctldata.Workflow.ShardStream - 252, // 194: vtctldata.Workflow.ShardStream.streams:type_name -> vtctldata.Workflow.Stream - 328, // 195: vtctldata.Workflow.ShardStream.tablet_controls:type_name -> topodata.Shard.TabletControl - 303, // 196: vtctldata.Workflow.Stream.tablet:type_name -> topodata.TabletAlias - 329, // 197: vtctldata.Workflow.Stream.binlog_source:type_name -> binlogdata.BinlogSource - 302, // 198: vtctldata.Workflow.Stream.transaction_timestamp:type_name -> vttime.Time - 302, // 199: vtctldata.Workflow.Stream.time_updated:type_name -> vttime.Time - 253, // 200: vtctldata.Workflow.Stream.copy_states:type_name -> vtctldata.Workflow.Stream.CopyState - 254, // 201: vtctldata.Workflow.Stream.logs:type_name -> vtctldata.Workflow.Stream.Log - 255, // 202: vtctldata.Workflow.Stream.throttler_status:type_name -> vtctldata.Workflow.Stream.ThrottlerStatus - 312, // 203: vtctldata.Workflow.Stream.tablet_types:type_name -> topodata.TabletType - 300, // 204: vtctldata.Workflow.Stream.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference - 302, // 205: vtctldata.Workflow.Stream.Log.created_at:type_name -> vttime.Time - 302, // 206: vtctldata.Workflow.Stream.Log.updated_at:type_name -> vttime.Time - 302, // 207: vtctldata.Workflow.Stream.ThrottlerStatus.time_throttled:type_name -> vttime.Time - 258, // 208: vtctldata.ApplyVSchemaResponse.UnknownVindexParamsEntry.value:type_name -> vtctldata.ApplyVSchemaResponse.ParamList - 260, // 209: vtctldata.CheckThrottlerResponse.MetricsEntry.value:type_name -> vtctldata.CheckThrottlerResponse.Metric - 10, // 210: vtctldata.FindAllShardsInKeyspaceResponse.ShardsEntry.value:type_name -> vtctldata.Shard - 326, // 211: vtctldata.GetCellsAliasesResponse.AliasesEntry.value:type_name -> topodata.CellsAlias - 330, // 212: vtctldata.GetShardReplicationResponse.ShardReplicationByCellEntry.value:type_name -> topodata.ShardReplication - 269, // 213: vtctldata.GetSrvKeyspaceNamesResponse.NamesEntry.value:type_name -> vtctldata.GetSrvKeyspaceNamesResponse.NameList - 331, // 214: vtctldata.GetSrvKeyspacesResponse.SrvKeyspacesEntry.value:type_name -> topodata.SrvKeyspace - 323, // 215: vtctldata.GetSrvVSchemasResponse.SrvVSchemasEntry.value:type_name -> vschema.SrvVSchema - 272, // 216: vtctldata.GetThrottlerStatusResponse.AggregatedMetricsEntry.value:type_name -> vtctldata.GetThrottlerStatusResponse.MetricResult - 302, // 217: vtctldata.GetThrottlerStatusResponse.MetricHealth.last_healthy_at:type_name -> vttime.Time - 275, // 218: vtctldata.GetThrottlerStatusResponse.MetricsHealthEntry.value:type_name -> vtctldata.GetThrottlerStatusResponse.MetricHealth - 322, // 219: vtctldata.GetThrottlerStatusResponse.ThrottledAppsEntry.value:type_name -> topodata.ThrottledAppRule - 302, // 220: vtctldata.GetThrottlerStatusResponse.RecentApp.checked_at:type_name -> vttime.Time - 279, // 221: vtctldata.GetThrottlerStatusResponse.RecentAppsEntry.value:type_name -> vtctldata.GetThrottlerStatusResponse.RecentApp - 303, // 222: vtctldata.MoveTablesCreateResponse.TabletInfo.tablet:type_name -> topodata.TabletAlias - 332, // 223: vtctldata.ShardReplicationPositionsResponse.ReplicationStatusesEntry.value:type_name -> replicationdata.Status - 313, // 224: vtctldata.ShardReplicationPositionsResponse.TabletMapEntry.value:type_name -> topodata.Tablet - 220, // 225: vtctldata.ValidateResponse.ResultsByKeyspaceEntry.value:type_name -> vtctldata.ValidateKeyspaceResponse - 224, // 226: vtctldata.ValidateKeyspaceResponse.ResultsByShardEntry.value:type_name -> vtctldata.ValidateShardResponse - 224, // 227: vtctldata.ValidateSchemaKeyspaceResponse.ResultsByShardEntry.value:type_name -> vtctldata.ValidateShardResponse - 224, // 228: vtctldata.ValidateVersionKeyspaceResponse.ResultsByShardEntry.value:type_name -> vtctldata.ValidateShardResponse - 224, // 229: vtctldata.ValidateVSchemaResponse.ResultsByShardEntry.value:type_name -> vtctldata.ValidateShardResponse - 333, // 230: vtctldata.VDiffShowResponse.TabletResponsesEntry.value:type_name -> tabletmanagerdata.VDiffResponse - 303, // 231: vtctldata.WorkflowDeleteResponse.TabletInfo.tablet:type_name -> topodata.TabletAlias - 303, // 232: vtctldata.WorkflowStatusResponse.ShardStreamState.tablet:type_name -> topodata.TabletAlias - 294, // 233: vtctldata.WorkflowStatusResponse.ShardStreams.streams:type_name -> vtctldata.WorkflowStatusResponse.ShardStreamState - 293, // 234: vtctldata.WorkflowStatusResponse.TableCopyStateEntry.value:type_name -> vtctldata.WorkflowStatusResponse.TableCopyState - 295, // 235: vtctldata.WorkflowStatusResponse.ShardStreamsEntry.value:type_name -> vtctldata.WorkflowStatusResponse.ShardStreams - 303, // 236: vtctldata.WorkflowUpdateResponse.TabletInfo.tablet:type_name -> topodata.TabletAlias - 237, // [237:237] is the sub-list for method output_type - 237, // [237:237] is the sub-list for method input_type - 237, // [237:237] is the sub-list for extension type_name - 237, // [237:237] is the sub-list for extension extendee - 0, // [0:237] is the sub-list for field type_name + 299, // 26: vtctldata.AddCellInfoRequest.cell_info:type_name -> topodata.CellInfo + 300, // 27: vtctldata.ApplyKeyspaceRoutingRulesRequest.keyspace_routing_rules:type_name -> vschema.KeyspaceRoutingRules + 300, // 28: vtctldata.ApplyKeyspaceRoutingRulesResponse.keyspace_routing_rules:type_name -> vschema.KeyspaceRoutingRules + 301, // 29: vtctldata.ApplyRoutingRulesRequest.routing_rules:type_name -> vschema.RoutingRules + 302, // 30: vtctldata.ApplyShardRoutingRulesRequest.shard_routing_rules:type_name -> vschema.ShardRoutingRules + 297, // 31: vtctldata.ApplySchemaRequest.wait_replicas_timeout:type_name -> vttime.Duration + 303, // 32: vtctldata.ApplySchemaRequest.caller_id:type_name -> vtrpc.CallerID + 260, // 33: vtctldata.ApplySchemaResponse.rows_affected_by_shard:type_name -> vtctldata.ApplySchemaResponse.RowsAffectedByShardEntry + 304, // 34: vtctldata.ApplyVSchemaRequest.v_schema:type_name -> vschema.Keyspace + 304, // 35: vtctldata.ApplyVSchemaResponse.v_schema:type_name -> vschema.Keyspace + 261, // 36: vtctldata.ApplyVSchemaResponse.unknown_vindex_params:type_name -> vtctldata.ApplyVSchemaResponse.UnknownVindexParamsEntry + 296, // 37: vtctldata.BackupRequest.tablet_alias:type_name -> topodata.TabletAlias + 296, // 38: vtctldata.BackupResponse.tablet_alias:type_name -> topodata.TabletAlias + 292, // 39: vtctldata.BackupResponse.event:type_name -> logutil.Event + 263, // 40: vtctldata.CancelSchemaMigrationResponse.rows_affected_by_shard:type_name -> vtctldata.CancelSchemaMigrationResponse.RowsAffectedByShardEntry + 296, // 41: vtctldata.ChangeTabletTypeRequest.tablet_alias:type_name -> topodata.TabletAlias + 305, // 42: vtctldata.ChangeTabletTypeRequest.db_type:type_name -> topodata.TabletType + 306, // 43: vtctldata.ChangeTabletTypeResponse.before_tablet:type_name -> topodata.Tablet + 306, // 44: vtctldata.ChangeTabletTypeResponse.after_tablet:type_name -> topodata.Tablet + 296, // 45: vtctldata.CheckThrottlerRequest.tablet_alias:type_name -> topodata.TabletAlias + 296, // 46: vtctldata.CheckThrottlerResponse.tablet_alias:type_name -> topodata.TabletAlias + 307, // 47: vtctldata.CheckThrottlerResponse.Check:type_name -> tabletmanagerdata.CheckThrottlerResponse + 264, // 48: vtctldata.CleanupSchemaMigrationResponse.rows_affected_by_shard:type_name -> vtctldata.CleanupSchemaMigrationResponse.RowsAffectedByShardEntry + 265, // 49: vtctldata.CompleteSchemaMigrationResponse.rows_affected_by_shard:type_name -> vtctldata.CompleteSchemaMigrationResponse.RowsAffectedByShardEntry + 308, // 50: vtctldata.CreateKeyspaceRequest.type:type_name -> topodata.KeyspaceType + 295, // 51: vtctldata.CreateKeyspaceRequest.snapshot_time:type_name -> vttime.Time + 8, // 52: vtctldata.CreateKeyspaceResponse.keyspace:type_name -> vtctldata.Keyspace + 8, // 53: vtctldata.CreateShardResponse.keyspace:type_name -> vtctldata.Keyspace + 10, // 54: vtctldata.CreateShardResponse.shard:type_name -> vtctldata.Shard + 10, // 55: vtctldata.DeleteShardsRequest.shards:type_name -> vtctldata.Shard + 296, // 56: vtctldata.DeleteTabletsRequest.tablet_aliases:type_name -> topodata.TabletAlias + 296, // 57: vtctldata.EmergencyReparentShardRequest.new_primary:type_name -> topodata.TabletAlias + 296, // 58: vtctldata.EmergencyReparentShardRequest.ignore_replicas:type_name -> topodata.TabletAlias + 297, // 59: vtctldata.EmergencyReparentShardRequest.wait_replicas_timeout:type_name -> vttime.Duration + 296, // 60: vtctldata.EmergencyReparentShardResponse.promoted_primary:type_name -> topodata.TabletAlias + 292, // 61: vtctldata.EmergencyReparentShardResponse.events:type_name -> logutil.Event + 296, // 62: vtctldata.ExecuteFetchAsAppRequest.tablet_alias:type_name -> topodata.TabletAlias + 309, // 63: vtctldata.ExecuteFetchAsAppResponse.result:type_name -> query.QueryResult + 296, // 64: vtctldata.ExecuteFetchAsDBARequest.tablet_alias:type_name -> topodata.TabletAlias + 309, // 65: vtctldata.ExecuteFetchAsDBAResponse.result:type_name -> query.QueryResult + 296, // 66: vtctldata.ExecuteHookRequest.tablet_alias:type_name -> topodata.TabletAlias + 310, // 67: vtctldata.ExecuteHookRequest.tablet_hook_request:type_name -> tabletmanagerdata.ExecuteHookRequest + 311, // 68: vtctldata.ExecuteHookResponse.hook_result:type_name -> tabletmanagerdata.ExecuteHookResponse + 296, // 69: vtctldata.ExecuteMultiFetchAsDBARequest.tablet_alias:type_name -> topodata.TabletAlias + 309, // 70: vtctldata.ExecuteMultiFetchAsDBAResponse.results:type_name -> query.QueryResult + 266, // 71: vtctldata.FindAllShardsInKeyspaceResponse.shards:type_name -> vtctldata.FindAllShardsInKeyspaceResponse.ShardsEntry + 267, // 72: vtctldata.ForceCutOverSchemaMigrationResponse.rows_affected_by_shard:type_name -> vtctldata.ForceCutOverSchemaMigrationResponse.RowsAffectedByShardEntry + 312, // 73: vtctldata.GetBackupsResponse.backups:type_name -> mysqlctl.BackupInfo + 299, // 74: vtctldata.GetCellInfoResponse.cell_info:type_name -> topodata.CellInfo + 268, // 75: vtctldata.GetCellsAliasesResponse.aliases:type_name -> vtctldata.GetCellsAliasesResponse.AliasesEntry + 296, // 76: vtctldata.GetFullStatusRequest.tablet_alias:type_name -> topodata.TabletAlias + 313, // 77: vtctldata.GetFullStatusResponse.status:type_name -> replicationdata.FullStatus + 8, // 78: vtctldata.GetKeyspacesResponse.keyspaces:type_name -> vtctldata.Keyspace + 8, // 79: vtctldata.GetKeyspaceResponse.keyspace:type_name -> vtctldata.Keyspace + 296, // 80: vtctldata.GetPermissionsRequest.tablet_alias:type_name -> topodata.TabletAlias + 314, // 81: vtctldata.GetPermissionsResponse.permissions:type_name -> tabletmanagerdata.Permissions + 300, // 82: vtctldata.GetKeyspaceRoutingRulesResponse.keyspace_routing_rules:type_name -> vschema.KeyspaceRoutingRules + 301, // 83: vtctldata.GetRoutingRulesResponse.routing_rules:type_name -> vschema.RoutingRules + 296, // 84: vtctldata.GetSchemaRequest.tablet_alias:type_name -> topodata.TabletAlias + 315, // 85: vtctldata.GetSchemaResponse.schema:type_name -> tabletmanagerdata.SchemaDefinition + 3, // 86: vtctldata.GetSchemaMigrationsRequest.status:type_name -> vtctldata.SchemaMigration.Status + 297, // 87: vtctldata.GetSchemaMigrationsRequest.recent:type_name -> vttime.Duration + 1, // 88: vtctldata.GetSchemaMigrationsRequest.order:type_name -> vtctldata.QueryOrdering + 9, // 89: vtctldata.GetSchemaMigrationsResponse.migrations:type_name -> vtctldata.SchemaMigration + 269, // 90: vtctldata.GetShardReplicationResponse.shard_replication_by_cell:type_name -> vtctldata.GetShardReplicationResponse.ShardReplicationByCellEntry + 10, // 91: vtctldata.GetShardResponse.shard:type_name -> vtctldata.Shard + 302, // 92: vtctldata.GetShardRoutingRulesResponse.shard_routing_rules:type_name -> vschema.ShardRoutingRules + 270, // 93: vtctldata.GetSrvKeyspaceNamesResponse.names:type_name -> vtctldata.GetSrvKeyspaceNamesResponse.NamesEntry + 272, // 94: vtctldata.GetSrvKeyspacesResponse.srv_keyspaces:type_name -> vtctldata.GetSrvKeyspacesResponse.SrvKeyspacesEntry + 316, // 95: vtctldata.UpdateThrottlerConfigRequest.throttled_app:type_name -> topodata.ThrottledAppRule + 317, // 96: vtctldata.GetSrvVSchemaResponse.srv_v_schema:type_name -> vschema.SrvVSchema + 273, // 97: vtctldata.GetSrvVSchemasResponse.srv_v_schemas:type_name -> vtctldata.GetSrvVSchemasResponse.SrvVSchemasEntry + 296, // 98: vtctldata.GetTabletRequest.tablet_alias:type_name -> topodata.TabletAlias + 306, // 99: vtctldata.GetTabletResponse.tablet:type_name -> topodata.Tablet + 296, // 100: vtctldata.GetTabletsRequest.tablet_aliases:type_name -> topodata.TabletAlias + 305, // 101: vtctldata.GetTabletsRequest.tablet_type:type_name -> topodata.TabletType + 306, // 102: vtctldata.GetTabletsResponse.tablets:type_name -> topodata.Tablet + 296, // 103: vtctldata.GetThrottlerStatusRequest.tablet_alias:type_name -> topodata.TabletAlias + 318, // 104: vtctldata.GetThrottlerStatusResponse.status:type_name -> tabletmanagerdata.GetThrottlerStatusResponse + 118, // 105: vtctldata.GetTopologyPathResponse.cell:type_name -> vtctldata.TopologyCell + 296, // 106: vtctldata.GetVersionRequest.tablet_alias:type_name -> topodata.TabletAlias + 304, // 107: vtctldata.GetVSchemaResponse.v_schema:type_name -> vschema.Keyspace + 12, // 108: vtctldata.GetWorkflowsResponse.workflows:type_name -> vtctldata.Workflow + 296, // 109: vtctldata.InitShardPrimaryRequest.primary_elect_tablet_alias:type_name -> topodata.TabletAlias + 297, // 110: vtctldata.InitShardPrimaryRequest.wait_replicas_timeout:type_name -> vttime.Duration + 292, // 111: vtctldata.InitShardPrimaryResponse.events:type_name -> logutil.Event + 274, // 112: vtctldata.LaunchSchemaMigrationResponse.rows_affected_by_shard:type_name -> vtctldata.LaunchSchemaMigrationResponse.RowsAffectedByShardEntry + 304, // 113: vtctldata.LookupVindexCreateRequest.vindex:type_name -> vschema.Keyspace + 305, // 114: vtctldata.LookupVindexCreateRequest.tablet_types:type_name -> topodata.TabletType + 293, // 115: vtctldata.LookupVindexCreateRequest.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference + 7, // 116: vtctldata.MaterializeCreateRequest.settings:type_name -> vtctldata.MaterializeSettings + 305, // 117: vtctldata.MigrateCreateRequest.tablet_types:type_name -> topodata.TabletType + 293, // 118: vtctldata.MigrateCreateRequest.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference + 305, // 119: vtctldata.MoveTablesCreateRequest.tablet_types:type_name -> topodata.TabletType + 293, // 120: vtctldata.MoveTablesCreateRequest.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference + 11, // 121: vtctldata.MoveTablesCreateRequest.workflow_options:type_name -> vtctldata.WorkflowOptions + 275, // 122: vtctldata.MoveTablesCreateResponse.details:type_name -> vtctldata.MoveTablesCreateResponse.TabletInfo + 296, // 123: vtctldata.PingTabletRequest.tablet_alias:type_name -> topodata.TabletAlias + 296, // 124: vtctldata.PlannedReparentShardRequest.new_primary:type_name -> topodata.TabletAlias + 296, // 125: vtctldata.PlannedReparentShardRequest.avoid_primary:type_name -> topodata.TabletAlias + 297, // 126: vtctldata.PlannedReparentShardRequest.wait_replicas_timeout:type_name -> vttime.Duration + 297, // 127: vtctldata.PlannedReparentShardRequest.tolerable_replication_lag:type_name -> vttime.Duration + 296, // 128: vtctldata.PlannedReparentShardResponse.promoted_primary:type_name -> topodata.TabletAlias + 292, // 129: vtctldata.PlannedReparentShardResponse.events:type_name -> logutil.Event + 296, // 130: vtctldata.RefreshStateRequest.tablet_alias:type_name -> topodata.TabletAlias + 296, // 131: vtctldata.ReloadSchemaRequest.tablet_alias:type_name -> topodata.TabletAlias + 292, // 132: vtctldata.ReloadSchemaKeyspaceResponse.events:type_name -> logutil.Event + 292, // 133: vtctldata.ReloadSchemaShardResponse.events:type_name -> logutil.Event + 296, // 134: vtctldata.ReparentTabletRequest.tablet:type_name -> topodata.TabletAlias + 296, // 135: vtctldata.ReparentTabletResponse.primary:type_name -> topodata.TabletAlias + 305, // 136: vtctldata.ReshardCreateRequest.tablet_types:type_name -> topodata.TabletType + 293, // 137: vtctldata.ReshardCreateRequest.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference + 296, // 138: vtctldata.RestoreFromBackupRequest.tablet_alias:type_name -> topodata.TabletAlias + 295, // 139: vtctldata.RestoreFromBackupRequest.backup_time:type_name -> vttime.Time + 295, // 140: vtctldata.RestoreFromBackupRequest.restore_to_timestamp:type_name -> vttime.Time + 296, // 141: vtctldata.RestoreFromBackupResponse.tablet_alias:type_name -> topodata.TabletAlias + 292, // 142: vtctldata.RestoreFromBackupResponse.event:type_name -> logutil.Event + 276, // 143: vtctldata.RetrySchemaMigrationResponse.rows_affected_by_shard:type_name -> vtctldata.RetrySchemaMigrationResponse.RowsAffectedByShardEntry + 296, // 144: vtctldata.RunHealthCheckRequest.tablet_alias:type_name -> topodata.TabletAlias + 294, // 145: vtctldata.SetKeyspaceDurabilityPolicyResponse.keyspace:type_name -> topodata.Keyspace + 294, // 146: vtctldata.SetKeyspaceShardingInfoResponse.keyspace:type_name -> topodata.Keyspace + 298, // 147: vtctldata.SetShardIsPrimaryServingResponse.shard:type_name -> topodata.Shard + 305, // 148: vtctldata.SetShardTabletControlRequest.tablet_type:type_name -> topodata.TabletType + 298, // 149: vtctldata.SetShardTabletControlResponse.shard:type_name -> topodata.Shard + 296, // 150: vtctldata.SetWritableRequest.tablet_alias:type_name -> topodata.TabletAlias + 296, // 151: vtctldata.ShardReplicationAddRequest.tablet_alias:type_name -> topodata.TabletAlias + 319, // 152: vtctldata.ShardReplicationFixResponse.error:type_name -> topodata.ShardReplicationError + 277, // 153: vtctldata.ShardReplicationPositionsResponse.replication_statuses:type_name -> vtctldata.ShardReplicationPositionsResponse.ReplicationStatusesEntry + 278, // 154: vtctldata.ShardReplicationPositionsResponse.tablet_map:type_name -> vtctldata.ShardReplicationPositionsResponse.TabletMapEntry + 296, // 155: vtctldata.ShardReplicationRemoveRequest.tablet_alias:type_name -> topodata.TabletAlias + 296, // 156: vtctldata.SleepTabletRequest.tablet_alias:type_name -> topodata.TabletAlias + 297, // 157: vtctldata.SleepTabletRequest.duration:type_name -> vttime.Duration + 320, // 158: vtctldata.SourceShardAddRequest.key_range:type_name -> topodata.KeyRange + 298, // 159: vtctldata.SourceShardAddResponse.shard:type_name -> topodata.Shard + 298, // 160: vtctldata.SourceShardDeleteResponse.shard:type_name -> topodata.Shard + 296, // 161: vtctldata.StartReplicationRequest.tablet_alias:type_name -> topodata.TabletAlias + 296, // 162: vtctldata.StopReplicationRequest.tablet_alias:type_name -> topodata.TabletAlias + 296, // 163: vtctldata.TabletExternallyReparentedRequest.tablet:type_name -> topodata.TabletAlias + 296, // 164: vtctldata.TabletExternallyReparentedResponse.new_primary:type_name -> topodata.TabletAlias + 296, // 165: vtctldata.TabletExternallyReparentedResponse.old_primary:type_name -> topodata.TabletAlias + 299, // 166: vtctldata.UpdateCellInfoRequest.cell_info:type_name -> topodata.CellInfo + 299, // 167: vtctldata.UpdateCellInfoResponse.cell_info:type_name -> topodata.CellInfo + 321, // 168: vtctldata.UpdateCellsAliasRequest.cells_alias:type_name -> topodata.CellsAlias + 321, // 169: vtctldata.UpdateCellsAliasResponse.cells_alias:type_name -> topodata.CellsAlias + 279, // 170: vtctldata.ValidateResponse.results_by_keyspace:type_name -> vtctldata.ValidateResponse.ResultsByKeyspaceEntry + 280, // 171: vtctldata.ValidateKeyspaceResponse.results_by_shard:type_name -> vtctldata.ValidateKeyspaceResponse.ResultsByShardEntry + 281, // 172: vtctldata.ValidateSchemaKeyspaceResponse.results_by_shard:type_name -> vtctldata.ValidateSchemaKeyspaceResponse.ResultsByShardEntry + 282, // 173: vtctldata.ValidateVersionKeyspaceResponse.results_by_shard:type_name -> vtctldata.ValidateVersionKeyspaceResponse.ResultsByShardEntry + 283, // 174: vtctldata.ValidateVSchemaResponse.results_by_shard:type_name -> vtctldata.ValidateVSchemaResponse.ResultsByShardEntry + 305, // 175: vtctldata.VDiffCreateRequest.tablet_types:type_name -> topodata.TabletType + 293, // 176: vtctldata.VDiffCreateRequest.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference + 297, // 177: vtctldata.VDiffCreateRequest.filtered_replication_wait_time:type_name -> vttime.Duration + 297, // 178: vtctldata.VDiffCreateRequest.wait_update_interval:type_name -> vttime.Duration + 297, // 179: vtctldata.VDiffCreateRequest.max_diff_duration:type_name -> vttime.Duration + 284, // 180: vtctldata.VDiffShowResponse.tablet_responses:type_name -> vtctldata.VDiffShowResponse.TabletResponsesEntry + 285, // 181: vtctldata.WorkflowDeleteResponse.details:type_name -> vtctldata.WorkflowDeleteResponse.TabletInfo + 289, // 182: vtctldata.WorkflowStatusResponse.table_copy_state:type_name -> vtctldata.WorkflowStatusResponse.TableCopyStateEntry + 290, // 183: vtctldata.WorkflowStatusResponse.shard_streams:type_name -> vtctldata.WorkflowStatusResponse.ShardStreamsEntry + 305, // 184: vtctldata.WorkflowSwitchTrafficRequest.tablet_types:type_name -> topodata.TabletType + 297, // 185: vtctldata.WorkflowSwitchTrafficRequest.max_replication_lag_allowed:type_name -> vttime.Duration + 297, // 186: vtctldata.WorkflowSwitchTrafficRequest.timeout:type_name -> vttime.Duration + 322, // 187: vtctldata.WorkflowUpdateRequest.tablet_request:type_name -> tabletmanagerdata.UpdateVReplicationWorkflowRequest + 291, // 188: vtctldata.WorkflowUpdateResponse.details:type_name -> vtctldata.WorkflowUpdateResponse.TabletInfo + 323, // 189: vtctldata.GetMirrorRulesResponse.mirror_rules:type_name -> vschema.MirrorRules + 305, // 190: vtctldata.WorkflowMirrorTrafficRequest.tablet_types:type_name -> topodata.TabletType + 255, // 191: vtctldata.Workflow.ShardStreamsEntry.value:type_name -> vtctldata.Workflow.ShardStream + 256, // 192: vtctldata.Workflow.ShardStream.streams:type_name -> vtctldata.Workflow.Stream + 324, // 193: vtctldata.Workflow.ShardStream.tablet_controls:type_name -> topodata.Shard.TabletControl + 296, // 194: vtctldata.Workflow.Stream.tablet:type_name -> topodata.TabletAlias + 325, // 195: vtctldata.Workflow.Stream.binlog_source:type_name -> binlogdata.BinlogSource + 295, // 196: vtctldata.Workflow.Stream.transaction_timestamp:type_name -> vttime.Time + 295, // 197: vtctldata.Workflow.Stream.time_updated:type_name -> vttime.Time + 257, // 198: vtctldata.Workflow.Stream.copy_states:type_name -> vtctldata.Workflow.Stream.CopyState + 258, // 199: vtctldata.Workflow.Stream.logs:type_name -> vtctldata.Workflow.Stream.Log + 259, // 200: vtctldata.Workflow.Stream.throttler_status:type_name -> vtctldata.Workflow.Stream.ThrottlerStatus + 305, // 201: vtctldata.Workflow.Stream.tablet_types:type_name -> topodata.TabletType + 293, // 202: vtctldata.Workflow.Stream.tablet_selection_preference:type_name -> tabletmanagerdata.TabletSelectionPreference + 295, // 203: vtctldata.Workflow.Stream.Log.created_at:type_name -> vttime.Time + 295, // 204: vtctldata.Workflow.Stream.Log.updated_at:type_name -> vttime.Time + 295, // 205: vtctldata.Workflow.Stream.ThrottlerStatus.time_throttled:type_name -> vttime.Time + 262, // 206: vtctldata.ApplyVSchemaResponse.UnknownVindexParamsEntry.value:type_name -> vtctldata.ApplyVSchemaResponse.ParamList + 10, // 207: vtctldata.FindAllShardsInKeyspaceResponse.ShardsEntry.value:type_name -> vtctldata.Shard + 321, // 208: vtctldata.GetCellsAliasesResponse.AliasesEntry.value:type_name -> topodata.CellsAlias + 326, // 209: vtctldata.GetShardReplicationResponse.ShardReplicationByCellEntry.value:type_name -> topodata.ShardReplication + 271, // 210: vtctldata.GetSrvKeyspaceNamesResponse.NamesEntry.value:type_name -> vtctldata.GetSrvKeyspaceNamesResponse.NameList + 327, // 211: vtctldata.GetSrvKeyspacesResponse.SrvKeyspacesEntry.value:type_name -> topodata.SrvKeyspace + 317, // 212: vtctldata.GetSrvVSchemasResponse.SrvVSchemasEntry.value:type_name -> vschema.SrvVSchema + 296, // 213: vtctldata.MoveTablesCreateResponse.TabletInfo.tablet:type_name -> topodata.TabletAlias + 328, // 214: vtctldata.ShardReplicationPositionsResponse.ReplicationStatusesEntry.value:type_name -> replicationdata.Status + 306, // 215: vtctldata.ShardReplicationPositionsResponse.TabletMapEntry.value:type_name -> topodata.Tablet + 220, // 216: vtctldata.ValidateResponse.ResultsByKeyspaceEntry.value:type_name -> vtctldata.ValidateKeyspaceResponse + 224, // 217: vtctldata.ValidateKeyspaceResponse.ResultsByShardEntry.value:type_name -> vtctldata.ValidateShardResponse + 224, // 218: vtctldata.ValidateSchemaKeyspaceResponse.ResultsByShardEntry.value:type_name -> vtctldata.ValidateShardResponse + 224, // 219: vtctldata.ValidateVersionKeyspaceResponse.ResultsByShardEntry.value:type_name -> vtctldata.ValidateShardResponse + 224, // 220: vtctldata.ValidateVSchemaResponse.ResultsByShardEntry.value:type_name -> vtctldata.ValidateShardResponse + 329, // 221: vtctldata.VDiffShowResponse.TabletResponsesEntry.value:type_name -> tabletmanagerdata.VDiffResponse + 296, // 222: vtctldata.WorkflowDeleteResponse.TabletInfo.tablet:type_name -> topodata.TabletAlias + 296, // 223: vtctldata.WorkflowStatusResponse.ShardStreamState.tablet:type_name -> topodata.TabletAlias + 287, // 224: vtctldata.WorkflowStatusResponse.ShardStreams.streams:type_name -> vtctldata.WorkflowStatusResponse.ShardStreamState + 286, // 225: vtctldata.WorkflowStatusResponse.TableCopyStateEntry.value:type_name -> vtctldata.WorkflowStatusResponse.TableCopyState + 288, // 226: vtctldata.WorkflowStatusResponse.ShardStreamsEntry.value:type_name -> vtctldata.WorkflowStatusResponse.ShardStreams + 296, // 227: vtctldata.WorkflowUpdateResponse.TabletInfo.tablet:type_name -> topodata.TabletAlias + 228, // [228:228] is the sub-list for method output_type + 228, // [228:228] is the sub-list for method input_type + 228, // [228:228] is the sub-list for extension type_name + 228, // [228:228] is the sub-list for extension extendee + 0, // [0:228] is the sub-list for field type_name } func init() { file_vtctldata_proto_init() } @@ -22966,8 +22586,8 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[246].Exporter = func(v any, i int) any { - switch v := v.(*Workflow_ReplicationLocation); i { + file_vtctldata_proto_msgTypes[245].Exporter = func(v any, i int) any { + switch v := v.(*GetMirrorRulesRequest); i { case 0: return &v.state case 1: @@ -22978,8 +22598,8 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[247].Exporter = func(v any, i int) any { - switch v := v.(*Workflow_ShardStream); i { + file_vtctldata_proto_msgTypes[246].Exporter = func(v any, i int) any { + switch v := v.(*GetMirrorRulesResponse); i { case 0: return &v.state case 1: @@ -22990,8 +22610,8 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[248].Exporter = func(v any, i int) any { - switch v := v.(*Workflow_Stream); i { + file_vtctldata_proto_msgTypes[247].Exporter = func(v any, i int) any { + switch v := v.(*WorkflowMirrorTrafficRequest); i { case 0: return &v.state case 1: @@ -23002,8 +22622,8 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[249].Exporter = func(v any, i int) any { - switch v := v.(*Workflow_Stream_CopyState); i { + file_vtctldata_proto_msgTypes[248].Exporter = func(v any, i int) any { + switch v := v.(*WorkflowMirrorTrafficResponse); i { case 0: return &v.state case 1: @@ -23015,7 +22635,7 @@ func file_vtctldata_proto_init() { } } file_vtctldata_proto_msgTypes[250].Exporter = func(v any, i int) any { - switch v := v.(*Workflow_Stream_Log); i { + switch v := v.(*Workflow_ReplicationLocation); i { case 0: return &v.state case 1: @@ -23027,7 +22647,7 @@ func file_vtctldata_proto_init() { } } file_vtctldata_proto_msgTypes[251].Exporter = func(v any, i int) any { - switch v := v.(*Workflow_Stream_ThrottlerStatus); i { + switch v := v.(*Workflow_ShardStream); i { case 0: return &v.state case 1: @@ -23038,8 +22658,8 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[254].Exporter = func(v any, i int) any { - switch v := v.(*ApplyVSchemaResponse_ParamList); i { + file_vtctldata_proto_msgTypes[252].Exporter = func(v any, i int) any { + switch v := v.(*Workflow_Stream); i { case 0: return &v.state case 1: @@ -23050,8 +22670,8 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[256].Exporter = func(v any, i int) any { - switch v := v.(*CheckThrottlerResponse_Metric); i { + file_vtctldata_proto_msgTypes[253].Exporter = func(v any, i int) any { + switch v := v.(*Workflow_Stream_CopyState); i { case 0: return &v.state case 1: @@ -23062,8 +22682,8 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[265].Exporter = func(v any, i int) any { - switch v := v.(*GetSrvKeyspaceNamesResponse_NameList); i { + file_vtctldata_proto_msgTypes[254].Exporter = func(v any, i int) any { + switch v := v.(*Workflow_Stream_Log); i { case 0: return &v.state case 1: @@ -23074,8 +22694,8 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[268].Exporter = func(v any, i int) any { - switch v := v.(*GetThrottlerStatusResponse_MetricResult); i { + file_vtctldata_proto_msgTypes[255].Exporter = func(v any, i int) any { + switch v := v.(*Workflow_Stream_ThrottlerStatus); i { case 0: return &v.state case 1: @@ -23086,8 +22706,8 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[271].Exporter = func(v any, i int) any { - switch v := v.(*GetThrottlerStatusResponse_MetricHealth); i { + file_vtctldata_proto_msgTypes[258].Exporter = func(v any, i int) any { + switch v := v.(*ApplyVSchemaResponse_ParamList); i { case 0: return &v.state case 1: @@ -23098,8 +22718,8 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[275].Exporter = func(v any, i int) any { - switch v := v.(*GetThrottlerStatusResponse_RecentApp); i { + file_vtctldata_proto_msgTypes[267].Exporter = func(v any, i int) any { + switch v := v.(*GetSrvKeyspaceNamesResponse_NameList); i { case 0: return &v.state case 1: @@ -23110,7 +22730,7 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[278].Exporter = func(v any, i int) any { + file_vtctldata_proto_msgTypes[271].Exporter = func(v any, i int) any { switch v := v.(*MoveTablesCreateResponse_TabletInfo); i { case 0: return &v.state @@ -23122,7 +22742,7 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[288].Exporter = func(v any, i int) any { + file_vtctldata_proto_msgTypes[281].Exporter = func(v any, i int) any { switch v := v.(*WorkflowDeleteResponse_TabletInfo); i { case 0: return &v.state @@ -23134,7 +22754,7 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[289].Exporter = func(v any, i int) any { + file_vtctldata_proto_msgTypes[282].Exporter = func(v any, i int) any { switch v := v.(*WorkflowStatusResponse_TableCopyState); i { case 0: return &v.state @@ -23146,7 +22766,7 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[290].Exporter = func(v any, i int) any { + file_vtctldata_proto_msgTypes[283].Exporter = func(v any, i int) any { switch v := v.(*WorkflowStatusResponse_ShardStreamState); i { case 0: return &v.state @@ -23158,7 +22778,7 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[291].Exporter = func(v any, i int) any { + file_vtctldata_proto_msgTypes[284].Exporter = func(v any, i int) any { switch v := v.(*WorkflowStatusResponse_ShardStreams); i { case 0: return &v.state @@ -23170,7 +22790,7 @@ func file_vtctldata_proto_init() { return nil } } - file_vtctldata_proto_msgTypes[294].Exporter = func(v any, i int) any { + file_vtctldata_proto_msgTypes[287].Exporter = func(v any, i int) any { switch v := v.(*WorkflowUpdateResponse_TabletInfo); i { case 0: return &v.state @@ -23189,7 +22809,7 @@ func file_vtctldata_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_vtctldata_proto_rawDesc, NumEnums: 4, - NumMessages: 295, + NumMessages: 288, NumExtensions: 0, NumServices: 0, }, diff --git a/go/vt/proto/vtctldata/vtctldata_vtproto.pb.go b/go/vt/proto/vtctldata/vtctldata_vtproto.pb.go index 0c23573ec48..7e38623a907 100644 --- a/go/vt/proto/vtctldata/vtctldata_vtproto.pb.go +++ b/go/vt/proto/vtctldata/vtctldata_vtproto.pb.go @@ -984,48 +984,13 @@ func (m *CheckThrottlerRequest) CloneMessageVT() proto.Message { return m.CloneVT() } -func (m *CheckThrottlerResponse_Metric) CloneVT() *CheckThrottlerResponse_Metric { - if m == nil { - return (*CheckThrottlerResponse_Metric)(nil) - } - r := &CheckThrottlerResponse_Metric{ - Name: m.Name, - StatusCode: m.StatusCode, - Value: m.Value, - Threshold: m.Threshold, - Error: m.Error, - Message: m.Message, - Scope: m.Scope, - } - if len(m.unknownFields) > 0 { - r.unknownFields = make([]byte, len(m.unknownFields)) - copy(r.unknownFields, m.unknownFields) - } - return r -} - -func (m *CheckThrottlerResponse_Metric) CloneMessageVT() proto.Message { - return m.CloneVT() -} - func (m *CheckThrottlerResponse) CloneVT() *CheckThrottlerResponse { if m == nil { return (*CheckThrottlerResponse)(nil) } r := &CheckThrottlerResponse{ - StatusCode: m.StatusCode, - Value: m.Value, - Threshold: m.Threshold, - Error: m.Error, - Message: m.Message, - RecentlyChecked: m.RecentlyChecked, - } - if rhs := m.Metrics; rhs != nil { - tmpContainer := make(map[string]*CheckThrottlerResponse_Metric, len(rhs)) - for k, v := range rhs { - tmpContainer[k] = v.CloneVT() - } - r.Metrics = tmpContainer + TabletAlias: m.TabletAlias.CloneVT(), + Check: m.Check.CloneVT(), } if len(m.unknownFields) > 0 { r.unknownFields = make([]byte, len(m.unknownFields)) @@ -2668,122 +2633,12 @@ func (m *GetThrottlerStatusRequest) CloneMessageVT() proto.Message { return m.CloneVT() } -func (m *GetThrottlerStatusResponse_MetricResult) CloneVT() *GetThrottlerStatusResponse_MetricResult { - if m == nil { - return (*GetThrottlerStatusResponse_MetricResult)(nil) - } - r := &GetThrottlerStatusResponse_MetricResult{ - Value: m.Value, - Error: m.Error, - } - if len(m.unknownFields) > 0 { - r.unknownFields = make([]byte, len(m.unknownFields)) - copy(r.unknownFields, m.unknownFields) - } - return r -} - -func (m *GetThrottlerStatusResponse_MetricResult) CloneMessageVT() proto.Message { - return m.CloneVT() -} - -func (m *GetThrottlerStatusResponse_MetricHealth) CloneVT() *GetThrottlerStatusResponse_MetricHealth { - if m == nil { - return (*GetThrottlerStatusResponse_MetricHealth)(nil) - } - r := &GetThrottlerStatusResponse_MetricHealth{ - LastHealthyAt: m.LastHealthyAt.CloneVT(), - SecondsSinceLastHealthy: m.SecondsSinceLastHealthy, - } - if len(m.unknownFields) > 0 { - r.unknownFields = make([]byte, len(m.unknownFields)) - copy(r.unknownFields, m.unknownFields) - } - return r -} - -func (m *GetThrottlerStatusResponse_MetricHealth) CloneMessageVT() proto.Message { - return m.CloneVT() -} - -func (m *GetThrottlerStatusResponse_RecentApp) CloneVT() *GetThrottlerStatusResponse_RecentApp { - if m == nil { - return (*GetThrottlerStatusResponse_RecentApp)(nil) - } - r := &GetThrottlerStatusResponse_RecentApp{ - CheckedAt: m.CheckedAt.CloneVT(), - StatusCode: m.StatusCode, - } - if len(m.unknownFields) > 0 { - r.unknownFields = make([]byte, len(m.unknownFields)) - copy(r.unknownFields, m.unknownFields) - } - return r -} - -func (m *GetThrottlerStatusResponse_RecentApp) CloneMessageVT() proto.Message { - return m.CloneVT() -} - func (m *GetThrottlerStatusResponse) CloneVT() *GetThrottlerStatusResponse { if m == nil { return (*GetThrottlerStatusResponse)(nil) } r := &GetThrottlerStatusResponse{ - TabletAlias: m.TabletAlias, - Keyspace: m.Keyspace, - Shard: m.Shard, - IsLeader: m.IsLeader, - IsOpen: m.IsOpen, - IsEnabled: m.IsEnabled, - IsDormant: m.IsDormant, - LagMetricQuery: m.LagMetricQuery, - CustomMetricQuery: m.CustomMetricQuery, - DefaultThreshold: m.DefaultThreshold, - MetricNameUsedAsDefault: m.MetricNameUsedAsDefault, - RecentlyChecked: m.RecentlyChecked, - } - if rhs := m.AggregatedMetrics; rhs != nil { - tmpContainer := make(map[string]*GetThrottlerStatusResponse_MetricResult, len(rhs)) - for k, v := range rhs { - tmpContainer[k] = v.CloneVT() - } - r.AggregatedMetrics = tmpContainer - } - if rhs := m.MetricThresholds; rhs != nil { - tmpContainer := make(map[string]float64, len(rhs)) - for k, v := range rhs { - tmpContainer[k] = v - } - r.MetricThresholds = tmpContainer - } - if rhs := m.MetricsHealth; rhs != nil { - tmpContainer := make(map[string]*GetThrottlerStatusResponse_MetricHealth, len(rhs)) - for k, v := range rhs { - tmpContainer[k] = v.CloneVT() - } - r.MetricsHealth = tmpContainer - } - if rhs := m.ThrottledApps; rhs != nil { - tmpContainer := make(map[string]*topodata.ThrottledAppRule, len(rhs)) - for k, v := range rhs { - tmpContainer[k] = v.CloneVT() - } - r.ThrottledApps = tmpContainer - } - if rhs := m.AppCheckedMetrics; rhs != nil { - tmpContainer := make(map[string]string, len(rhs)) - for k, v := range rhs { - tmpContainer[k] = v - } - r.AppCheckedMetrics = tmpContainer - } - if rhs := m.RecentApps; rhs != nil { - tmpContainer := make(map[string]*GetThrottlerStatusResponse_RecentApp, len(rhs)) - for k, v := range rhs { - tmpContainer[k] = v.CloneVT() - } - r.RecentApps = tmpContainer + Status: m.Status.CloneVT(), } if len(m.unknownFields) > 0 { r.unknownFields = make([]byte, len(m.unknownFields)) @@ -5792,6 +5647,85 @@ func (m *WorkflowUpdateResponse) CloneMessageVT() proto.Message { return m.CloneVT() } +func (m *GetMirrorRulesRequest) CloneVT() *GetMirrorRulesRequest { + if m == nil { + return (*GetMirrorRulesRequest)(nil) + } + r := &GetMirrorRulesRequest{} + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *GetMirrorRulesRequest) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *GetMirrorRulesResponse) CloneVT() *GetMirrorRulesResponse { + if m == nil { + return (*GetMirrorRulesResponse)(nil) + } + r := &GetMirrorRulesResponse{ + MirrorRules: m.MirrorRules.CloneVT(), + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *GetMirrorRulesResponse) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *WorkflowMirrorTrafficRequest) CloneVT() *WorkflowMirrorTrafficRequest { + if m == nil { + return (*WorkflowMirrorTrafficRequest)(nil) + } + r := &WorkflowMirrorTrafficRequest{ + Keyspace: m.Keyspace, + Workflow: m.Workflow, + Percent: m.Percent, + } + if rhs := m.TabletTypes; rhs != nil { + tmpContainer := make([]topodata.TabletType, len(rhs)) + copy(tmpContainer, rhs) + r.TabletTypes = tmpContainer + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *WorkflowMirrorTrafficRequest) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *WorkflowMirrorTrafficResponse) CloneVT() *WorkflowMirrorTrafficResponse { + if m == nil { + return (*WorkflowMirrorTrafficResponse)(nil) + } + r := &WorkflowMirrorTrafficResponse{ + Summary: m.Summary, + StartState: m.StartState, + CurrentState: m.CurrentState, + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *WorkflowMirrorTrafficResponse) CloneMessageVT() proto.Message { + return m.CloneVT() +} + func (m *ExecuteVtctlCommandRequest) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil @@ -8788,84 +8722,6 @@ func (m *CheckThrottlerRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) return len(dAtA) - i, nil } -func (m *CheckThrottlerResponse_Metric) MarshalVT() (dAtA []byte, err error) { - if m == nil { - return nil, nil - } - size := m.SizeVT() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBufferVT(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *CheckThrottlerResponse_Metric) MarshalToVT(dAtA []byte) (int, error) { - size := m.SizeVT() - return m.MarshalToSizedBufferVT(dAtA[:size]) -} - -func (m *CheckThrottlerResponse_Metric) MarshalToSizedBufferVT(dAtA []byte) (int, error) { - if m == nil { - return 0, nil - } - i := len(dAtA) - _ = i - var l int - _ = l - if m.unknownFields != nil { - i -= len(m.unknownFields) - copy(dAtA[i:], m.unknownFields) - } - if len(m.Scope) > 0 { - i -= len(m.Scope) - copy(dAtA[i:], m.Scope) - i = encodeVarint(dAtA, i, uint64(len(m.Scope))) - i-- - dAtA[i] = 0x3a - } - if len(m.Message) > 0 { - i -= len(m.Message) - copy(dAtA[i:], m.Message) - i = encodeVarint(dAtA, i, uint64(len(m.Message))) - i-- - dAtA[i] = 0x32 - } - if len(m.Error) > 0 { - i -= len(m.Error) - copy(dAtA[i:], m.Error) - i = encodeVarint(dAtA, i, uint64(len(m.Error))) - i-- - dAtA[i] = 0x2a - } - if m.Threshold != 0 { - i -= 8 - binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.Threshold)))) - i-- - dAtA[i] = 0x21 - } - if m.Value != 0 { - i -= 8 - binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.Value)))) - i-- - dAtA[i] = 0x19 - } - if m.StatusCode != 0 { - i = encodeVarint(dAtA, i, uint64(m.StatusCode)) - i-- - dAtA[i] = 0x10 - } - if len(m.Name) > 0 { - i -= len(m.Name) - copy(dAtA[i:], m.Name) - i = encodeVarint(dAtA, i, uint64(len(m.Name))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - func (m *CheckThrottlerResponse) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil @@ -8896,68 +8752,25 @@ func (m *CheckThrottlerResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } - if len(m.Metrics) > 0 { - for k := range m.Metrics { - v := m.Metrics[k] - baseI := i - size, err := v.MarshalToSizedBufferVT(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarint(dAtA, i, uint64(size)) - i-- - dAtA[i] = 0x12 - i -= len(k) - copy(dAtA[i:], k) - i = encodeVarint(dAtA, i, uint64(len(k))) - i-- - dAtA[i] = 0xa - i = encodeVarint(dAtA, i, uint64(baseI-i)) - i-- - dAtA[i] = 0x3a - } - } - if m.RecentlyChecked { - i-- - if m.RecentlyChecked { - dAtA[i] = 1 - } else { - dAtA[i] = 0 + if m.Check != nil { + size, err := m.Check.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) i-- - dAtA[i] = 0x30 - } - if len(m.Message) > 0 { - i -= len(m.Message) - copy(dAtA[i:], m.Message) - i = encodeVarint(dAtA, i, uint64(len(m.Message))) - i-- - dAtA[i] = 0x2a - } - if len(m.Error) > 0 { - i -= len(m.Error) - copy(dAtA[i:], m.Error) - i = encodeVarint(dAtA, i, uint64(len(m.Error))) - i-- - dAtA[i] = 0x22 - } - if m.Threshold != 0 { - i -= 8 - binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.Threshold)))) - i-- - dAtA[i] = 0x19 - } - if m.Value != 0 { - i -= 8 - binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.Value)))) - i-- - dAtA[i] = 0x11 + dAtA[i] = 0x12 } - if m.StatusCode != 0 { - i = encodeVarint(dAtA, i, uint64(m.StatusCode)) + if m.TabletAlias != nil { + size, err := m.TabletAlias.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) i-- - dAtA[i] = 0x8 + dAtA[i] = 0xa } return len(dAtA) - i, nil } @@ -12987,101 +12800,7 @@ func (m *GetThrottlerStatusRequest) MarshalToSizedBufferVT(dAtA []byte) (int, er return len(dAtA) - i, nil } -func (m *GetThrottlerStatusResponse_MetricResult) MarshalVT() (dAtA []byte, err error) { - if m == nil { - return nil, nil - } - size := m.SizeVT() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBufferVT(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *GetThrottlerStatusResponse_MetricResult) MarshalToVT(dAtA []byte) (int, error) { - size := m.SizeVT() - return m.MarshalToSizedBufferVT(dAtA[:size]) -} - -func (m *GetThrottlerStatusResponse_MetricResult) MarshalToSizedBufferVT(dAtA []byte) (int, error) { - if m == nil { - return 0, nil - } - i := len(dAtA) - _ = i - var l int - _ = l - if m.unknownFields != nil { - i -= len(m.unknownFields) - copy(dAtA[i:], m.unknownFields) - } - if len(m.Error) > 0 { - i -= len(m.Error) - copy(dAtA[i:], m.Error) - i = encodeVarint(dAtA, i, uint64(len(m.Error))) - i-- - dAtA[i] = 0x12 - } - if m.Value != 0 { - i -= 8 - binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.Value)))) - i-- - dAtA[i] = 0x9 - } - return len(dAtA) - i, nil -} - -func (m *GetThrottlerStatusResponse_MetricHealth) MarshalVT() (dAtA []byte, err error) { - if m == nil { - return nil, nil - } - size := m.SizeVT() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBufferVT(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *GetThrottlerStatusResponse_MetricHealth) MarshalToVT(dAtA []byte) (int, error) { - size := m.SizeVT() - return m.MarshalToSizedBufferVT(dAtA[:size]) -} - -func (m *GetThrottlerStatusResponse_MetricHealth) MarshalToSizedBufferVT(dAtA []byte) (int, error) { - if m == nil { - return 0, nil - } - i := len(dAtA) - _ = i - var l int - _ = l - if m.unknownFields != nil { - i -= len(m.unknownFields) - copy(dAtA[i:], m.unknownFields) - } - if m.SecondsSinceLastHealthy != 0 { - i = encodeVarint(dAtA, i, uint64(m.SecondsSinceLastHealthy)) - i-- - dAtA[i] = 0x10 - } - if m.LastHealthyAt != nil { - size, err := m.LastHealthyAt.MarshalToSizedBufferVT(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarint(dAtA, i, uint64(size)) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *GetThrottlerStatusResponse_RecentApp) MarshalVT() (dAtA []byte, err error) { +func (m *GetThrottlerStatusResponse) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil } @@ -13094,12 +12813,12 @@ func (m *GetThrottlerStatusResponse_RecentApp) MarshalVT() (dAtA []byte, err err return dAtA[:n], nil } -func (m *GetThrottlerStatusResponse_RecentApp) MarshalToVT(dAtA []byte) (int, error) { +func (m *GetThrottlerStatusResponse) MarshalToVT(dAtA []byte) (int, error) { size := m.SizeVT() return m.MarshalToSizedBufferVT(dAtA[:size]) } -func (m *GetThrottlerStatusResponse_RecentApp) MarshalToSizedBufferVT(dAtA []byte) (int, error) { +func (m *GetThrottlerStatusResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { if m == nil { return 0, nil } @@ -13111,13 +12830,8 @@ func (m *GetThrottlerStatusResponse_RecentApp) MarshalToSizedBufferVT(dAtA []byt i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } - if m.StatusCode != 0 { - i = encodeVarint(dAtA, i, uint64(m.StatusCode)) - i-- - dAtA[i] = 0x10 - } - if m.CheckedAt != nil { - size, err := m.CheckedAt.MarshalToSizedBufferVT(dAtA[:i]) + if m.Status != nil { + size, err := m.Status.MarshalToSizedBufferVT(dAtA[:i]) if err != nil { return 0, err } @@ -13129,268 +12843,6 @@ func (m *GetThrottlerStatusResponse_RecentApp) MarshalToSizedBufferVT(dAtA []byt return len(dAtA) - i, nil } -func (m *GetThrottlerStatusResponse) MarshalVT() (dAtA []byte, err error) { - if m == nil { - return nil, nil - } - size := m.SizeVT() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBufferVT(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *GetThrottlerStatusResponse) MarshalToVT(dAtA []byte) (int, error) { - size := m.SizeVT() - return m.MarshalToSizedBufferVT(dAtA[:size]) -} - -func (m *GetThrottlerStatusResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { - if m == nil { - return 0, nil - } - i := len(dAtA) - _ = i - var l int - _ = l - if m.unknownFields != nil { - i -= len(m.unknownFields) - copy(dAtA[i:], m.unknownFields) - } - if len(m.RecentApps) > 0 { - for k := range m.RecentApps { - v := m.RecentApps[k] - baseI := i - size, err := v.MarshalToSizedBufferVT(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarint(dAtA, i, uint64(size)) - i-- - dAtA[i] = 0x12 - i -= len(k) - copy(dAtA[i:], k) - i = encodeVarint(dAtA, i, uint64(len(k))) - i-- - dAtA[i] = 0xa - i = encodeVarint(dAtA, i, uint64(baseI-i)) - i-- - dAtA[i] = 0x1 - i-- - dAtA[i] = 0x92 - } - } - if m.RecentlyChecked { - i-- - if m.RecentlyChecked { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i-- - dAtA[i] = 0x1 - i-- - dAtA[i] = 0x88 - } - if len(m.AppCheckedMetrics) > 0 { - for k := range m.AppCheckedMetrics { - v := m.AppCheckedMetrics[k] - baseI := i - i -= len(v) - copy(dAtA[i:], v) - i = encodeVarint(dAtA, i, uint64(len(v))) - i-- - dAtA[i] = 0x12 - i -= len(k) - copy(dAtA[i:], k) - i = encodeVarint(dAtA, i, uint64(len(k))) - i-- - dAtA[i] = 0xa - i = encodeVarint(dAtA, i, uint64(baseI-i)) - i-- - dAtA[i] = 0x1 - i-- - dAtA[i] = 0x82 - } - } - if len(m.ThrottledApps) > 0 { - for k := range m.ThrottledApps { - v := m.ThrottledApps[k] - baseI := i - size, err := v.MarshalToSizedBufferVT(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarint(dAtA, i, uint64(size)) - i-- - dAtA[i] = 0x12 - i -= len(k) - copy(dAtA[i:], k) - i = encodeVarint(dAtA, i, uint64(len(k))) - i-- - dAtA[i] = 0xa - i = encodeVarint(dAtA, i, uint64(baseI-i)) - i-- - dAtA[i] = 0x7a - } - } - if len(m.MetricsHealth) > 0 { - for k := range m.MetricsHealth { - v := m.MetricsHealth[k] - baseI := i - size, err := v.MarshalToSizedBufferVT(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarint(dAtA, i, uint64(size)) - i-- - dAtA[i] = 0x12 - i -= len(k) - copy(dAtA[i:], k) - i = encodeVarint(dAtA, i, uint64(len(k))) - i-- - dAtA[i] = 0xa - i = encodeVarint(dAtA, i, uint64(baseI-i)) - i-- - dAtA[i] = 0x72 - } - } - if len(m.MetricThresholds) > 0 { - for k := range m.MetricThresholds { - v := m.MetricThresholds[k] - baseI := i - i -= 8 - binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(v)))) - i-- - dAtA[i] = 0x11 - i -= len(k) - copy(dAtA[i:], k) - i = encodeVarint(dAtA, i, uint64(len(k))) - i-- - dAtA[i] = 0xa - i = encodeVarint(dAtA, i, uint64(baseI-i)) - i-- - dAtA[i] = 0x6a - } - } - if len(m.AggregatedMetrics) > 0 { - for k := range m.AggregatedMetrics { - v := m.AggregatedMetrics[k] - baseI := i - size, err := v.MarshalToSizedBufferVT(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarint(dAtA, i, uint64(size)) - i-- - dAtA[i] = 0x12 - i -= len(k) - copy(dAtA[i:], k) - i = encodeVarint(dAtA, i, uint64(len(k))) - i-- - dAtA[i] = 0xa - i = encodeVarint(dAtA, i, uint64(baseI-i)) - i-- - dAtA[i] = 0x62 - } - } - if len(m.MetricNameUsedAsDefault) > 0 { - i -= len(m.MetricNameUsedAsDefault) - copy(dAtA[i:], m.MetricNameUsedAsDefault) - i = encodeVarint(dAtA, i, uint64(len(m.MetricNameUsedAsDefault))) - i-- - dAtA[i] = 0x5a - } - if m.DefaultThreshold != 0 { - i -= 8 - binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.DefaultThreshold)))) - i-- - dAtA[i] = 0x51 - } - if len(m.CustomMetricQuery) > 0 { - i -= len(m.CustomMetricQuery) - copy(dAtA[i:], m.CustomMetricQuery) - i = encodeVarint(dAtA, i, uint64(len(m.CustomMetricQuery))) - i-- - dAtA[i] = 0x4a - } - if len(m.LagMetricQuery) > 0 { - i -= len(m.LagMetricQuery) - copy(dAtA[i:], m.LagMetricQuery) - i = encodeVarint(dAtA, i, uint64(len(m.LagMetricQuery))) - i-- - dAtA[i] = 0x42 - } - if m.IsDormant { - i-- - if m.IsDormant { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i-- - dAtA[i] = 0x38 - } - if m.IsEnabled { - i-- - if m.IsEnabled { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i-- - dAtA[i] = 0x30 - } - if m.IsOpen { - i-- - if m.IsOpen { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i-- - dAtA[i] = 0x28 - } - if m.IsLeader { - i-- - if m.IsLeader { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i-- - dAtA[i] = 0x20 - } - if len(m.Shard) > 0 { - i -= len(m.Shard) - copy(dAtA[i:], m.Shard) - i = encodeVarint(dAtA, i, uint64(len(m.Shard))) - i-- - dAtA[i] = 0x1a - } - if len(m.Keyspace) > 0 { - i -= len(m.Keyspace) - copy(dAtA[i:], m.Keyspace) - i = encodeVarint(dAtA, i, uint64(len(m.Keyspace))) - i-- - dAtA[i] = 0x12 - } - if len(m.TabletAlias) > 0 { - i -= len(m.TabletAlias) - copy(dAtA[i:], m.TabletAlias) - i = encodeVarint(dAtA, i, uint64(len(m.TabletAlias))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - func (m *GetTopologyPathRequest) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil @@ -21228,6 +20680,210 @@ func (m *WorkflowUpdateResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error return len(dAtA) - i, nil } +func (m *GetMirrorRulesRequest) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetMirrorRulesRequest) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *GetMirrorRulesRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + return len(dAtA) - i, nil +} + +func (m *GetMirrorRulesResponse) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetMirrorRulesResponse) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *GetMirrorRulesResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.MirrorRules != nil { + size, err := m.MirrorRules.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *WorkflowMirrorTrafficRequest) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *WorkflowMirrorTrafficRequest) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *WorkflowMirrorTrafficRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Percent != 0 { + i -= 4 + binary.LittleEndian.PutUint32(dAtA[i:], uint32(math.Float32bits(float32(m.Percent)))) + i-- + dAtA[i] = 0x25 + } + if len(m.TabletTypes) > 0 { + var pksize2 int + for _, num := range m.TabletTypes { + pksize2 += sov(uint64(num)) + } + i -= pksize2 + j1 := i + for _, num1 := range m.TabletTypes { + num := uint64(num1) + for num >= 1<<7 { + dAtA[j1] = uint8(uint64(num)&0x7f | 0x80) + num >>= 7 + j1++ + } + dAtA[j1] = uint8(num) + j1++ + } + i = encodeVarint(dAtA, i, uint64(pksize2)) + i-- + dAtA[i] = 0x1a + } + if len(m.Workflow) > 0 { + i -= len(m.Workflow) + copy(dAtA[i:], m.Workflow) + i = encodeVarint(dAtA, i, uint64(len(m.Workflow))) + i-- + dAtA[i] = 0x12 + } + if len(m.Keyspace) > 0 { + i -= len(m.Keyspace) + copy(dAtA[i:], m.Keyspace) + i = encodeVarint(dAtA, i, uint64(len(m.Keyspace))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *WorkflowMirrorTrafficResponse) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *WorkflowMirrorTrafficResponse) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *WorkflowMirrorTrafficResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.CurrentState) > 0 { + i -= len(m.CurrentState) + copy(dAtA[i:], m.CurrentState) + i = encodeVarint(dAtA, i, uint64(len(m.CurrentState))) + i-- + dAtA[i] = 0x1a + } + if len(m.StartState) > 0 { + i -= len(m.StartState) + copy(dAtA[i:], m.StartState) + i = encodeVarint(dAtA, i, uint64(len(m.StartState))) + i-- + dAtA[i] = 0x12 + } + if len(m.Summary) > 0 { + i -= len(m.Summary) + copy(dAtA[i:], m.Summary) + i = encodeVarint(dAtA, i, uint64(len(m.Summary))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarint(dAtA []byte, offset int, v uint64) int { offset -= sov(v) base := offset @@ -22417,80 +22073,20 @@ func (m *CheckThrottlerRequest) SizeVT() (n int) { return n } -func (m *CheckThrottlerResponse_Metric) SizeVT() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Name) - if l > 0 { - n += 1 + l + sov(uint64(l)) - } - if m.StatusCode != 0 { - n += 1 + sov(uint64(m.StatusCode)) - } - if m.Value != 0 { - n += 9 - } - if m.Threshold != 0 { - n += 9 - } - l = len(m.Error) - if l > 0 { - n += 1 + l + sov(uint64(l)) - } - l = len(m.Message) - if l > 0 { - n += 1 + l + sov(uint64(l)) - } - l = len(m.Scope) - if l > 0 { - n += 1 + l + sov(uint64(l)) - } - n += len(m.unknownFields) - return n -} - func (m *CheckThrottlerResponse) SizeVT() (n int) { if m == nil { return 0 } var l int _ = l - if m.StatusCode != 0 { - n += 1 + sov(uint64(m.StatusCode)) - } - if m.Value != 0 { - n += 9 - } - if m.Threshold != 0 { - n += 9 - } - l = len(m.Error) - if l > 0 { + if m.TabletAlias != nil { + l = m.TabletAlias.SizeVT() n += 1 + l + sov(uint64(l)) } - l = len(m.Message) - if l > 0 { + if m.Check != nil { + l = m.Check.SizeVT() n += 1 + l + sov(uint64(l)) } - if m.RecentlyChecked { - n += 2 - } - if len(m.Metrics) > 0 { - for k, v := range m.Metrics { - _ = k - _ = v - l = 0 - if v != nil { - l = v.SizeVT() - } - l += 1 + sov(uint64(l)) - mapEntrySize := 1 + len(k) + sov(uint64(len(k))) + l - n += mapEntrySize + 1 + sov(uint64(mapEntrySize)) - } - } n += len(m.unknownFields) return n } @@ -23947,173 +23543,16 @@ func (m *GetThrottlerStatusRequest) SizeVT() (n int) { return n } -func (m *GetThrottlerStatusResponse_MetricResult) SizeVT() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Value != 0 { - n += 9 - } - l = len(m.Error) - if l > 0 { - n += 1 + l + sov(uint64(l)) - } - n += len(m.unknownFields) - return n -} - -func (m *GetThrottlerStatusResponse_MetricHealth) SizeVT() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.LastHealthyAt != nil { - l = m.LastHealthyAt.SizeVT() - n += 1 + l + sov(uint64(l)) - } - if m.SecondsSinceLastHealthy != 0 { - n += 1 + sov(uint64(m.SecondsSinceLastHealthy)) - } - n += len(m.unknownFields) - return n -} - -func (m *GetThrottlerStatusResponse_RecentApp) SizeVT() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.CheckedAt != nil { - l = m.CheckedAt.SizeVT() - n += 1 + l + sov(uint64(l)) - } - if m.StatusCode != 0 { - n += 1 + sov(uint64(m.StatusCode)) - } - n += len(m.unknownFields) - return n -} - func (m *GetThrottlerStatusResponse) SizeVT() (n int) { if m == nil { return 0 } var l int _ = l - l = len(m.TabletAlias) - if l > 0 { - n += 1 + l + sov(uint64(l)) - } - l = len(m.Keyspace) - if l > 0 { - n += 1 + l + sov(uint64(l)) - } - l = len(m.Shard) - if l > 0 { - n += 1 + l + sov(uint64(l)) - } - if m.IsLeader { - n += 2 - } - if m.IsOpen { - n += 2 - } - if m.IsEnabled { - n += 2 - } - if m.IsDormant { - n += 2 - } - l = len(m.LagMetricQuery) - if l > 0 { - n += 1 + l + sov(uint64(l)) - } - l = len(m.CustomMetricQuery) - if l > 0 { - n += 1 + l + sov(uint64(l)) - } - if m.DefaultThreshold != 0 { - n += 9 - } - l = len(m.MetricNameUsedAsDefault) - if l > 0 { + if m.Status != nil { + l = m.Status.SizeVT() n += 1 + l + sov(uint64(l)) } - if len(m.AggregatedMetrics) > 0 { - for k, v := range m.AggregatedMetrics { - _ = k - _ = v - l = 0 - if v != nil { - l = v.SizeVT() - } - l += 1 + sov(uint64(l)) - mapEntrySize := 1 + len(k) + sov(uint64(len(k))) + l - n += mapEntrySize + 1 + sov(uint64(mapEntrySize)) - } - } - if len(m.MetricThresholds) > 0 { - for k, v := range m.MetricThresholds { - _ = k - _ = v - mapEntrySize := 1 + len(k) + sov(uint64(len(k))) + 1 + 8 - n += mapEntrySize + 1 + sov(uint64(mapEntrySize)) - } - } - if len(m.MetricsHealth) > 0 { - for k, v := range m.MetricsHealth { - _ = k - _ = v - l = 0 - if v != nil { - l = v.SizeVT() - } - l += 1 + sov(uint64(l)) - mapEntrySize := 1 + len(k) + sov(uint64(len(k))) + l - n += mapEntrySize + 1 + sov(uint64(mapEntrySize)) - } - } - if len(m.ThrottledApps) > 0 { - for k, v := range m.ThrottledApps { - _ = k - _ = v - l = 0 - if v != nil { - l = v.SizeVT() - } - l += 1 + sov(uint64(l)) - mapEntrySize := 1 + len(k) + sov(uint64(len(k))) + l - n += mapEntrySize + 1 + sov(uint64(mapEntrySize)) - } - } - if len(m.AppCheckedMetrics) > 0 { - for k, v := range m.AppCheckedMetrics { - _ = k - _ = v - mapEntrySize := 1 + len(k) + sov(uint64(len(k))) + 1 + len(v) + sov(uint64(len(v))) - n += mapEntrySize + 2 + sov(uint64(mapEntrySize)) - } - } - if m.RecentlyChecked { - n += 3 - } - if len(m.RecentApps) > 0 { - for k, v := range m.RecentApps { - _ = k - _ = v - l = 0 - if v != nil { - l = v.SizeVT() - } - l += 1 + sov(uint64(l)) - mapEntrySize := 1 + len(k) + sov(uint64(len(k))) + l - n += mapEntrySize + 2 + sov(uint64(mapEntrySize)) - } - } n += len(m.unknownFields) return n } @@ -27074,6 +26513,80 @@ func (m *WorkflowUpdateResponse) SizeVT() (n int) { return n } +func (m *GetMirrorRulesRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + n += len(m.unknownFields) + return n +} + +func (m *GetMirrorRulesResponse) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.MirrorRules != nil { + l = m.MirrorRules.SizeVT() + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *WorkflowMirrorTrafficRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Keyspace) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.Workflow) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if len(m.TabletTypes) > 0 { + l = 0 + for _, e := range m.TabletTypes { + l += sov(uint64(e)) + } + n += 1 + sov(uint64(l)) + l + } + if m.Percent != 0 { + n += 5 + } + n += len(m.unknownFields) + return n +} + +func (m *WorkflowMirrorTrafficResponse) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Summary) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.StartState) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.CurrentState) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + func sov(x uint64) (n int) { return (bits.Len64(x|1) + 6) / 7 } @@ -35165,226 +34678,6 @@ func (m *CheckThrottlerRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *CheckThrottlerResponse_Metric) UnmarshalVT(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: CheckThrottlerResponse_Metric: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: CheckThrottlerResponse_Metric: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLength - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLength - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Name = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field StatusCode", wireType) - } - m.StatusCode = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.StatusCode |= int32(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 1 { - return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) - } - var v uint64 - if (iNdEx + 8) > l { - return io.ErrUnexpectedEOF - } - v = uint64(binary.LittleEndian.Uint64(dAtA[iNdEx:])) - iNdEx += 8 - m.Value = float64(math.Float64frombits(v)) - case 4: - if wireType != 1 { - return fmt.Errorf("proto: wrong wireType = %d for field Threshold", wireType) - } - var v uint64 - if (iNdEx + 8) > l { - return io.ErrUnexpectedEOF - } - v = uint64(binary.LittleEndian.Uint64(dAtA[iNdEx:])) - iNdEx += 8 - m.Threshold = float64(math.Float64frombits(v)) - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLength - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLength - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Error = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Message", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLength - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLength - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Message = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 7: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Scope", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLength - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLength - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Scope = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skip(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLength - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func (m *CheckThrottlerResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -35415,51 +34708,10 @@ func (m *CheckThrottlerResponse) UnmarshalVT(dAtA []byte) error { } switch fieldNum { case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field StatusCode", wireType) - } - m.StatusCode = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.StatusCode |= int32(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 2: - if wireType != 1 { - return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) - } - var v uint64 - if (iNdEx + 8) > l { - return io.ErrUnexpectedEOF - } - v = uint64(binary.LittleEndian.Uint64(dAtA[iNdEx:])) - iNdEx += 8 - m.Value = float64(math.Float64frombits(v)) - case 3: - if wireType != 1 { - return fmt.Errorf("proto: wrong wireType = %d for field Threshold", wireType) - } - var v uint64 - if (iNdEx + 8) > l { - return io.ErrUnexpectedEOF - } - v = uint64(binary.LittleEndian.Uint64(dAtA[iNdEx:])) - iNdEx += 8 - m.Threshold = float64(math.Float64frombits(v)) - case 4: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field TabletAlias", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -35469,79 +34721,31 @@ func (m *CheckThrottlerResponse) UnmarshalVT(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { + if msglen < 0 { return ErrInvalidLength } - postIndex := iNdEx + intStringLen + postIndex := iNdEx + msglen if postIndex < 0 { return ErrInvalidLength } if postIndex > l { return io.ErrUnexpectedEOF } - m.Error = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Message", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLength - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLength + if m.TabletAlias == nil { + m.TabletAlias = &topodata.TabletAlias{} } - if postIndex > l { - return io.ErrUnexpectedEOF + if err := m.TabletAlias.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err } - m.Message = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 6: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field RecentlyChecked", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.RecentlyChecked = bool(v != 0) - case 7: + case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Metrics", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Check", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -35568,105 +34772,12 @@ func (m *CheckThrottlerResponse) UnmarshalVT(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Metrics == nil { - m.Metrics = make(map[string]*CheckThrottlerResponse_Metric) + if m.Check == nil { + m.Check = &tabletmanagerdata.CheckThrottlerResponse{} } - var mapkey string - var mapvalue *CheckThrottlerResponse_Metric - for iNdEx < postIndex { - entryPreIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - if fieldNum == 1 { - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLength - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey < 0 { - return ErrInvalidLength - } - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey - } else if fieldNum == 2 { - var mapmsglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - mapmsglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if mapmsglen < 0 { - return ErrInvalidLength - } - postmsgIndex := iNdEx + mapmsglen - if postmsgIndex < 0 { - return ErrInvalidLength - } - if postmsgIndex > l { - return io.ErrUnexpectedEOF - } - mapvalue = &CheckThrottlerResponse_Metric{} - if err := mapvalue.UnmarshalVT(dAtA[iNdEx:postmsgIndex]); err != nil { - return err - } - iNdEx = postmsgIndex - } else { - iNdEx = entryPreIndex - skippy, err := skip(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLength - } - if (iNdEx + skippy) > postIndex { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } + if err := m.Check.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err } - m.Metrics[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex @@ -44927,7 +44038,7 @@ func (m *GetThrottlerStatusRequest) UnmarshalVT(dAtA []byte) error { } return nil } -func (m *GetThrottlerStatusResponse_MetricResult) UnmarshalVT(dAtA []byte) error { +func (m *GetThrottlerStatusResponse) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -44950,28 +44061,17 @@ func (m *GetThrottlerStatusResponse_MetricResult) UnmarshalVT(dAtA []byte) error fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetThrottlerStatusResponse_MetricResult: wiretype end group for non-group") + return fmt.Errorf("proto: GetThrottlerStatusResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetThrottlerStatusResponse_MetricResult: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetThrottlerStatusResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: - if wireType != 1 { - return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) - } - var v uint64 - if (iNdEx + 8) > l { - return io.ErrUnexpectedEOF - } - v = uint64(binary.LittleEndian.Uint64(dAtA[iNdEx:])) - iNdEx += 8 - m.Value = float64(math.Float64frombits(v)) - case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -44981,23 +44081,27 @@ func (m *GetThrottlerStatusResponse_MetricResult) UnmarshalVT(dAtA []byte) error } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { + if msglen < 0 { return ErrInvalidLength } - postIndex := iNdEx + intStringLen + postIndex := iNdEx + msglen if postIndex < 0 { return ErrInvalidLength } if postIndex > l { return io.ErrUnexpectedEOF } - m.Error = string(dAtA[iNdEx:postIndex]) + if m.Status == nil { + m.Status = &tabletmanagerdata.GetThrottlerStatusResponse{} + } + if err := m.Status.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex default: iNdEx = preIndex @@ -45021,7 +44125,7 @@ func (m *GetThrottlerStatusResponse_MetricResult) UnmarshalVT(dAtA []byte) error } return nil } -func (m *GetThrottlerStatusResponse_MetricHealth) UnmarshalVT(dAtA []byte) error { +func (m *GetTopologyPathRequest) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -45044,17 +44148,17 @@ func (m *GetThrottlerStatusResponse_MetricHealth) UnmarshalVT(dAtA []byte) error fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GetThrottlerStatusResponse_MetricHealth: wiretype end group for non-group") + return fmt.Errorf("proto: GetTopologyPathRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GetThrottlerStatusResponse_MetricHealth: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GetTopologyPathRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field LastHealthyAt", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -45064,33 +44168,48 @@ func (m *GetThrottlerStatusResponse_MetricHealth) UnmarshalVT(dAtA []byte) error } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLength } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex < 0 { return ErrInvalidLength } if postIndex > l { return io.ErrUnexpectedEOF } - if m.LastHealthyAt == nil { - m.LastHealthyAt = &vttime.Time{} - } - if err := m.LastHealthyAt.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Path = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field SecondsSinceLastHealthy", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + m.Version = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Version |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AsJson", wireType) } - m.SecondsSinceLastHealthy = 0 + var v int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflow @@ -45100,1342 +44219,12 @@ func (m *GetThrottlerStatusResponse_MetricHealth) UnmarshalVT(dAtA []byte) error } b := dAtA[iNdEx] iNdEx++ - m.SecondsSinceLastHealthy |= int64(b&0x7F) << shift + v |= int(b&0x7F) << shift if b < 0x80 { break } } - default: - iNdEx = preIndex - skippy, err := skip(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLength - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *GetThrottlerStatusResponse_RecentApp) UnmarshalVT(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: GetThrottlerStatusResponse_RecentApp: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: GetThrottlerStatusResponse_RecentApp: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field CheckedAt", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLength - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLength - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.CheckedAt == nil { - m.CheckedAt = &vttime.Time{} - } - if err := m.CheckedAt.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field StatusCode", wireType) - } - m.StatusCode = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.StatusCode |= int32(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skip(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLength - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *GetThrottlerStatusResponse) UnmarshalVT(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: GetThrottlerStatusResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: GetThrottlerStatusResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field TabletAlias", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLength - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLength - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.TabletAlias = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Keyspace", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLength - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLength - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Keyspace = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Shard", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLength - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLength - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Shard = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field IsLeader", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.IsLeader = bool(v != 0) - case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field IsOpen", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.IsOpen = bool(v != 0) - case 6: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field IsEnabled", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.IsEnabled = bool(v != 0) - case 7: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field IsDormant", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.IsDormant = bool(v != 0) - case 8: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field LagMetricQuery", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLength - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLength - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.LagMetricQuery = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 9: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field CustomMetricQuery", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLength - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLength - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.CustomMetricQuery = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 10: - if wireType != 1 { - return fmt.Errorf("proto: wrong wireType = %d for field DefaultThreshold", wireType) - } - var v uint64 - if (iNdEx + 8) > l { - return io.ErrUnexpectedEOF - } - v = uint64(binary.LittleEndian.Uint64(dAtA[iNdEx:])) - iNdEx += 8 - m.DefaultThreshold = float64(math.Float64frombits(v)) - case 11: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field MetricNameUsedAsDefault", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLength - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLength - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.MetricNameUsedAsDefault = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 12: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field AggregatedMetrics", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLength - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLength - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.AggregatedMetrics == nil { - m.AggregatedMetrics = make(map[string]*GetThrottlerStatusResponse_MetricResult) - } - var mapkey string - var mapvalue *GetThrottlerStatusResponse_MetricResult - for iNdEx < postIndex { - entryPreIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - if fieldNum == 1 { - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLength - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey < 0 { - return ErrInvalidLength - } - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey - } else if fieldNum == 2 { - var mapmsglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - mapmsglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if mapmsglen < 0 { - return ErrInvalidLength - } - postmsgIndex := iNdEx + mapmsglen - if postmsgIndex < 0 { - return ErrInvalidLength - } - if postmsgIndex > l { - return io.ErrUnexpectedEOF - } - mapvalue = &GetThrottlerStatusResponse_MetricResult{} - if err := mapvalue.UnmarshalVT(dAtA[iNdEx:postmsgIndex]); err != nil { - return err - } - iNdEx = postmsgIndex - } else { - iNdEx = entryPreIndex - skippy, err := skip(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLength - } - if (iNdEx + skippy) > postIndex { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - m.AggregatedMetrics[mapkey] = mapvalue - iNdEx = postIndex - case 13: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field MetricThresholds", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLength - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLength - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.MetricThresholds == nil { - m.MetricThresholds = make(map[string]float64) - } - var mapkey string - var mapvalue float64 - for iNdEx < postIndex { - entryPreIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - if fieldNum == 1 { - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLength - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey < 0 { - return ErrInvalidLength - } - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey - } else if fieldNum == 2 { - var mapvaluetemp uint64 - if (iNdEx + 8) > l { - return io.ErrUnexpectedEOF - } - mapvaluetemp = uint64(binary.LittleEndian.Uint64(dAtA[iNdEx:])) - iNdEx += 8 - mapvalue = math.Float64frombits(mapvaluetemp) - } else { - iNdEx = entryPreIndex - skippy, err := skip(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLength - } - if (iNdEx + skippy) > postIndex { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - m.MetricThresholds[mapkey] = mapvalue - iNdEx = postIndex - case 14: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field MetricsHealth", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLength - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLength - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.MetricsHealth == nil { - m.MetricsHealth = make(map[string]*GetThrottlerStatusResponse_MetricHealth) - } - var mapkey string - var mapvalue *GetThrottlerStatusResponse_MetricHealth - for iNdEx < postIndex { - entryPreIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - if fieldNum == 1 { - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLength - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey < 0 { - return ErrInvalidLength - } - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey - } else if fieldNum == 2 { - var mapmsglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - mapmsglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if mapmsglen < 0 { - return ErrInvalidLength - } - postmsgIndex := iNdEx + mapmsglen - if postmsgIndex < 0 { - return ErrInvalidLength - } - if postmsgIndex > l { - return io.ErrUnexpectedEOF - } - mapvalue = &GetThrottlerStatusResponse_MetricHealth{} - if err := mapvalue.UnmarshalVT(dAtA[iNdEx:postmsgIndex]); err != nil { - return err - } - iNdEx = postmsgIndex - } else { - iNdEx = entryPreIndex - skippy, err := skip(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLength - } - if (iNdEx + skippy) > postIndex { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - m.MetricsHealth[mapkey] = mapvalue - iNdEx = postIndex - case 15: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ThrottledApps", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLength - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLength - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.ThrottledApps == nil { - m.ThrottledApps = make(map[string]*topodata.ThrottledAppRule) - } - var mapkey string - var mapvalue *topodata.ThrottledAppRule - for iNdEx < postIndex { - entryPreIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - if fieldNum == 1 { - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLength - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey < 0 { - return ErrInvalidLength - } - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey - } else if fieldNum == 2 { - var mapmsglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - mapmsglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if mapmsglen < 0 { - return ErrInvalidLength - } - postmsgIndex := iNdEx + mapmsglen - if postmsgIndex < 0 { - return ErrInvalidLength - } - if postmsgIndex > l { - return io.ErrUnexpectedEOF - } - mapvalue = &topodata.ThrottledAppRule{} - if err := mapvalue.UnmarshalVT(dAtA[iNdEx:postmsgIndex]); err != nil { - return err - } - iNdEx = postmsgIndex - } else { - iNdEx = entryPreIndex - skippy, err := skip(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLength - } - if (iNdEx + skippy) > postIndex { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - m.ThrottledApps[mapkey] = mapvalue - iNdEx = postIndex - case 16: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field AppCheckedMetrics", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLength - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLength - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.AppCheckedMetrics == nil { - m.AppCheckedMetrics = make(map[string]string) - } - var mapkey string - var mapvalue string - for iNdEx < postIndex { - entryPreIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - if fieldNum == 1 { - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLength - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey < 0 { - return ErrInvalidLength - } - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey - } else if fieldNum == 2 { - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapvalue |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLength - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue < 0 { - return ErrInvalidLength - } - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue - } else { - iNdEx = entryPreIndex - skippy, err := skip(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLength - } - if (iNdEx + skippy) > postIndex { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - m.AppCheckedMetrics[mapkey] = mapvalue - iNdEx = postIndex - case 17: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field RecentlyChecked", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.RecentlyChecked = bool(v != 0) - case 18: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field RecentApps", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLength - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLength - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.RecentApps == nil { - m.RecentApps = make(map[string]*GetThrottlerStatusResponse_RecentApp) - } - var mapkey string - var mapvalue *GetThrottlerStatusResponse_RecentApp - for iNdEx < postIndex { - entryPreIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - if fieldNum == 1 { - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLength - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey < 0 { - return ErrInvalidLength - } - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey - } else if fieldNum == 2 { - var mapmsglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - mapmsglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if mapmsglen < 0 { - return ErrInvalidLength - } - postmsgIndex := iNdEx + mapmsglen - if postmsgIndex < 0 { - return ErrInvalidLength - } - if postmsgIndex > l { - return io.ErrUnexpectedEOF - } - mapvalue = &GetThrottlerStatusResponse_RecentApp{} - if err := mapvalue.UnmarshalVT(dAtA[iNdEx:postmsgIndex]); err != nil { - return err - } - iNdEx = postmsgIndex - } else { - iNdEx = entryPreIndex - skippy, err := skip(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLength - } - if (iNdEx + skippy) > postIndex { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - m.RecentApps[mapkey] = mapvalue - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skip(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLength - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *GetTopologyPathRequest) UnmarshalVT(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: GetTopologyPathRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: GetTopologyPathRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLength - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLength - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Path = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) - } - m.Version = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Version |= int64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field AsJson", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflow - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.AsJson = bool(v != 0) + m.AsJson = bool(v != 0) default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) @@ -65422,6 +63211,486 @@ func (m *WorkflowUpdateResponse) UnmarshalVT(dAtA []byte) error { } return nil } +func (m *GetMirrorRulesRequest) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetMirrorRulesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetMirrorRulesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetMirrorRulesResponse) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetMirrorRulesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetMirrorRulesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MirrorRules", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.MirrorRules == nil { + m.MirrorRules = &vschema.MirrorRules{} + } + if err := m.MirrorRules.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *WorkflowMirrorTrafficRequest) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: WorkflowMirrorTrafficRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: WorkflowMirrorTrafficRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Keyspace", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Keyspace = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Workflow", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Workflow = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType == 0 { + var v topodata.TabletType + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= topodata.TabletType(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.TabletTypes = append(m.TabletTypes, v) + } else if wireType == 2 { + var packedLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + packedLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if packedLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + packedLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + var elementCount int + if elementCount != 0 && len(m.TabletTypes) == 0 { + m.TabletTypes = make([]topodata.TabletType, 0, elementCount) + } + for iNdEx < postIndex { + var v topodata.TabletType + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= topodata.TabletType(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.TabletTypes = append(m.TabletTypes, v) + } + } else { + return fmt.Errorf("proto: wrong wireType = %d for field TabletTypes", wireType) + } + case 4: + if wireType != 5 { + return fmt.Errorf("proto: wrong wireType = %d for field Percent", wireType) + } + var v uint32 + if (iNdEx + 4) > l { + return io.ErrUnexpectedEOF + } + v = uint32(binary.LittleEndian.Uint32(dAtA[iNdEx:])) + iNdEx += 4 + m.Percent = float32(math.Float32frombits(v)) + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *WorkflowMirrorTrafficResponse) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: WorkflowMirrorTrafficResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: WorkflowMirrorTrafficResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Summary", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Summary = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StartState", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.StartState = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CurrentState", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CurrentState = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skip(dAtA []byte) (n int, err error) { l := len(dAtA) diff --git a/go/vt/proto/vtctlservice/vtctlservice.pb.go b/go/vt/proto/vtctlservice/vtctlservice.pb.go index 194571e550d..e5ff978e853 100644 --- a/go/vt/proto/vtctlservice/vtctlservice.pb.go +++ b/go/vt/proto/vtctlservice/vtctlservice.pb.go @@ -51,7 +51,7 @@ var file_vtctlservice_proto_rawDesc = []byte{ 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x56, 0x74, 0x63, 0x74, 0x6c, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x32, 0x98, 0x56, 0x0a, 0x06, 0x56, 0x74, 0x63, 0x74, 0x6c, + 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x32, 0xdf, 0x57, 0x0a, 0x06, 0x56, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x12, 0x4e, 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x43, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x65, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, @@ -741,10 +741,22 @@ var file_vtctlservice_proto_rawDesc = []byte{ 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x42, 0x2b, 0x5a, 0x29, 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, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x00, 0x12, 0x57, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x75, + 0x6c, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, + 0x47, 0x65, 0x74, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, + 0x61, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x75, 0x6c, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6c, 0x0a, 0x15, 0x57, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x72, 0x61, 0x66, + 0x66, 0x69, 0x63, 0x12, 0x27, 0x2e, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, + 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x72, + 0x61, 0x66, 0x66, 0x69, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x76, + 0x74, 0x63, 0x74, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, + 0x77, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x2b, 0x5a, 0x29, 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, 0x76, 0x74, 0x63, 0x74, 0x6c, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var file_vtctlservice_proto_goTypes = []any{ @@ -866,120 +878,124 @@ var file_vtctlservice_proto_goTypes = []any{ (*vtctldata.WorkflowStatusRequest)(nil), // 115: vtctldata.WorkflowStatusRequest (*vtctldata.WorkflowSwitchTrafficRequest)(nil), // 116: vtctldata.WorkflowSwitchTrafficRequest (*vtctldata.WorkflowUpdateRequest)(nil), // 117: vtctldata.WorkflowUpdateRequest - (*vtctldata.ExecuteVtctlCommandResponse)(nil), // 118: vtctldata.ExecuteVtctlCommandResponse - (*vtctldata.AddCellInfoResponse)(nil), // 119: vtctldata.AddCellInfoResponse - (*vtctldata.AddCellsAliasResponse)(nil), // 120: vtctldata.AddCellsAliasResponse - (*vtctldata.ApplyRoutingRulesResponse)(nil), // 121: vtctldata.ApplyRoutingRulesResponse - (*vtctldata.ApplySchemaResponse)(nil), // 122: vtctldata.ApplySchemaResponse - (*vtctldata.ApplyKeyspaceRoutingRulesResponse)(nil), // 123: vtctldata.ApplyKeyspaceRoutingRulesResponse - (*vtctldata.ApplyShardRoutingRulesResponse)(nil), // 124: vtctldata.ApplyShardRoutingRulesResponse - (*vtctldata.ApplyVSchemaResponse)(nil), // 125: vtctldata.ApplyVSchemaResponse - (*vtctldata.BackupResponse)(nil), // 126: vtctldata.BackupResponse - (*vtctldata.CancelSchemaMigrationResponse)(nil), // 127: vtctldata.CancelSchemaMigrationResponse - (*vtctldata.ChangeTabletTypeResponse)(nil), // 128: vtctldata.ChangeTabletTypeResponse - (*vtctldata.CheckThrottlerResponse)(nil), // 129: vtctldata.CheckThrottlerResponse - (*vtctldata.CleanupSchemaMigrationResponse)(nil), // 130: vtctldata.CleanupSchemaMigrationResponse - (*vtctldata.CompleteSchemaMigrationResponse)(nil), // 131: vtctldata.CompleteSchemaMigrationResponse - (*vtctldata.CreateKeyspaceResponse)(nil), // 132: vtctldata.CreateKeyspaceResponse - (*vtctldata.CreateShardResponse)(nil), // 133: vtctldata.CreateShardResponse - (*vtctldata.DeleteCellInfoResponse)(nil), // 134: vtctldata.DeleteCellInfoResponse - (*vtctldata.DeleteCellsAliasResponse)(nil), // 135: vtctldata.DeleteCellsAliasResponse - (*vtctldata.DeleteKeyspaceResponse)(nil), // 136: vtctldata.DeleteKeyspaceResponse - (*vtctldata.DeleteShardsResponse)(nil), // 137: vtctldata.DeleteShardsResponse - (*vtctldata.DeleteSrvVSchemaResponse)(nil), // 138: vtctldata.DeleteSrvVSchemaResponse - (*vtctldata.DeleteTabletsResponse)(nil), // 139: vtctldata.DeleteTabletsResponse - (*vtctldata.EmergencyReparentShardResponse)(nil), // 140: vtctldata.EmergencyReparentShardResponse - (*vtctldata.ExecuteFetchAsAppResponse)(nil), // 141: vtctldata.ExecuteFetchAsAppResponse - (*vtctldata.ExecuteFetchAsDBAResponse)(nil), // 142: vtctldata.ExecuteFetchAsDBAResponse - (*vtctldata.ExecuteHookResponse)(nil), // 143: vtctldata.ExecuteHookResponse - (*vtctldata.ExecuteMultiFetchAsDBAResponse)(nil), // 144: vtctldata.ExecuteMultiFetchAsDBAResponse - (*vtctldata.FindAllShardsInKeyspaceResponse)(nil), // 145: vtctldata.FindAllShardsInKeyspaceResponse - (*vtctldata.ForceCutOverSchemaMigrationResponse)(nil), // 146: vtctldata.ForceCutOverSchemaMigrationResponse - (*vtctldata.GetBackupsResponse)(nil), // 147: vtctldata.GetBackupsResponse - (*vtctldata.GetCellInfoResponse)(nil), // 148: vtctldata.GetCellInfoResponse - (*vtctldata.GetCellInfoNamesResponse)(nil), // 149: vtctldata.GetCellInfoNamesResponse - (*vtctldata.GetCellsAliasesResponse)(nil), // 150: vtctldata.GetCellsAliasesResponse - (*vtctldata.GetFullStatusResponse)(nil), // 151: vtctldata.GetFullStatusResponse - (*vtctldata.GetKeyspaceResponse)(nil), // 152: vtctldata.GetKeyspaceResponse - (*vtctldata.GetKeyspacesResponse)(nil), // 153: vtctldata.GetKeyspacesResponse - (*vtctldata.GetKeyspaceRoutingRulesResponse)(nil), // 154: vtctldata.GetKeyspaceRoutingRulesResponse - (*vtctldata.GetPermissionsResponse)(nil), // 155: vtctldata.GetPermissionsResponse - (*vtctldata.GetRoutingRulesResponse)(nil), // 156: vtctldata.GetRoutingRulesResponse - (*vtctldata.GetSchemaResponse)(nil), // 157: vtctldata.GetSchemaResponse - (*vtctldata.GetSchemaMigrationsResponse)(nil), // 158: vtctldata.GetSchemaMigrationsResponse - (*vtctldata.GetShardReplicationResponse)(nil), // 159: vtctldata.GetShardReplicationResponse - (*vtctldata.GetShardResponse)(nil), // 160: vtctldata.GetShardResponse - (*vtctldata.GetShardRoutingRulesResponse)(nil), // 161: vtctldata.GetShardRoutingRulesResponse - (*vtctldata.GetSrvKeyspaceNamesResponse)(nil), // 162: vtctldata.GetSrvKeyspaceNamesResponse - (*vtctldata.GetSrvKeyspacesResponse)(nil), // 163: vtctldata.GetSrvKeyspacesResponse - (*vtctldata.UpdateThrottlerConfigResponse)(nil), // 164: vtctldata.UpdateThrottlerConfigResponse - (*vtctldata.GetSrvVSchemaResponse)(nil), // 165: vtctldata.GetSrvVSchemaResponse - (*vtctldata.GetSrvVSchemasResponse)(nil), // 166: vtctldata.GetSrvVSchemasResponse - (*vtctldata.GetTabletResponse)(nil), // 167: vtctldata.GetTabletResponse - (*vtctldata.GetTabletsResponse)(nil), // 168: vtctldata.GetTabletsResponse - (*vtctldata.GetThrottlerStatusResponse)(nil), // 169: vtctldata.GetThrottlerStatusResponse - (*vtctldata.GetTopologyPathResponse)(nil), // 170: vtctldata.GetTopologyPathResponse - (*vtctldata.GetVersionResponse)(nil), // 171: vtctldata.GetVersionResponse - (*vtctldata.GetVSchemaResponse)(nil), // 172: vtctldata.GetVSchemaResponse - (*vtctldata.GetWorkflowsResponse)(nil), // 173: vtctldata.GetWorkflowsResponse - (*vtctldata.InitShardPrimaryResponse)(nil), // 174: vtctldata.InitShardPrimaryResponse - (*vtctldata.LaunchSchemaMigrationResponse)(nil), // 175: vtctldata.LaunchSchemaMigrationResponse - (*vtctldata.LookupVindexCreateResponse)(nil), // 176: vtctldata.LookupVindexCreateResponse - (*vtctldata.LookupVindexExternalizeResponse)(nil), // 177: vtctldata.LookupVindexExternalizeResponse - (*vtctldata.MaterializeCreateResponse)(nil), // 178: vtctldata.MaterializeCreateResponse - (*vtctldata.WorkflowStatusResponse)(nil), // 179: vtctldata.WorkflowStatusResponse - (*vtctldata.MountRegisterResponse)(nil), // 180: vtctldata.MountRegisterResponse - (*vtctldata.MountUnregisterResponse)(nil), // 181: vtctldata.MountUnregisterResponse - (*vtctldata.MountShowResponse)(nil), // 182: vtctldata.MountShowResponse - (*vtctldata.MountListResponse)(nil), // 183: vtctldata.MountListResponse - (*vtctldata.MoveTablesCompleteResponse)(nil), // 184: vtctldata.MoveTablesCompleteResponse - (*vtctldata.PingTabletResponse)(nil), // 185: vtctldata.PingTabletResponse - (*vtctldata.PlannedReparentShardResponse)(nil), // 186: vtctldata.PlannedReparentShardResponse - (*vtctldata.RebuildKeyspaceGraphResponse)(nil), // 187: vtctldata.RebuildKeyspaceGraphResponse - (*vtctldata.RebuildVSchemaGraphResponse)(nil), // 188: vtctldata.RebuildVSchemaGraphResponse - (*vtctldata.RefreshStateResponse)(nil), // 189: vtctldata.RefreshStateResponse - (*vtctldata.RefreshStateByShardResponse)(nil), // 190: vtctldata.RefreshStateByShardResponse - (*vtctldata.ReloadSchemaResponse)(nil), // 191: vtctldata.ReloadSchemaResponse - (*vtctldata.ReloadSchemaKeyspaceResponse)(nil), // 192: vtctldata.ReloadSchemaKeyspaceResponse - (*vtctldata.ReloadSchemaShardResponse)(nil), // 193: vtctldata.ReloadSchemaShardResponse - (*vtctldata.RemoveBackupResponse)(nil), // 194: vtctldata.RemoveBackupResponse - (*vtctldata.RemoveKeyspaceCellResponse)(nil), // 195: vtctldata.RemoveKeyspaceCellResponse - (*vtctldata.RemoveShardCellResponse)(nil), // 196: vtctldata.RemoveShardCellResponse - (*vtctldata.ReparentTabletResponse)(nil), // 197: vtctldata.ReparentTabletResponse - (*vtctldata.RestoreFromBackupResponse)(nil), // 198: vtctldata.RestoreFromBackupResponse - (*vtctldata.RetrySchemaMigrationResponse)(nil), // 199: vtctldata.RetrySchemaMigrationResponse - (*vtctldata.RunHealthCheckResponse)(nil), // 200: vtctldata.RunHealthCheckResponse - (*vtctldata.SetKeyspaceDurabilityPolicyResponse)(nil), // 201: vtctldata.SetKeyspaceDurabilityPolicyResponse - (*vtctldata.SetShardIsPrimaryServingResponse)(nil), // 202: vtctldata.SetShardIsPrimaryServingResponse - (*vtctldata.SetShardTabletControlResponse)(nil), // 203: vtctldata.SetShardTabletControlResponse - (*vtctldata.SetWritableResponse)(nil), // 204: vtctldata.SetWritableResponse - (*vtctldata.ShardReplicationAddResponse)(nil), // 205: vtctldata.ShardReplicationAddResponse - (*vtctldata.ShardReplicationFixResponse)(nil), // 206: vtctldata.ShardReplicationFixResponse - (*vtctldata.ShardReplicationPositionsResponse)(nil), // 207: vtctldata.ShardReplicationPositionsResponse - (*vtctldata.ShardReplicationRemoveResponse)(nil), // 208: vtctldata.ShardReplicationRemoveResponse - (*vtctldata.SleepTabletResponse)(nil), // 209: vtctldata.SleepTabletResponse - (*vtctldata.SourceShardAddResponse)(nil), // 210: vtctldata.SourceShardAddResponse - (*vtctldata.SourceShardDeleteResponse)(nil), // 211: vtctldata.SourceShardDeleteResponse - (*vtctldata.StartReplicationResponse)(nil), // 212: vtctldata.StartReplicationResponse - (*vtctldata.StopReplicationResponse)(nil), // 213: vtctldata.StopReplicationResponse - (*vtctldata.TabletExternallyReparentedResponse)(nil), // 214: vtctldata.TabletExternallyReparentedResponse - (*vtctldata.UpdateCellInfoResponse)(nil), // 215: vtctldata.UpdateCellInfoResponse - (*vtctldata.UpdateCellsAliasResponse)(nil), // 216: vtctldata.UpdateCellsAliasResponse - (*vtctldata.ValidateResponse)(nil), // 217: vtctldata.ValidateResponse - (*vtctldata.ValidateKeyspaceResponse)(nil), // 218: vtctldata.ValidateKeyspaceResponse - (*vtctldata.ValidateSchemaKeyspaceResponse)(nil), // 219: vtctldata.ValidateSchemaKeyspaceResponse - (*vtctldata.ValidateShardResponse)(nil), // 220: vtctldata.ValidateShardResponse - (*vtctldata.ValidateVersionKeyspaceResponse)(nil), // 221: vtctldata.ValidateVersionKeyspaceResponse - (*vtctldata.ValidateVersionShardResponse)(nil), // 222: vtctldata.ValidateVersionShardResponse - (*vtctldata.ValidateVSchemaResponse)(nil), // 223: vtctldata.ValidateVSchemaResponse - (*vtctldata.VDiffCreateResponse)(nil), // 224: vtctldata.VDiffCreateResponse - (*vtctldata.VDiffDeleteResponse)(nil), // 225: vtctldata.VDiffDeleteResponse - (*vtctldata.VDiffResumeResponse)(nil), // 226: vtctldata.VDiffResumeResponse - (*vtctldata.VDiffShowResponse)(nil), // 227: vtctldata.VDiffShowResponse - (*vtctldata.VDiffStopResponse)(nil), // 228: vtctldata.VDiffStopResponse - (*vtctldata.WorkflowDeleteResponse)(nil), // 229: vtctldata.WorkflowDeleteResponse - (*vtctldata.WorkflowSwitchTrafficResponse)(nil), // 230: vtctldata.WorkflowSwitchTrafficResponse - (*vtctldata.WorkflowUpdateResponse)(nil), // 231: vtctldata.WorkflowUpdateResponse + (*vtctldata.GetMirrorRulesRequest)(nil), // 118: vtctldata.GetMirrorRulesRequest + (*vtctldata.WorkflowMirrorTrafficRequest)(nil), // 119: vtctldata.WorkflowMirrorTrafficRequest + (*vtctldata.ExecuteVtctlCommandResponse)(nil), // 120: vtctldata.ExecuteVtctlCommandResponse + (*vtctldata.AddCellInfoResponse)(nil), // 121: vtctldata.AddCellInfoResponse + (*vtctldata.AddCellsAliasResponse)(nil), // 122: vtctldata.AddCellsAliasResponse + (*vtctldata.ApplyRoutingRulesResponse)(nil), // 123: vtctldata.ApplyRoutingRulesResponse + (*vtctldata.ApplySchemaResponse)(nil), // 124: vtctldata.ApplySchemaResponse + (*vtctldata.ApplyKeyspaceRoutingRulesResponse)(nil), // 125: vtctldata.ApplyKeyspaceRoutingRulesResponse + (*vtctldata.ApplyShardRoutingRulesResponse)(nil), // 126: vtctldata.ApplyShardRoutingRulesResponse + (*vtctldata.ApplyVSchemaResponse)(nil), // 127: vtctldata.ApplyVSchemaResponse + (*vtctldata.BackupResponse)(nil), // 128: vtctldata.BackupResponse + (*vtctldata.CancelSchemaMigrationResponse)(nil), // 129: vtctldata.CancelSchemaMigrationResponse + (*vtctldata.ChangeTabletTypeResponse)(nil), // 130: vtctldata.ChangeTabletTypeResponse + (*vtctldata.CheckThrottlerResponse)(nil), // 131: vtctldata.CheckThrottlerResponse + (*vtctldata.CleanupSchemaMigrationResponse)(nil), // 132: vtctldata.CleanupSchemaMigrationResponse + (*vtctldata.CompleteSchemaMigrationResponse)(nil), // 133: vtctldata.CompleteSchemaMigrationResponse + (*vtctldata.CreateKeyspaceResponse)(nil), // 134: vtctldata.CreateKeyspaceResponse + (*vtctldata.CreateShardResponse)(nil), // 135: vtctldata.CreateShardResponse + (*vtctldata.DeleteCellInfoResponse)(nil), // 136: vtctldata.DeleteCellInfoResponse + (*vtctldata.DeleteCellsAliasResponse)(nil), // 137: vtctldata.DeleteCellsAliasResponse + (*vtctldata.DeleteKeyspaceResponse)(nil), // 138: vtctldata.DeleteKeyspaceResponse + (*vtctldata.DeleteShardsResponse)(nil), // 139: vtctldata.DeleteShardsResponse + (*vtctldata.DeleteSrvVSchemaResponse)(nil), // 140: vtctldata.DeleteSrvVSchemaResponse + (*vtctldata.DeleteTabletsResponse)(nil), // 141: vtctldata.DeleteTabletsResponse + (*vtctldata.EmergencyReparentShardResponse)(nil), // 142: vtctldata.EmergencyReparentShardResponse + (*vtctldata.ExecuteFetchAsAppResponse)(nil), // 143: vtctldata.ExecuteFetchAsAppResponse + (*vtctldata.ExecuteFetchAsDBAResponse)(nil), // 144: vtctldata.ExecuteFetchAsDBAResponse + (*vtctldata.ExecuteHookResponse)(nil), // 145: vtctldata.ExecuteHookResponse + (*vtctldata.ExecuteMultiFetchAsDBAResponse)(nil), // 146: vtctldata.ExecuteMultiFetchAsDBAResponse + (*vtctldata.FindAllShardsInKeyspaceResponse)(nil), // 147: vtctldata.FindAllShardsInKeyspaceResponse + (*vtctldata.ForceCutOverSchemaMigrationResponse)(nil), // 148: vtctldata.ForceCutOverSchemaMigrationResponse + (*vtctldata.GetBackupsResponse)(nil), // 149: vtctldata.GetBackupsResponse + (*vtctldata.GetCellInfoResponse)(nil), // 150: vtctldata.GetCellInfoResponse + (*vtctldata.GetCellInfoNamesResponse)(nil), // 151: vtctldata.GetCellInfoNamesResponse + (*vtctldata.GetCellsAliasesResponse)(nil), // 152: vtctldata.GetCellsAliasesResponse + (*vtctldata.GetFullStatusResponse)(nil), // 153: vtctldata.GetFullStatusResponse + (*vtctldata.GetKeyspaceResponse)(nil), // 154: vtctldata.GetKeyspaceResponse + (*vtctldata.GetKeyspacesResponse)(nil), // 155: vtctldata.GetKeyspacesResponse + (*vtctldata.GetKeyspaceRoutingRulesResponse)(nil), // 156: vtctldata.GetKeyspaceRoutingRulesResponse + (*vtctldata.GetPermissionsResponse)(nil), // 157: vtctldata.GetPermissionsResponse + (*vtctldata.GetRoutingRulesResponse)(nil), // 158: vtctldata.GetRoutingRulesResponse + (*vtctldata.GetSchemaResponse)(nil), // 159: vtctldata.GetSchemaResponse + (*vtctldata.GetSchemaMigrationsResponse)(nil), // 160: vtctldata.GetSchemaMigrationsResponse + (*vtctldata.GetShardReplicationResponse)(nil), // 161: vtctldata.GetShardReplicationResponse + (*vtctldata.GetShardResponse)(nil), // 162: vtctldata.GetShardResponse + (*vtctldata.GetShardRoutingRulesResponse)(nil), // 163: vtctldata.GetShardRoutingRulesResponse + (*vtctldata.GetSrvKeyspaceNamesResponse)(nil), // 164: vtctldata.GetSrvKeyspaceNamesResponse + (*vtctldata.GetSrvKeyspacesResponse)(nil), // 165: vtctldata.GetSrvKeyspacesResponse + (*vtctldata.UpdateThrottlerConfigResponse)(nil), // 166: vtctldata.UpdateThrottlerConfigResponse + (*vtctldata.GetSrvVSchemaResponse)(nil), // 167: vtctldata.GetSrvVSchemaResponse + (*vtctldata.GetSrvVSchemasResponse)(nil), // 168: vtctldata.GetSrvVSchemasResponse + (*vtctldata.GetTabletResponse)(nil), // 169: vtctldata.GetTabletResponse + (*vtctldata.GetTabletsResponse)(nil), // 170: vtctldata.GetTabletsResponse + (*vtctldata.GetThrottlerStatusResponse)(nil), // 171: vtctldata.GetThrottlerStatusResponse + (*vtctldata.GetTopologyPathResponse)(nil), // 172: vtctldata.GetTopologyPathResponse + (*vtctldata.GetVersionResponse)(nil), // 173: vtctldata.GetVersionResponse + (*vtctldata.GetVSchemaResponse)(nil), // 174: vtctldata.GetVSchemaResponse + (*vtctldata.GetWorkflowsResponse)(nil), // 175: vtctldata.GetWorkflowsResponse + (*vtctldata.InitShardPrimaryResponse)(nil), // 176: vtctldata.InitShardPrimaryResponse + (*vtctldata.LaunchSchemaMigrationResponse)(nil), // 177: vtctldata.LaunchSchemaMigrationResponse + (*vtctldata.LookupVindexCreateResponse)(nil), // 178: vtctldata.LookupVindexCreateResponse + (*vtctldata.LookupVindexExternalizeResponse)(nil), // 179: vtctldata.LookupVindexExternalizeResponse + (*vtctldata.MaterializeCreateResponse)(nil), // 180: vtctldata.MaterializeCreateResponse + (*vtctldata.WorkflowStatusResponse)(nil), // 181: vtctldata.WorkflowStatusResponse + (*vtctldata.MountRegisterResponse)(nil), // 182: vtctldata.MountRegisterResponse + (*vtctldata.MountUnregisterResponse)(nil), // 183: vtctldata.MountUnregisterResponse + (*vtctldata.MountShowResponse)(nil), // 184: vtctldata.MountShowResponse + (*vtctldata.MountListResponse)(nil), // 185: vtctldata.MountListResponse + (*vtctldata.MoveTablesCompleteResponse)(nil), // 186: vtctldata.MoveTablesCompleteResponse + (*vtctldata.PingTabletResponse)(nil), // 187: vtctldata.PingTabletResponse + (*vtctldata.PlannedReparentShardResponse)(nil), // 188: vtctldata.PlannedReparentShardResponse + (*vtctldata.RebuildKeyspaceGraphResponse)(nil), // 189: vtctldata.RebuildKeyspaceGraphResponse + (*vtctldata.RebuildVSchemaGraphResponse)(nil), // 190: vtctldata.RebuildVSchemaGraphResponse + (*vtctldata.RefreshStateResponse)(nil), // 191: vtctldata.RefreshStateResponse + (*vtctldata.RefreshStateByShardResponse)(nil), // 192: vtctldata.RefreshStateByShardResponse + (*vtctldata.ReloadSchemaResponse)(nil), // 193: vtctldata.ReloadSchemaResponse + (*vtctldata.ReloadSchemaKeyspaceResponse)(nil), // 194: vtctldata.ReloadSchemaKeyspaceResponse + (*vtctldata.ReloadSchemaShardResponse)(nil), // 195: vtctldata.ReloadSchemaShardResponse + (*vtctldata.RemoveBackupResponse)(nil), // 196: vtctldata.RemoveBackupResponse + (*vtctldata.RemoveKeyspaceCellResponse)(nil), // 197: vtctldata.RemoveKeyspaceCellResponse + (*vtctldata.RemoveShardCellResponse)(nil), // 198: vtctldata.RemoveShardCellResponse + (*vtctldata.ReparentTabletResponse)(nil), // 199: vtctldata.ReparentTabletResponse + (*vtctldata.RestoreFromBackupResponse)(nil), // 200: vtctldata.RestoreFromBackupResponse + (*vtctldata.RetrySchemaMigrationResponse)(nil), // 201: vtctldata.RetrySchemaMigrationResponse + (*vtctldata.RunHealthCheckResponse)(nil), // 202: vtctldata.RunHealthCheckResponse + (*vtctldata.SetKeyspaceDurabilityPolicyResponse)(nil), // 203: vtctldata.SetKeyspaceDurabilityPolicyResponse + (*vtctldata.SetShardIsPrimaryServingResponse)(nil), // 204: vtctldata.SetShardIsPrimaryServingResponse + (*vtctldata.SetShardTabletControlResponse)(nil), // 205: vtctldata.SetShardTabletControlResponse + (*vtctldata.SetWritableResponse)(nil), // 206: vtctldata.SetWritableResponse + (*vtctldata.ShardReplicationAddResponse)(nil), // 207: vtctldata.ShardReplicationAddResponse + (*vtctldata.ShardReplicationFixResponse)(nil), // 208: vtctldata.ShardReplicationFixResponse + (*vtctldata.ShardReplicationPositionsResponse)(nil), // 209: vtctldata.ShardReplicationPositionsResponse + (*vtctldata.ShardReplicationRemoveResponse)(nil), // 210: vtctldata.ShardReplicationRemoveResponse + (*vtctldata.SleepTabletResponse)(nil), // 211: vtctldata.SleepTabletResponse + (*vtctldata.SourceShardAddResponse)(nil), // 212: vtctldata.SourceShardAddResponse + (*vtctldata.SourceShardDeleteResponse)(nil), // 213: vtctldata.SourceShardDeleteResponse + (*vtctldata.StartReplicationResponse)(nil), // 214: vtctldata.StartReplicationResponse + (*vtctldata.StopReplicationResponse)(nil), // 215: vtctldata.StopReplicationResponse + (*vtctldata.TabletExternallyReparentedResponse)(nil), // 216: vtctldata.TabletExternallyReparentedResponse + (*vtctldata.UpdateCellInfoResponse)(nil), // 217: vtctldata.UpdateCellInfoResponse + (*vtctldata.UpdateCellsAliasResponse)(nil), // 218: vtctldata.UpdateCellsAliasResponse + (*vtctldata.ValidateResponse)(nil), // 219: vtctldata.ValidateResponse + (*vtctldata.ValidateKeyspaceResponse)(nil), // 220: vtctldata.ValidateKeyspaceResponse + (*vtctldata.ValidateSchemaKeyspaceResponse)(nil), // 221: vtctldata.ValidateSchemaKeyspaceResponse + (*vtctldata.ValidateShardResponse)(nil), // 222: vtctldata.ValidateShardResponse + (*vtctldata.ValidateVersionKeyspaceResponse)(nil), // 223: vtctldata.ValidateVersionKeyspaceResponse + (*vtctldata.ValidateVersionShardResponse)(nil), // 224: vtctldata.ValidateVersionShardResponse + (*vtctldata.ValidateVSchemaResponse)(nil), // 225: vtctldata.ValidateVSchemaResponse + (*vtctldata.VDiffCreateResponse)(nil), // 226: vtctldata.VDiffCreateResponse + (*vtctldata.VDiffDeleteResponse)(nil), // 227: vtctldata.VDiffDeleteResponse + (*vtctldata.VDiffResumeResponse)(nil), // 228: vtctldata.VDiffResumeResponse + (*vtctldata.VDiffShowResponse)(nil), // 229: vtctldata.VDiffShowResponse + (*vtctldata.VDiffStopResponse)(nil), // 230: vtctldata.VDiffStopResponse + (*vtctldata.WorkflowDeleteResponse)(nil), // 231: vtctldata.WorkflowDeleteResponse + (*vtctldata.WorkflowSwitchTrafficResponse)(nil), // 232: vtctldata.WorkflowSwitchTrafficResponse + (*vtctldata.WorkflowUpdateResponse)(nil), // 233: vtctldata.WorkflowUpdateResponse + (*vtctldata.GetMirrorRulesResponse)(nil), // 234: vtctldata.GetMirrorRulesResponse + (*vtctldata.WorkflowMirrorTrafficResponse)(nil), // 235: vtctldata.WorkflowMirrorTrafficResponse } var file_vtctlservice_proto_depIdxs = []int32{ 0, // 0: vtctlservice.Vtctl.ExecuteVtctlCommand:input_type -> vtctldata.ExecuteVtctlCommandRequest @@ -1100,126 +1116,130 @@ var file_vtctlservice_proto_depIdxs = []int32{ 115, // 115: vtctlservice.Vtctld.WorkflowStatus:input_type -> vtctldata.WorkflowStatusRequest 116, // 116: vtctlservice.Vtctld.WorkflowSwitchTraffic:input_type -> vtctldata.WorkflowSwitchTrafficRequest 117, // 117: vtctlservice.Vtctld.WorkflowUpdate:input_type -> vtctldata.WorkflowUpdateRequest - 118, // 118: vtctlservice.Vtctl.ExecuteVtctlCommand:output_type -> vtctldata.ExecuteVtctlCommandResponse - 119, // 119: vtctlservice.Vtctld.AddCellInfo:output_type -> vtctldata.AddCellInfoResponse - 120, // 120: vtctlservice.Vtctld.AddCellsAlias:output_type -> vtctldata.AddCellsAliasResponse - 121, // 121: vtctlservice.Vtctld.ApplyRoutingRules:output_type -> vtctldata.ApplyRoutingRulesResponse - 122, // 122: vtctlservice.Vtctld.ApplySchema:output_type -> vtctldata.ApplySchemaResponse - 123, // 123: vtctlservice.Vtctld.ApplyKeyspaceRoutingRules:output_type -> vtctldata.ApplyKeyspaceRoutingRulesResponse - 124, // 124: vtctlservice.Vtctld.ApplyShardRoutingRules:output_type -> vtctldata.ApplyShardRoutingRulesResponse - 125, // 125: vtctlservice.Vtctld.ApplyVSchema:output_type -> vtctldata.ApplyVSchemaResponse - 126, // 126: vtctlservice.Vtctld.Backup:output_type -> vtctldata.BackupResponse - 126, // 127: vtctlservice.Vtctld.BackupShard:output_type -> vtctldata.BackupResponse - 127, // 128: vtctlservice.Vtctld.CancelSchemaMigration:output_type -> vtctldata.CancelSchemaMigrationResponse - 128, // 129: vtctlservice.Vtctld.ChangeTabletType:output_type -> vtctldata.ChangeTabletTypeResponse - 129, // 130: vtctlservice.Vtctld.CheckThrottler:output_type -> vtctldata.CheckThrottlerResponse - 130, // 131: vtctlservice.Vtctld.CleanupSchemaMigration:output_type -> vtctldata.CleanupSchemaMigrationResponse - 131, // 132: vtctlservice.Vtctld.CompleteSchemaMigration:output_type -> vtctldata.CompleteSchemaMigrationResponse - 132, // 133: vtctlservice.Vtctld.CreateKeyspace:output_type -> vtctldata.CreateKeyspaceResponse - 133, // 134: vtctlservice.Vtctld.CreateShard:output_type -> vtctldata.CreateShardResponse - 134, // 135: vtctlservice.Vtctld.DeleteCellInfo:output_type -> vtctldata.DeleteCellInfoResponse - 135, // 136: vtctlservice.Vtctld.DeleteCellsAlias:output_type -> vtctldata.DeleteCellsAliasResponse - 136, // 137: vtctlservice.Vtctld.DeleteKeyspace:output_type -> vtctldata.DeleteKeyspaceResponse - 137, // 138: vtctlservice.Vtctld.DeleteShards:output_type -> vtctldata.DeleteShardsResponse - 138, // 139: vtctlservice.Vtctld.DeleteSrvVSchema:output_type -> vtctldata.DeleteSrvVSchemaResponse - 139, // 140: vtctlservice.Vtctld.DeleteTablets:output_type -> vtctldata.DeleteTabletsResponse - 140, // 141: vtctlservice.Vtctld.EmergencyReparentShard:output_type -> vtctldata.EmergencyReparentShardResponse - 141, // 142: vtctlservice.Vtctld.ExecuteFetchAsApp:output_type -> vtctldata.ExecuteFetchAsAppResponse - 142, // 143: vtctlservice.Vtctld.ExecuteFetchAsDBA:output_type -> vtctldata.ExecuteFetchAsDBAResponse - 143, // 144: vtctlservice.Vtctld.ExecuteHook:output_type -> vtctldata.ExecuteHookResponse - 144, // 145: vtctlservice.Vtctld.ExecuteMultiFetchAsDBA:output_type -> vtctldata.ExecuteMultiFetchAsDBAResponse - 145, // 146: vtctlservice.Vtctld.FindAllShardsInKeyspace:output_type -> vtctldata.FindAllShardsInKeyspaceResponse - 146, // 147: vtctlservice.Vtctld.ForceCutOverSchemaMigration:output_type -> vtctldata.ForceCutOverSchemaMigrationResponse - 147, // 148: vtctlservice.Vtctld.GetBackups:output_type -> vtctldata.GetBackupsResponse - 148, // 149: vtctlservice.Vtctld.GetCellInfo:output_type -> vtctldata.GetCellInfoResponse - 149, // 150: vtctlservice.Vtctld.GetCellInfoNames:output_type -> vtctldata.GetCellInfoNamesResponse - 150, // 151: vtctlservice.Vtctld.GetCellsAliases:output_type -> vtctldata.GetCellsAliasesResponse - 151, // 152: vtctlservice.Vtctld.GetFullStatus:output_type -> vtctldata.GetFullStatusResponse - 152, // 153: vtctlservice.Vtctld.GetKeyspace:output_type -> vtctldata.GetKeyspaceResponse - 153, // 154: vtctlservice.Vtctld.GetKeyspaces:output_type -> vtctldata.GetKeyspacesResponse - 154, // 155: vtctlservice.Vtctld.GetKeyspaceRoutingRules:output_type -> vtctldata.GetKeyspaceRoutingRulesResponse - 155, // 156: vtctlservice.Vtctld.GetPermissions:output_type -> vtctldata.GetPermissionsResponse - 156, // 157: vtctlservice.Vtctld.GetRoutingRules:output_type -> vtctldata.GetRoutingRulesResponse - 157, // 158: vtctlservice.Vtctld.GetSchema:output_type -> vtctldata.GetSchemaResponse - 158, // 159: vtctlservice.Vtctld.GetSchemaMigrations:output_type -> vtctldata.GetSchemaMigrationsResponse - 159, // 160: vtctlservice.Vtctld.GetShardReplication:output_type -> vtctldata.GetShardReplicationResponse - 160, // 161: vtctlservice.Vtctld.GetShard:output_type -> vtctldata.GetShardResponse - 161, // 162: vtctlservice.Vtctld.GetShardRoutingRules:output_type -> vtctldata.GetShardRoutingRulesResponse - 162, // 163: vtctlservice.Vtctld.GetSrvKeyspaceNames:output_type -> vtctldata.GetSrvKeyspaceNamesResponse - 163, // 164: vtctlservice.Vtctld.GetSrvKeyspaces:output_type -> vtctldata.GetSrvKeyspacesResponse - 164, // 165: vtctlservice.Vtctld.UpdateThrottlerConfig:output_type -> vtctldata.UpdateThrottlerConfigResponse - 165, // 166: vtctlservice.Vtctld.GetSrvVSchema:output_type -> vtctldata.GetSrvVSchemaResponse - 166, // 167: vtctlservice.Vtctld.GetSrvVSchemas:output_type -> vtctldata.GetSrvVSchemasResponse - 167, // 168: vtctlservice.Vtctld.GetTablet:output_type -> vtctldata.GetTabletResponse - 168, // 169: vtctlservice.Vtctld.GetTablets:output_type -> vtctldata.GetTabletsResponse - 169, // 170: vtctlservice.Vtctld.GetThrottlerStatus:output_type -> vtctldata.GetThrottlerStatusResponse - 170, // 171: vtctlservice.Vtctld.GetTopologyPath:output_type -> vtctldata.GetTopologyPathResponse - 171, // 172: vtctlservice.Vtctld.GetVersion:output_type -> vtctldata.GetVersionResponse - 172, // 173: vtctlservice.Vtctld.GetVSchema:output_type -> vtctldata.GetVSchemaResponse - 173, // 174: vtctlservice.Vtctld.GetWorkflows:output_type -> vtctldata.GetWorkflowsResponse - 174, // 175: vtctlservice.Vtctld.InitShardPrimary:output_type -> vtctldata.InitShardPrimaryResponse - 175, // 176: vtctlservice.Vtctld.LaunchSchemaMigration:output_type -> vtctldata.LaunchSchemaMigrationResponse - 176, // 177: vtctlservice.Vtctld.LookupVindexCreate:output_type -> vtctldata.LookupVindexCreateResponse - 177, // 178: vtctlservice.Vtctld.LookupVindexExternalize:output_type -> vtctldata.LookupVindexExternalizeResponse - 178, // 179: vtctlservice.Vtctld.MaterializeCreate:output_type -> vtctldata.MaterializeCreateResponse - 179, // 180: vtctlservice.Vtctld.MigrateCreate:output_type -> vtctldata.WorkflowStatusResponse - 180, // 181: vtctlservice.Vtctld.MountRegister:output_type -> vtctldata.MountRegisterResponse - 181, // 182: vtctlservice.Vtctld.MountUnregister:output_type -> vtctldata.MountUnregisterResponse - 182, // 183: vtctlservice.Vtctld.MountShow:output_type -> vtctldata.MountShowResponse - 183, // 184: vtctlservice.Vtctld.MountList:output_type -> vtctldata.MountListResponse - 179, // 185: vtctlservice.Vtctld.MoveTablesCreate:output_type -> vtctldata.WorkflowStatusResponse - 184, // 186: vtctlservice.Vtctld.MoveTablesComplete:output_type -> vtctldata.MoveTablesCompleteResponse - 185, // 187: vtctlservice.Vtctld.PingTablet:output_type -> vtctldata.PingTabletResponse - 186, // 188: vtctlservice.Vtctld.PlannedReparentShard:output_type -> vtctldata.PlannedReparentShardResponse - 187, // 189: vtctlservice.Vtctld.RebuildKeyspaceGraph:output_type -> vtctldata.RebuildKeyspaceGraphResponse - 188, // 190: vtctlservice.Vtctld.RebuildVSchemaGraph:output_type -> vtctldata.RebuildVSchemaGraphResponse - 189, // 191: vtctlservice.Vtctld.RefreshState:output_type -> vtctldata.RefreshStateResponse - 190, // 192: vtctlservice.Vtctld.RefreshStateByShard:output_type -> vtctldata.RefreshStateByShardResponse - 191, // 193: vtctlservice.Vtctld.ReloadSchema:output_type -> vtctldata.ReloadSchemaResponse - 192, // 194: vtctlservice.Vtctld.ReloadSchemaKeyspace:output_type -> vtctldata.ReloadSchemaKeyspaceResponse - 193, // 195: vtctlservice.Vtctld.ReloadSchemaShard:output_type -> vtctldata.ReloadSchemaShardResponse - 194, // 196: vtctlservice.Vtctld.RemoveBackup:output_type -> vtctldata.RemoveBackupResponse - 195, // 197: vtctlservice.Vtctld.RemoveKeyspaceCell:output_type -> vtctldata.RemoveKeyspaceCellResponse - 196, // 198: vtctlservice.Vtctld.RemoveShardCell:output_type -> vtctldata.RemoveShardCellResponse - 197, // 199: vtctlservice.Vtctld.ReparentTablet:output_type -> vtctldata.ReparentTabletResponse - 179, // 200: vtctlservice.Vtctld.ReshardCreate:output_type -> vtctldata.WorkflowStatusResponse - 198, // 201: vtctlservice.Vtctld.RestoreFromBackup:output_type -> vtctldata.RestoreFromBackupResponse - 199, // 202: vtctlservice.Vtctld.RetrySchemaMigration:output_type -> vtctldata.RetrySchemaMigrationResponse - 200, // 203: vtctlservice.Vtctld.RunHealthCheck:output_type -> vtctldata.RunHealthCheckResponse - 201, // 204: vtctlservice.Vtctld.SetKeyspaceDurabilityPolicy:output_type -> vtctldata.SetKeyspaceDurabilityPolicyResponse - 202, // 205: vtctlservice.Vtctld.SetShardIsPrimaryServing:output_type -> vtctldata.SetShardIsPrimaryServingResponse - 203, // 206: vtctlservice.Vtctld.SetShardTabletControl:output_type -> vtctldata.SetShardTabletControlResponse - 204, // 207: vtctlservice.Vtctld.SetWritable:output_type -> vtctldata.SetWritableResponse - 205, // 208: vtctlservice.Vtctld.ShardReplicationAdd:output_type -> vtctldata.ShardReplicationAddResponse - 206, // 209: vtctlservice.Vtctld.ShardReplicationFix:output_type -> vtctldata.ShardReplicationFixResponse - 207, // 210: vtctlservice.Vtctld.ShardReplicationPositions:output_type -> vtctldata.ShardReplicationPositionsResponse - 208, // 211: vtctlservice.Vtctld.ShardReplicationRemove:output_type -> vtctldata.ShardReplicationRemoveResponse - 209, // 212: vtctlservice.Vtctld.SleepTablet:output_type -> vtctldata.SleepTabletResponse - 210, // 213: vtctlservice.Vtctld.SourceShardAdd:output_type -> vtctldata.SourceShardAddResponse - 211, // 214: vtctlservice.Vtctld.SourceShardDelete:output_type -> vtctldata.SourceShardDeleteResponse - 212, // 215: vtctlservice.Vtctld.StartReplication:output_type -> vtctldata.StartReplicationResponse - 213, // 216: vtctlservice.Vtctld.StopReplication:output_type -> vtctldata.StopReplicationResponse - 214, // 217: vtctlservice.Vtctld.TabletExternallyReparented:output_type -> vtctldata.TabletExternallyReparentedResponse - 215, // 218: vtctlservice.Vtctld.UpdateCellInfo:output_type -> vtctldata.UpdateCellInfoResponse - 216, // 219: vtctlservice.Vtctld.UpdateCellsAlias:output_type -> vtctldata.UpdateCellsAliasResponse - 217, // 220: vtctlservice.Vtctld.Validate:output_type -> vtctldata.ValidateResponse - 218, // 221: vtctlservice.Vtctld.ValidateKeyspace:output_type -> vtctldata.ValidateKeyspaceResponse - 219, // 222: vtctlservice.Vtctld.ValidateSchemaKeyspace:output_type -> vtctldata.ValidateSchemaKeyspaceResponse - 220, // 223: vtctlservice.Vtctld.ValidateShard:output_type -> vtctldata.ValidateShardResponse - 221, // 224: vtctlservice.Vtctld.ValidateVersionKeyspace:output_type -> vtctldata.ValidateVersionKeyspaceResponse - 222, // 225: vtctlservice.Vtctld.ValidateVersionShard:output_type -> vtctldata.ValidateVersionShardResponse - 223, // 226: vtctlservice.Vtctld.ValidateVSchema:output_type -> vtctldata.ValidateVSchemaResponse - 224, // 227: vtctlservice.Vtctld.VDiffCreate:output_type -> vtctldata.VDiffCreateResponse - 225, // 228: vtctlservice.Vtctld.VDiffDelete:output_type -> vtctldata.VDiffDeleteResponse - 226, // 229: vtctlservice.Vtctld.VDiffResume:output_type -> vtctldata.VDiffResumeResponse - 227, // 230: vtctlservice.Vtctld.VDiffShow:output_type -> vtctldata.VDiffShowResponse - 228, // 231: vtctlservice.Vtctld.VDiffStop:output_type -> vtctldata.VDiffStopResponse - 229, // 232: vtctlservice.Vtctld.WorkflowDelete:output_type -> vtctldata.WorkflowDeleteResponse - 179, // 233: vtctlservice.Vtctld.WorkflowStatus:output_type -> vtctldata.WorkflowStatusResponse - 230, // 234: vtctlservice.Vtctld.WorkflowSwitchTraffic:output_type -> vtctldata.WorkflowSwitchTrafficResponse - 231, // 235: vtctlservice.Vtctld.WorkflowUpdate:output_type -> vtctldata.WorkflowUpdateResponse - 118, // [118:236] is the sub-list for method output_type - 0, // [0:118] is the sub-list for method input_type + 118, // 118: vtctlservice.Vtctld.GetMirrorRules:input_type -> vtctldata.GetMirrorRulesRequest + 119, // 119: vtctlservice.Vtctld.WorkflowMirrorTraffic:input_type -> vtctldata.WorkflowMirrorTrafficRequest + 120, // 120: vtctlservice.Vtctl.ExecuteVtctlCommand:output_type -> vtctldata.ExecuteVtctlCommandResponse + 121, // 121: vtctlservice.Vtctld.AddCellInfo:output_type -> vtctldata.AddCellInfoResponse + 122, // 122: vtctlservice.Vtctld.AddCellsAlias:output_type -> vtctldata.AddCellsAliasResponse + 123, // 123: vtctlservice.Vtctld.ApplyRoutingRules:output_type -> vtctldata.ApplyRoutingRulesResponse + 124, // 124: vtctlservice.Vtctld.ApplySchema:output_type -> vtctldata.ApplySchemaResponse + 125, // 125: vtctlservice.Vtctld.ApplyKeyspaceRoutingRules:output_type -> vtctldata.ApplyKeyspaceRoutingRulesResponse + 126, // 126: vtctlservice.Vtctld.ApplyShardRoutingRules:output_type -> vtctldata.ApplyShardRoutingRulesResponse + 127, // 127: vtctlservice.Vtctld.ApplyVSchema:output_type -> vtctldata.ApplyVSchemaResponse + 128, // 128: vtctlservice.Vtctld.Backup:output_type -> vtctldata.BackupResponse + 128, // 129: vtctlservice.Vtctld.BackupShard:output_type -> vtctldata.BackupResponse + 129, // 130: vtctlservice.Vtctld.CancelSchemaMigration:output_type -> vtctldata.CancelSchemaMigrationResponse + 130, // 131: vtctlservice.Vtctld.ChangeTabletType:output_type -> vtctldata.ChangeTabletTypeResponse + 131, // 132: vtctlservice.Vtctld.CheckThrottler:output_type -> vtctldata.CheckThrottlerResponse + 132, // 133: vtctlservice.Vtctld.CleanupSchemaMigration:output_type -> vtctldata.CleanupSchemaMigrationResponse + 133, // 134: vtctlservice.Vtctld.CompleteSchemaMigration:output_type -> vtctldata.CompleteSchemaMigrationResponse + 134, // 135: vtctlservice.Vtctld.CreateKeyspace:output_type -> vtctldata.CreateKeyspaceResponse + 135, // 136: vtctlservice.Vtctld.CreateShard:output_type -> vtctldata.CreateShardResponse + 136, // 137: vtctlservice.Vtctld.DeleteCellInfo:output_type -> vtctldata.DeleteCellInfoResponse + 137, // 138: vtctlservice.Vtctld.DeleteCellsAlias:output_type -> vtctldata.DeleteCellsAliasResponse + 138, // 139: vtctlservice.Vtctld.DeleteKeyspace:output_type -> vtctldata.DeleteKeyspaceResponse + 139, // 140: vtctlservice.Vtctld.DeleteShards:output_type -> vtctldata.DeleteShardsResponse + 140, // 141: vtctlservice.Vtctld.DeleteSrvVSchema:output_type -> vtctldata.DeleteSrvVSchemaResponse + 141, // 142: vtctlservice.Vtctld.DeleteTablets:output_type -> vtctldata.DeleteTabletsResponse + 142, // 143: vtctlservice.Vtctld.EmergencyReparentShard:output_type -> vtctldata.EmergencyReparentShardResponse + 143, // 144: vtctlservice.Vtctld.ExecuteFetchAsApp:output_type -> vtctldata.ExecuteFetchAsAppResponse + 144, // 145: vtctlservice.Vtctld.ExecuteFetchAsDBA:output_type -> vtctldata.ExecuteFetchAsDBAResponse + 145, // 146: vtctlservice.Vtctld.ExecuteHook:output_type -> vtctldata.ExecuteHookResponse + 146, // 147: vtctlservice.Vtctld.ExecuteMultiFetchAsDBA:output_type -> vtctldata.ExecuteMultiFetchAsDBAResponse + 147, // 148: vtctlservice.Vtctld.FindAllShardsInKeyspace:output_type -> vtctldata.FindAllShardsInKeyspaceResponse + 148, // 149: vtctlservice.Vtctld.ForceCutOverSchemaMigration:output_type -> vtctldata.ForceCutOverSchemaMigrationResponse + 149, // 150: vtctlservice.Vtctld.GetBackups:output_type -> vtctldata.GetBackupsResponse + 150, // 151: vtctlservice.Vtctld.GetCellInfo:output_type -> vtctldata.GetCellInfoResponse + 151, // 152: vtctlservice.Vtctld.GetCellInfoNames:output_type -> vtctldata.GetCellInfoNamesResponse + 152, // 153: vtctlservice.Vtctld.GetCellsAliases:output_type -> vtctldata.GetCellsAliasesResponse + 153, // 154: vtctlservice.Vtctld.GetFullStatus:output_type -> vtctldata.GetFullStatusResponse + 154, // 155: vtctlservice.Vtctld.GetKeyspace:output_type -> vtctldata.GetKeyspaceResponse + 155, // 156: vtctlservice.Vtctld.GetKeyspaces:output_type -> vtctldata.GetKeyspacesResponse + 156, // 157: vtctlservice.Vtctld.GetKeyspaceRoutingRules:output_type -> vtctldata.GetKeyspaceRoutingRulesResponse + 157, // 158: vtctlservice.Vtctld.GetPermissions:output_type -> vtctldata.GetPermissionsResponse + 158, // 159: vtctlservice.Vtctld.GetRoutingRules:output_type -> vtctldata.GetRoutingRulesResponse + 159, // 160: vtctlservice.Vtctld.GetSchema:output_type -> vtctldata.GetSchemaResponse + 160, // 161: vtctlservice.Vtctld.GetSchemaMigrations:output_type -> vtctldata.GetSchemaMigrationsResponse + 161, // 162: vtctlservice.Vtctld.GetShardReplication:output_type -> vtctldata.GetShardReplicationResponse + 162, // 163: vtctlservice.Vtctld.GetShard:output_type -> vtctldata.GetShardResponse + 163, // 164: vtctlservice.Vtctld.GetShardRoutingRules:output_type -> vtctldata.GetShardRoutingRulesResponse + 164, // 165: vtctlservice.Vtctld.GetSrvKeyspaceNames:output_type -> vtctldata.GetSrvKeyspaceNamesResponse + 165, // 166: vtctlservice.Vtctld.GetSrvKeyspaces:output_type -> vtctldata.GetSrvKeyspacesResponse + 166, // 167: vtctlservice.Vtctld.UpdateThrottlerConfig:output_type -> vtctldata.UpdateThrottlerConfigResponse + 167, // 168: vtctlservice.Vtctld.GetSrvVSchema:output_type -> vtctldata.GetSrvVSchemaResponse + 168, // 169: vtctlservice.Vtctld.GetSrvVSchemas:output_type -> vtctldata.GetSrvVSchemasResponse + 169, // 170: vtctlservice.Vtctld.GetTablet:output_type -> vtctldata.GetTabletResponse + 170, // 171: vtctlservice.Vtctld.GetTablets:output_type -> vtctldata.GetTabletsResponse + 171, // 172: vtctlservice.Vtctld.GetThrottlerStatus:output_type -> vtctldata.GetThrottlerStatusResponse + 172, // 173: vtctlservice.Vtctld.GetTopologyPath:output_type -> vtctldata.GetTopologyPathResponse + 173, // 174: vtctlservice.Vtctld.GetVersion:output_type -> vtctldata.GetVersionResponse + 174, // 175: vtctlservice.Vtctld.GetVSchema:output_type -> vtctldata.GetVSchemaResponse + 175, // 176: vtctlservice.Vtctld.GetWorkflows:output_type -> vtctldata.GetWorkflowsResponse + 176, // 177: vtctlservice.Vtctld.InitShardPrimary:output_type -> vtctldata.InitShardPrimaryResponse + 177, // 178: vtctlservice.Vtctld.LaunchSchemaMigration:output_type -> vtctldata.LaunchSchemaMigrationResponse + 178, // 179: vtctlservice.Vtctld.LookupVindexCreate:output_type -> vtctldata.LookupVindexCreateResponse + 179, // 180: vtctlservice.Vtctld.LookupVindexExternalize:output_type -> vtctldata.LookupVindexExternalizeResponse + 180, // 181: vtctlservice.Vtctld.MaterializeCreate:output_type -> vtctldata.MaterializeCreateResponse + 181, // 182: vtctlservice.Vtctld.MigrateCreate:output_type -> vtctldata.WorkflowStatusResponse + 182, // 183: vtctlservice.Vtctld.MountRegister:output_type -> vtctldata.MountRegisterResponse + 183, // 184: vtctlservice.Vtctld.MountUnregister:output_type -> vtctldata.MountUnregisterResponse + 184, // 185: vtctlservice.Vtctld.MountShow:output_type -> vtctldata.MountShowResponse + 185, // 186: vtctlservice.Vtctld.MountList:output_type -> vtctldata.MountListResponse + 181, // 187: vtctlservice.Vtctld.MoveTablesCreate:output_type -> vtctldata.WorkflowStatusResponse + 186, // 188: vtctlservice.Vtctld.MoveTablesComplete:output_type -> vtctldata.MoveTablesCompleteResponse + 187, // 189: vtctlservice.Vtctld.PingTablet:output_type -> vtctldata.PingTabletResponse + 188, // 190: vtctlservice.Vtctld.PlannedReparentShard:output_type -> vtctldata.PlannedReparentShardResponse + 189, // 191: vtctlservice.Vtctld.RebuildKeyspaceGraph:output_type -> vtctldata.RebuildKeyspaceGraphResponse + 190, // 192: vtctlservice.Vtctld.RebuildVSchemaGraph:output_type -> vtctldata.RebuildVSchemaGraphResponse + 191, // 193: vtctlservice.Vtctld.RefreshState:output_type -> vtctldata.RefreshStateResponse + 192, // 194: vtctlservice.Vtctld.RefreshStateByShard:output_type -> vtctldata.RefreshStateByShardResponse + 193, // 195: vtctlservice.Vtctld.ReloadSchema:output_type -> vtctldata.ReloadSchemaResponse + 194, // 196: vtctlservice.Vtctld.ReloadSchemaKeyspace:output_type -> vtctldata.ReloadSchemaKeyspaceResponse + 195, // 197: vtctlservice.Vtctld.ReloadSchemaShard:output_type -> vtctldata.ReloadSchemaShardResponse + 196, // 198: vtctlservice.Vtctld.RemoveBackup:output_type -> vtctldata.RemoveBackupResponse + 197, // 199: vtctlservice.Vtctld.RemoveKeyspaceCell:output_type -> vtctldata.RemoveKeyspaceCellResponse + 198, // 200: vtctlservice.Vtctld.RemoveShardCell:output_type -> vtctldata.RemoveShardCellResponse + 199, // 201: vtctlservice.Vtctld.ReparentTablet:output_type -> vtctldata.ReparentTabletResponse + 181, // 202: vtctlservice.Vtctld.ReshardCreate:output_type -> vtctldata.WorkflowStatusResponse + 200, // 203: vtctlservice.Vtctld.RestoreFromBackup:output_type -> vtctldata.RestoreFromBackupResponse + 201, // 204: vtctlservice.Vtctld.RetrySchemaMigration:output_type -> vtctldata.RetrySchemaMigrationResponse + 202, // 205: vtctlservice.Vtctld.RunHealthCheck:output_type -> vtctldata.RunHealthCheckResponse + 203, // 206: vtctlservice.Vtctld.SetKeyspaceDurabilityPolicy:output_type -> vtctldata.SetKeyspaceDurabilityPolicyResponse + 204, // 207: vtctlservice.Vtctld.SetShardIsPrimaryServing:output_type -> vtctldata.SetShardIsPrimaryServingResponse + 205, // 208: vtctlservice.Vtctld.SetShardTabletControl:output_type -> vtctldata.SetShardTabletControlResponse + 206, // 209: vtctlservice.Vtctld.SetWritable:output_type -> vtctldata.SetWritableResponse + 207, // 210: vtctlservice.Vtctld.ShardReplicationAdd:output_type -> vtctldata.ShardReplicationAddResponse + 208, // 211: vtctlservice.Vtctld.ShardReplicationFix:output_type -> vtctldata.ShardReplicationFixResponse + 209, // 212: vtctlservice.Vtctld.ShardReplicationPositions:output_type -> vtctldata.ShardReplicationPositionsResponse + 210, // 213: vtctlservice.Vtctld.ShardReplicationRemove:output_type -> vtctldata.ShardReplicationRemoveResponse + 211, // 214: vtctlservice.Vtctld.SleepTablet:output_type -> vtctldata.SleepTabletResponse + 212, // 215: vtctlservice.Vtctld.SourceShardAdd:output_type -> vtctldata.SourceShardAddResponse + 213, // 216: vtctlservice.Vtctld.SourceShardDelete:output_type -> vtctldata.SourceShardDeleteResponse + 214, // 217: vtctlservice.Vtctld.StartReplication:output_type -> vtctldata.StartReplicationResponse + 215, // 218: vtctlservice.Vtctld.StopReplication:output_type -> vtctldata.StopReplicationResponse + 216, // 219: vtctlservice.Vtctld.TabletExternallyReparented:output_type -> vtctldata.TabletExternallyReparentedResponse + 217, // 220: vtctlservice.Vtctld.UpdateCellInfo:output_type -> vtctldata.UpdateCellInfoResponse + 218, // 221: vtctlservice.Vtctld.UpdateCellsAlias:output_type -> vtctldata.UpdateCellsAliasResponse + 219, // 222: vtctlservice.Vtctld.Validate:output_type -> vtctldata.ValidateResponse + 220, // 223: vtctlservice.Vtctld.ValidateKeyspace:output_type -> vtctldata.ValidateKeyspaceResponse + 221, // 224: vtctlservice.Vtctld.ValidateSchemaKeyspace:output_type -> vtctldata.ValidateSchemaKeyspaceResponse + 222, // 225: vtctlservice.Vtctld.ValidateShard:output_type -> vtctldata.ValidateShardResponse + 223, // 226: vtctlservice.Vtctld.ValidateVersionKeyspace:output_type -> vtctldata.ValidateVersionKeyspaceResponse + 224, // 227: vtctlservice.Vtctld.ValidateVersionShard:output_type -> vtctldata.ValidateVersionShardResponse + 225, // 228: vtctlservice.Vtctld.ValidateVSchema:output_type -> vtctldata.ValidateVSchemaResponse + 226, // 229: vtctlservice.Vtctld.VDiffCreate:output_type -> vtctldata.VDiffCreateResponse + 227, // 230: vtctlservice.Vtctld.VDiffDelete:output_type -> vtctldata.VDiffDeleteResponse + 228, // 231: vtctlservice.Vtctld.VDiffResume:output_type -> vtctldata.VDiffResumeResponse + 229, // 232: vtctlservice.Vtctld.VDiffShow:output_type -> vtctldata.VDiffShowResponse + 230, // 233: vtctlservice.Vtctld.VDiffStop:output_type -> vtctldata.VDiffStopResponse + 231, // 234: vtctlservice.Vtctld.WorkflowDelete:output_type -> vtctldata.WorkflowDeleteResponse + 181, // 235: vtctlservice.Vtctld.WorkflowStatus:output_type -> vtctldata.WorkflowStatusResponse + 232, // 236: vtctlservice.Vtctld.WorkflowSwitchTraffic:output_type -> vtctldata.WorkflowSwitchTrafficResponse + 233, // 237: vtctlservice.Vtctld.WorkflowUpdate:output_type -> vtctldata.WorkflowUpdateResponse + 234, // 238: vtctlservice.Vtctld.GetMirrorRules:output_type -> vtctldata.GetMirrorRulesResponse + 235, // 239: vtctlservice.Vtctld.WorkflowMirrorTraffic:output_type -> vtctldata.WorkflowMirrorTrafficResponse + 120, // [120:240] is the sub-list for method output_type + 0, // [0:120] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name diff --git a/go/vt/proto/vtctlservice/vtctlservice_grpc.pb.go b/go/vt/proto/vtctlservice/vtctlservice_grpc.pb.go index 0d336619ac0..56cef8d1dcd 100644 --- a/go/vt/proto/vtctlservice/vtctlservice_grpc.pb.go +++ b/go/vt/proto/vtctlservice/vtctlservice_grpc.pb.go @@ -464,6 +464,9 @@ type VtctldClient interface { // WorkflowUpdate updates the configuration of a vreplication workflow // using the provided updated parameters. WorkflowUpdate(ctx context.Context, in *vtctldata.WorkflowUpdateRequest, opts ...grpc.CallOption) (*vtctldata.WorkflowUpdateResponse, error) + // GetMirrorRules returns the VSchema routing rules. + GetMirrorRules(ctx context.Context, in *vtctldata.GetMirrorRulesRequest, opts ...grpc.CallOption) (*vtctldata.GetMirrorRulesResponse, error) + WorkflowMirrorTraffic(ctx context.Context, in *vtctldata.WorkflowMirrorTrafficRequest, opts ...grpc.CallOption) (*vtctldata.WorkflowMirrorTrafficResponse, error) } type vtctldClient struct { @@ -1596,6 +1599,24 @@ func (c *vtctldClient) WorkflowUpdate(ctx context.Context, in *vtctldata.Workflo return out, nil } +func (c *vtctldClient) GetMirrorRules(ctx context.Context, in *vtctldata.GetMirrorRulesRequest, opts ...grpc.CallOption) (*vtctldata.GetMirrorRulesResponse, error) { + out := new(vtctldata.GetMirrorRulesResponse) + err := c.cc.Invoke(ctx, "/vtctlservice.Vtctld/GetMirrorRules", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *vtctldClient) WorkflowMirrorTraffic(ctx context.Context, in *vtctldata.WorkflowMirrorTrafficRequest, opts ...grpc.CallOption) (*vtctldata.WorkflowMirrorTrafficResponse, error) { + out := new(vtctldata.WorkflowMirrorTrafficResponse) + err := c.cc.Invoke(ctx, "/vtctlservice.Vtctld/WorkflowMirrorTraffic", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // VtctldServer is the server API for Vtctld service. // All implementations must embed UnimplementedVtctldServer // for forward compatibility @@ -1928,6 +1949,9 @@ type VtctldServer interface { // WorkflowUpdate updates the configuration of a vreplication workflow // using the provided updated parameters. WorkflowUpdate(context.Context, *vtctldata.WorkflowUpdateRequest) (*vtctldata.WorkflowUpdateResponse, error) + // GetMirrorRules returns the VSchema routing rules. + GetMirrorRules(context.Context, *vtctldata.GetMirrorRulesRequest) (*vtctldata.GetMirrorRulesResponse, error) + WorkflowMirrorTraffic(context.Context, *vtctldata.WorkflowMirrorTrafficRequest) (*vtctldata.WorkflowMirrorTrafficResponse, error) mustEmbedUnimplementedVtctldServer() } @@ -2286,6 +2310,12 @@ func (UnimplementedVtctldServer) WorkflowSwitchTraffic(context.Context, *vtctlda func (UnimplementedVtctldServer) WorkflowUpdate(context.Context, *vtctldata.WorkflowUpdateRequest) (*vtctldata.WorkflowUpdateResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method WorkflowUpdate not implemented") } +func (UnimplementedVtctldServer) GetMirrorRules(context.Context, *vtctldata.GetMirrorRulesRequest) (*vtctldata.GetMirrorRulesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetMirrorRules not implemented") +} +func (UnimplementedVtctldServer) WorkflowMirrorTraffic(context.Context, *vtctldata.WorkflowMirrorTrafficRequest) (*vtctldata.WorkflowMirrorTrafficResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method WorkflowMirrorTraffic not implemented") +} func (UnimplementedVtctldServer) mustEmbedUnimplementedVtctldServer() {} // UnsafeVtctldServer may be embedded to opt out of forward compatibility for this service. @@ -4414,6 +4444,42 @@ func _Vtctld_WorkflowUpdate_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } +func _Vtctld_GetMirrorRules_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(vtctldata.GetMirrorRulesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(VtctldServer).GetMirrorRules(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/vtctlservice.Vtctld/GetMirrorRules", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(VtctldServer).GetMirrorRules(ctx, req.(*vtctldata.GetMirrorRulesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Vtctld_WorkflowMirrorTraffic_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(vtctldata.WorkflowMirrorTrafficRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(VtctldServer).WorkflowMirrorTraffic(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/vtctlservice.Vtctld/WorkflowMirrorTraffic", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(VtctldServer).WorkflowMirrorTraffic(ctx, req.(*vtctldata.WorkflowMirrorTrafficRequest)) + } + return interceptor(ctx, in, info, handler) +} + // Vtctld_ServiceDesc is the grpc.ServiceDesc for Vtctld service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -4877,6 +4943,14 @@ var Vtctld_ServiceDesc = grpc.ServiceDesc{ MethodName: "WorkflowUpdate", Handler: _Vtctld_WorkflowUpdate_Handler, }, + { + MethodName: "GetMirrorRules", + Handler: _Vtctld_GetMirrorRules_Handler, + }, + { + MethodName: "WorkflowMirrorTraffic", + Handler: _Vtctld_WorkflowMirrorTraffic_Handler, + }, }, Streams: []grpc.StreamDesc{ { diff --git a/go/vt/proto/vtgateservice/vtgateservice.pb.go b/go/vt/proto/vtgateservice/vtgateservice.pb.go index fbe32f082e9..165e3c0bbef 100644 --- a/go/vt/proto/vtgateservice/vtgateservice.pb.go +++ b/go/vt/proto/vtgateservice/vtgateservice.pb.go @@ -44,7 +44,7 @@ var file_vtgateservice_proto_rawDesc = []byte{ 0x0a, 0x13, 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x1a, 0x0c, 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x32, 0x8f, 0x04, 0x0a, 0x06, 0x56, 0x69, 0x74, 0x65, 0x73, 0x73, 0x12, 0x3c, 0x0a, + 0x74, 0x6f, 0x32, 0xb0, 0x03, 0x0a, 0x06, 0x56, 0x69, 0x74, 0x65, 0x73, 0x73, 0x12, 0x3c, 0x0a, 0x07, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, @@ -58,65 +58,56 @@ var file_vtgateservice_proto_rawDesc = []byte{ 0x74, 0x65, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x5d, 0x0a, 0x12, 0x52, 0x65, - 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x21, 0x2e, 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, - 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x73, - 0x6f, 0x6c, 0x76, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x07, 0x56, 0x53, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x12, 0x16, 0x2e, 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x56, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x76, - 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x3c, 0x0a, 0x07, 0x50, 0x72, 0x65, - 0x70, 0x61, 0x72, 0x65, 0x12, 0x16, 0x2e, 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x50, 0x72, - 0x65, 0x70, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x76, - 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0c, 0x43, 0x6c, 0x6f, 0x73, 0x65, - 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x2e, 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, - 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x6c, - 0x6f, 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x42, 0x42, 0x0a, 0x14, 0x69, 0x6f, 0x2e, 0x76, 0x69, 0x74, 0x65, 0x73, - 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5a, 0x2a, 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, 0x76, 0x74, 0x67, 0x61, 0x74, - 0x65, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x3e, 0x0a, 0x07, 0x56, 0x53, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x16, 0x2e, 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x56, + 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, + 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x56, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x3c, 0x0a, 0x07, 0x50, 0x72, + 0x65, 0x70, 0x61, 0x72, 0x65, 0x12, 0x16, 0x2e, 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x50, + 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, + 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0c, 0x43, 0x6c, 0x6f, 0x73, + 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x2e, 0x76, 0x74, 0x67, 0x61, 0x74, + 0x65, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x76, 0x74, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x43, + 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x42, 0x0a, 0x14, 0x69, 0x6f, 0x2e, 0x76, 0x69, 0x74, 0x65, + 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5a, 0x2a, 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, 0x76, 0x74, 0x67, 0x61, + 0x74, 0x65, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var file_vtgateservice_proto_goTypes = []any{ - (*vtgate.ExecuteRequest)(nil), // 0: vtgate.ExecuteRequest - (*vtgate.ExecuteBatchRequest)(nil), // 1: vtgate.ExecuteBatchRequest - (*vtgate.StreamExecuteRequest)(nil), // 2: vtgate.StreamExecuteRequest - (*vtgate.ResolveTransactionRequest)(nil), // 3: vtgate.ResolveTransactionRequest - (*vtgate.VStreamRequest)(nil), // 4: vtgate.VStreamRequest - (*vtgate.PrepareRequest)(nil), // 5: vtgate.PrepareRequest - (*vtgate.CloseSessionRequest)(nil), // 6: vtgate.CloseSessionRequest - (*vtgate.ExecuteResponse)(nil), // 7: vtgate.ExecuteResponse - (*vtgate.ExecuteBatchResponse)(nil), // 8: vtgate.ExecuteBatchResponse - (*vtgate.StreamExecuteResponse)(nil), // 9: vtgate.StreamExecuteResponse - (*vtgate.ResolveTransactionResponse)(nil), // 10: vtgate.ResolveTransactionResponse - (*vtgate.VStreamResponse)(nil), // 11: vtgate.VStreamResponse - (*vtgate.PrepareResponse)(nil), // 12: vtgate.PrepareResponse - (*vtgate.CloseSessionResponse)(nil), // 13: vtgate.CloseSessionResponse + (*vtgate.ExecuteRequest)(nil), // 0: vtgate.ExecuteRequest + (*vtgate.ExecuteBatchRequest)(nil), // 1: vtgate.ExecuteBatchRequest + (*vtgate.StreamExecuteRequest)(nil), // 2: vtgate.StreamExecuteRequest + (*vtgate.VStreamRequest)(nil), // 3: vtgate.VStreamRequest + (*vtgate.PrepareRequest)(nil), // 4: vtgate.PrepareRequest + (*vtgate.CloseSessionRequest)(nil), // 5: vtgate.CloseSessionRequest + (*vtgate.ExecuteResponse)(nil), // 6: vtgate.ExecuteResponse + (*vtgate.ExecuteBatchResponse)(nil), // 7: vtgate.ExecuteBatchResponse + (*vtgate.StreamExecuteResponse)(nil), // 8: vtgate.StreamExecuteResponse + (*vtgate.VStreamResponse)(nil), // 9: vtgate.VStreamResponse + (*vtgate.PrepareResponse)(nil), // 10: vtgate.PrepareResponse + (*vtgate.CloseSessionResponse)(nil), // 11: vtgate.CloseSessionResponse } var file_vtgateservice_proto_depIdxs = []int32{ 0, // 0: vtgateservice.Vitess.Execute:input_type -> vtgate.ExecuteRequest 1, // 1: vtgateservice.Vitess.ExecuteBatch:input_type -> vtgate.ExecuteBatchRequest 2, // 2: vtgateservice.Vitess.StreamExecute:input_type -> vtgate.StreamExecuteRequest - 3, // 3: vtgateservice.Vitess.ResolveTransaction:input_type -> vtgate.ResolveTransactionRequest - 4, // 4: vtgateservice.Vitess.VStream:input_type -> vtgate.VStreamRequest - 5, // 5: vtgateservice.Vitess.Prepare:input_type -> vtgate.PrepareRequest - 6, // 6: vtgateservice.Vitess.CloseSession:input_type -> vtgate.CloseSessionRequest - 7, // 7: vtgateservice.Vitess.Execute:output_type -> vtgate.ExecuteResponse - 8, // 8: vtgateservice.Vitess.ExecuteBatch:output_type -> vtgate.ExecuteBatchResponse - 9, // 9: vtgateservice.Vitess.StreamExecute:output_type -> vtgate.StreamExecuteResponse - 10, // 10: vtgateservice.Vitess.ResolveTransaction:output_type -> vtgate.ResolveTransactionResponse - 11, // 11: vtgateservice.Vitess.VStream:output_type -> vtgate.VStreamResponse - 12, // 12: vtgateservice.Vitess.Prepare:output_type -> vtgate.PrepareResponse - 13, // 13: vtgateservice.Vitess.CloseSession:output_type -> vtgate.CloseSessionResponse - 7, // [7:14] is the sub-list for method output_type - 0, // [0:7] is the sub-list for method input_type + 3, // 3: vtgateservice.Vitess.VStream:input_type -> vtgate.VStreamRequest + 4, // 4: vtgateservice.Vitess.Prepare:input_type -> vtgate.PrepareRequest + 5, // 5: vtgateservice.Vitess.CloseSession:input_type -> vtgate.CloseSessionRequest + 6, // 6: vtgateservice.Vitess.Execute:output_type -> vtgate.ExecuteResponse + 7, // 7: vtgateservice.Vitess.ExecuteBatch:output_type -> vtgate.ExecuteBatchResponse + 8, // 8: vtgateservice.Vitess.StreamExecute:output_type -> vtgate.StreamExecuteResponse + 9, // 9: vtgateservice.Vitess.VStream:output_type -> vtgate.VStreamResponse + 10, // 10: vtgateservice.Vitess.Prepare:output_type -> vtgate.PrepareResponse + 11, // 11: vtgateservice.Vitess.CloseSession:output_type -> vtgate.CloseSessionResponse + 6, // [6:12] is the sub-list for method output_type + 0, // [0:6] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name diff --git a/go/vt/proto/vtgateservice/vtgateservice_grpc.pb.go b/go/vt/proto/vtgateservice/vtgateservice_grpc.pb.go index 44dd83d7f0b..80042781649 100644 --- a/go/vt/proto/vtgateservice/vtgateservice_grpc.pb.go +++ b/go/vt/proto/vtgateservice/vtgateservice_grpc.pb.go @@ -39,9 +39,6 @@ type VitessClient interface { // Use this method if the query returns a large number of rows. // API group: v3 StreamExecute(ctx context.Context, in *vtgate.StreamExecuteRequest, opts ...grpc.CallOption) (Vitess_StreamExecuteClient, error) - // ResolveTransaction resolves a transaction. - // API group: Transactions - ResolveTransaction(ctx context.Context, in *vtgate.ResolveTransactionRequest, opts ...grpc.CallOption) (*vtgate.ResolveTransactionResponse, error) // VStream streams binlog events from the requested sources. VStream(ctx context.Context, in *vtgate.VStreamRequest, opts ...grpc.CallOption) (Vitess_VStreamClient, error) // Prepare is used by the MySQL server plugin as part of supporting prepared statements. @@ -110,15 +107,6 @@ func (x *vitessStreamExecuteClient) Recv() (*vtgate.StreamExecuteResponse, error return m, nil } -func (c *vitessClient) ResolveTransaction(ctx context.Context, in *vtgate.ResolveTransactionRequest, opts ...grpc.CallOption) (*vtgate.ResolveTransactionResponse, error) { - out := new(vtgate.ResolveTransactionResponse) - err := c.cc.Invoke(ctx, "/vtgateservice.Vitess/ResolveTransaction", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *vitessClient) VStream(ctx context.Context, in *vtgate.VStreamRequest, opts ...grpc.CallOption) (Vitess_VStreamClient, error) { stream, err := c.cc.NewStream(ctx, &Vitess_ServiceDesc.Streams[1], "/vtgateservice.Vitess/VStream", opts...) if err != nil { @@ -189,9 +177,6 @@ type VitessServer interface { // Use this method if the query returns a large number of rows. // API group: v3 StreamExecute(*vtgate.StreamExecuteRequest, Vitess_StreamExecuteServer) error - // ResolveTransaction resolves a transaction. - // API group: Transactions - ResolveTransaction(context.Context, *vtgate.ResolveTransactionRequest) (*vtgate.ResolveTransactionResponse, error) // VStream streams binlog events from the requested sources. VStream(*vtgate.VStreamRequest, Vitess_VStreamServer) error // Prepare is used by the MySQL server plugin as part of supporting prepared statements. @@ -216,9 +201,6 @@ func (UnimplementedVitessServer) ExecuteBatch(context.Context, *vtgate.ExecuteBa func (UnimplementedVitessServer) StreamExecute(*vtgate.StreamExecuteRequest, Vitess_StreamExecuteServer) error { return status.Errorf(codes.Unimplemented, "method StreamExecute not implemented") } -func (UnimplementedVitessServer) ResolveTransaction(context.Context, *vtgate.ResolveTransactionRequest) (*vtgate.ResolveTransactionResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ResolveTransaction not implemented") -} func (UnimplementedVitessServer) VStream(*vtgate.VStreamRequest, Vitess_VStreamServer) error { return status.Errorf(codes.Unimplemented, "method VStream not implemented") } @@ -298,24 +280,6 @@ func (x *vitessStreamExecuteServer) Send(m *vtgate.StreamExecuteResponse) error return x.ServerStream.SendMsg(m) } -func _Vitess_ResolveTransaction_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(vtgate.ResolveTransactionRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(VitessServer).ResolveTransaction(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/vtgateservice.Vitess/ResolveTransaction", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(VitessServer).ResolveTransaction(ctx, req.(*vtgate.ResolveTransactionRequest)) - } - return interceptor(ctx, in, info, handler) -} - func _Vitess_VStream_Handler(srv interface{}, stream grpc.ServerStream) error { m := new(vtgate.VStreamRequest) if err := stream.RecvMsg(m); err != nil { @@ -388,10 +352,6 @@ var Vitess_ServiceDesc = grpc.ServiceDesc{ MethodName: "ExecuteBatch", Handler: _Vitess_ExecuteBatch_Handler, }, - { - MethodName: "ResolveTransaction", - Handler: _Vitess_ResolveTransaction_Handler, - }, { MethodName: "Prepare", Handler: _Vitess_Prepare_Handler, diff --git a/go/vt/proto/vttest/vttest.pb.go b/go/vt/proto/vttest/vttest.pb.go index 0f34089ae16..8dca7c6f112 100644 --- a/go/vt/proto/vttest/vttest.pb.go +++ b/go/vt/proto/vttest/vttest.pb.go @@ -212,6 +212,8 @@ type VTTestTopology struct { Cells []string `protobuf:"bytes,2,rep,name=cells,proto3" json:"cells,omitempty"` // routing rules for the topology. RoutingRules *vschema.RoutingRules `protobuf:"bytes,3,opt,name=routing_rules,json=routingRules,proto3" json:"routing_rules,omitempty"` + // mirror rules for the topology. + MirrorRules *vschema.MirrorRules `protobuf:"bytes,4,opt,name=mirror_rules,json=mirrorRules,proto3" json:"mirror_rules,omitempty"` } func (x *VTTestTopology) Reset() { @@ -267,6 +269,13 @@ func (x *VTTestTopology) GetRoutingRules() *vschema.RoutingRules { return nil } +func (x *VTTestTopology) GetMirrorRules() *vschema.MirrorRules { + if x != nil { + return x.MirrorRules + } + return nil +} + var File_vttest_proto protoreflect.FileDescriptor var file_vttest_proto_rawDesc = []byte{ @@ -286,7 +295,7 @@ var file_vttest_proto_rawDesc = []byte{ 0x6c, 0x69, 0x63, 0x61, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x72, 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x4a, 0x04, 0x08, 0x03, - 0x10, 0x04, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0x92, + 0x10, 0x04, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0xcb, 0x01, 0x0a, 0x0e, 0x56, 0x54, 0x54, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x12, 0x2e, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x74, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x4b, 0x65, @@ -296,10 +305,13 @@ var file_vttest_proto_rawDesc = []byte{ 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x76, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x0c, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, - 0x6c, 0x65, 0x73, 0x42, 0x25, 0x5a, 0x23, 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, 0x76, 0x74, 0x74, 0x65, 0x73, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x6c, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x0c, 0x6d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x72, 0x75, + 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x73, 0x63, 0x68, + 0x65, 0x6d, 0x61, 0x2e, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, + 0x0b, 0x6d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x42, 0x25, 0x5a, 0x23, + 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, 0x76, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -320,16 +332,18 @@ var file_vttest_proto_goTypes = []any{ (*Keyspace)(nil), // 1: vttest.Keyspace (*VTTestTopology)(nil), // 2: vttest.VTTestTopology (*vschema.RoutingRules)(nil), // 3: vschema.RoutingRules + (*vschema.MirrorRules)(nil), // 4: vschema.MirrorRules } var file_vttest_proto_depIdxs = []int32{ 0, // 0: vttest.Keyspace.shards:type_name -> vttest.Shard 1, // 1: vttest.VTTestTopology.keyspaces:type_name -> vttest.Keyspace 3, // 2: vttest.VTTestTopology.routing_rules:type_name -> vschema.RoutingRules - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 4, // 3: vttest.VTTestTopology.mirror_rules:type_name -> vschema.MirrorRules + 4, // [4:4] is the sub-list for method output_type + 4, // [4:4] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name } func init() { file_vttest_proto_init() } diff --git a/go/vt/proto/vttest/vttest_vtproto.pb.go b/go/vt/proto/vttest/vttest_vtproto.pb.go index 8000a036a5f..82ad7a17e2c 100644 --- a/go/vt/proto/vttest/vttest_vtproto.pb.go +++ b/go/vt/proto/vttest/vttest_vtproto.pb.go @@ -72,6 +72,7 @@ func (m *VTTestTopology) CloneVT() *VTTestTopology { } r := &VTTestTopology{ RoutingRules: m.RoutingRules.CloneVT(), + MirrorRules: m.MirrorRules.CloneVT(), } if rhs := m.Keyspaces; rhs != nil { tmpContainer := make([]*Keyspace, len(rhs)) @@ -235,6 +236,16 @@ func (m *VTTestTopology) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.MirrorRules != nil { + size, err := m.MirrorRules.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x22 + } if m.RoutingRules != nil { size, err := m.RoutingRules.MarshalToSizedBufferVT(dAtA[:i]) if err != nil { @@ -346,6 +357,10 @@ func (m *VTTestTopology) SizeVT() (n int) { l = m.RoutingRules.SizeVT() n += 1 + l + sov(uint64(l)) } + if m.MirrorRules != nil { + l = m.MirrorRules.SizeVT() + n += 1 + l + sov(uint64(l)) + } n += len(m.unknownFields) return n } @@ -757,6 +772,42 @@ func (m *VTTestTopology) UnmarshalVT(dAtA []byte) error { return err } iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MirrorRules", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.MirrorRules == nil { + m.MirrorRules = &vschema.MirrorRules{} + } + if err := m.MirrorRules.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) diff --git a/go/vt/schema/online_ddl.go b/go/vt/schema/online_ddl.go index 7b8647f86b7..59363b00889 100644 --- a/go/vt/schema/online_ddl.go +++ b/go/vt/schema/online_ddl.go @@ -223,35 +223,21 @@ func NewOnlineDDL(keyspace string, table string, sql string, ddlStrategySetting encodeDirective(string(ddlStrategySetting.Strategy)), encodeDirective(ddlStrategySetting.Options), )} - if uuid, err := legacyParseRevertUUID(sql); err == nil { - sql = fmt.Sprintf("revert vitess_migration '%s'", uuid) - } stmt, err := parser.Parse(sql) if err != nil { - isLegacyRevertStatement := false - // query validation and rebuilding - if _, err := legacyParseRevertUUID(sql); err == nil { - // This is a revert statement of the form "revert ". We allow this for now. Future work will - // make sure the statement is a valid, parseable "revert vitess_migration ''", but we must - // be backwards compatible for now. - isLegacyRevertStatement = true - } - if !isLegacyRevertStatement { - // otherwise the statement should have been parseable! - return nil, err - } - } else { - switch stmt := stmt.(type) { - case sqlparser.DDLStatement: - stmt.SetComments(comments) - case *sqlparser.RevertMigration: - stmt.SetComments(comments) - default: - return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "Unsupported statement for Online DDL: %v", sqlparser.String(stmt)) - } - sql = sqlparser.String(stmt) + return nil, err + } + switch stmt := stmt.(type) { + case sqlparser.DDLStatement: + stmt.SetComments(comments) + case *sqlparser.RevertMigration: + stmt.SetComments(comments) + default: + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "Unsupported statement for Online DDL: %v", sqlparser.String(stmt)) } + sql = sqlparser.String(stmt) + } return &OnlineDDL{ @@ -354,14 +340,7 @@ func (onlineDDL *OnlineDDL) sqlWithoutComments(parser *sqlparser.Parser) (sql st sql = onlineDDL.SQL stmt, err := parser.Parse(sql) if err != nil { - // query validation and rebuilding - if _, err := legacyParseRevertUUID(sql); err == nil { - // This is a revert statement of the form "revert ". We allow this for now. Future work will - // make sure the statement is a valid, parseable "revert vitess_migration ''", but we must - // be backwards compatible for now. - return sql, nil - } - // otherwise the statement should have been parseable! + // The statement should have been parseable! return "", err } @@ -421,9 +400,6 @@ func (onlineDDL *OnlineDDL) GetActionStr(parser *sqlparser.Parser) (action sqlpa // fo the reverted migration. // The function returns error when this is not a revert migration. func (onlineDDL *OnlineDDL) GetRevertUUID(parser *sqlparser.Parser) (uuid string, err error) { - if uuid, err := legacyParseRevertUUID(onlineDDL.SQL); err == nil { - return uuid, nil - } if stmt, err := parser.Parse(onlineDDL.SQL); err == nil { if revert, ok := stmt.(*sqlparser.RevertMigration); ok { return revert.UUID, nil diff --git a/go/vt/schema/online_ddl_test.go b/go/vt/schema/online_ddl_test.go index c443f6b28ce..dad92904854 100644 --- a/go/vt/schema/online_ddl_test.go +++ b/go/vt/schema/online_ddl_test.go @@ -157,10 +157,14 @@ func TestGetRevertUUID(t *testing.T) { }{ { statement: "revert 4e5dcf80_354b_11eb_82cd_f875a4d24e90", - uuid: "4e5dcf80_354b_11eb_82cd_f875a4d24e90", + isError: true, }, { statement: "REVERT 4e5dcf80_354b_11eb_82cd_f875a4d24e90", + isError: true, + }, + { + statement: "revert vitess_migration '4e5dcf80_354b_11eb_82cd_f875a4d24e90'", uuid: "4e5dcf80_354b_11eb_82cd_f875a4d24e90", }, { @@ -185,6 +189,9 @@ func TestGetRevertUUID(t *testing.T) { for _, ts := range tt { t.Run(ts.statement, func(t *testing.T) { onlineDDL, err := NewOnlineDDL("test_ks", "t", ts.statement, NewDDLStrategySetting(DDLStrategyOnline, ""), migrationContext, "", parser) + if err != nil && ts.isError { + return + } assert.NoError(t, err) require.NotNil(t, onlineDDL) uuid, err := onlineDDL.GetRevertUUID(parser) diff --git a/go/vt/schema/parser.go b/go/vt/schema/parser.go index 78ec4ec36e6..7f5e133e01c 100644 --- a/go/vt/schema/parser.go +++ b/go/vt/schema/parser.go @@ -17,7 +17,6 @@ limitations under the License. package schema import ( - "fmt" "regexp" "strings" @@ -50,7 +49,6 @@ var ( // ALTER TABLE tbl something regexp.MustCompile(alterTableBasicPattern + `([\S]+)\s+(.*$)`), } - revertStatementRegexp = regexp.MustCompile(`(?i)^revert\s+([\S]*)$`) enumValuesRegexp = regexp.MustCompile("(?i)^enum[(](.*)[)]$") setValuesRegexp = regexp.MustCompile("(?i)^set[(](.*)[)]$") @@ -79,19 +77,6 @@ func ParseAlterTableOptions(alterStatement string) (explicitSchema, explicitTabl return explicitSchema, explicitTable, alterOptions } -// legacyParseRevertUUID expects a query like "revert 4e5dcf80_354b_11eb_82cd_f875a4d24e90" and returns the UUID value. -func legacyParseRevertUUID(sql string) (uuid string, err error) { - submatch := revertStatementRegexp.FindStringSubmatch(sql) - if len(submatch) == 0 { - return "", fmt.Errorf("Not a Revert DDL: '%s'", sql) - } - uuid = submatch[1] - if !IsOnlineDDLUUID(uuid) { - return "", fmt.Errorf("Not an online DDL UUID: '%s'", uuid) - } - return uuid, nil -} - // ParseEnumValues parses the comma delimited part of an enum column definition func ParseEnumValues(enumColumnType string) string { if submatch := enumValuesRegexp.FindStringSubmatch(enumColumnType); len(submatch) > 0 { diff --git a/go/vt/schema/parser_test.go b/go/vt/schema/parser_test.go index fe9264c29b9..dc696fd3d1d 100644 --- a/go/vt/schema/parser_test.go +++ b/go/vt/schema/parser_test.go @@ -48,23 +48,6 @@ func TestParseAlterTableOptions(t *testing.T) { } } -func TestLegacyParseRevertUUID(t *testing.T) { - - { - uuid, err := legacyParseRevertUUID("revert 4e5dcf80_354b_11eb_82cd_f875a4d24e90") - assert.NoError(t, err) - assert.Equal(t, "4e5dcf80_354b_11eb_82cd_f875a4d24e90", uuid) - } - { - _, err := legacyParseRevertUUID("revert 4e5dcf80_354b_11eb_82cd_f875a4") - assert.Error(t, err) - } - { - _, err := legacyParseRevertUUID("revert vitess_migration '4e5dcf80_354b_11eb_82cd_f875a4d24e90'") - assert.Error(t, err) - } -} - func TestParseEnumValues(t *testing.T) { { inputs := []string{ diff --git a/go/vt/schemadiff/column.go b/go/vt/schemadiff/column.go index da2145f3ab0..7e55192cb06 100644 --- a/go/vt/schemadiff/column.go +++ b/go/vt/schemadiff/column.go @@ -71,11 +71,66 @@ func NewModifyColumnDiffByDefinition(definition *sqlparser.ColumnDefinition) *Mo } type ColumnDefinitionEntity struct { - columnDefinition *sqlparser.ColumnDefinition + columnDefinition *sqlparser.ColumnDefinition + tableCharsetCollate *charsetCollate + Env *Environment } -func NewColumnDefinitionEntity(c *sqlparser.ColumnDefinition) *ColumnDefinitionEntity { - return &ColumnDefinitionEntity{columnDefinition: c} +func NewColumnDefinitionEntity(env *Environment, c *sqlparser.ColumnDefinition, tableCharsetCollate *charsetCollate) *ColumnDefinitionEntity { + return &ColumnDefinitionEntity{ + columnDefinition: c, + tableCharsetCollate: tableCharsetCollate, + Env: env, + } +} + +func (c *ColumnDefinitionEntity) Clone() *ColumnDefinitionEntity { + clone := &ColumnDefinitionEntity{ + columnDefinition: sqlparser.Clone(c.columnDefinition), + tableCharsetCollate: c.tableCharsetCollate, + Env: c.Env, + } + return clone +} + +// SetExplicitCharsetCollate enriches this column definition with collation and charset. Those may be +// already present, or perhaps just one of them is present (in which case we use the one to populate the other), +// or both might be missing, in which case we use the table's charset/collation. +func (c *ColumnDefinitionEntity) SetExplicitCharsetCollate() error { + if !c.IsTextual() { + return nil + } + // We will now denormalize the columns charset & collate as needed (if empty, populate from table.) + // Normalizing _this_ column definition: + if c.columnDefinition.Type.Charset.Name != "" && c.columnDefinition.Type.Options.Collate == "" { + // Charset defined without collation. Assign the default collation for that charset. + collation := c.Env.CollationEnv().DefaultCollationForCharset(c.columnDefinition.Type.Charset.Name) + if collation == collations.Unknown { + return &UnknownColumnCharsetCollationError{Column: c.columnDefinition.Name.String(), Charset: c.tableCharsetCollate.charset} + } + c.columnDefinition.Type.Options.Collate = c.Env.CollationEnv().LookupName(collation) + } + if c.columnDefinition.Type.Charset.Name == "" && c.columnDefinition.Type.Options.Collate != "" { + // Column has explicit collation but no charset. We can infer the charset from the collation. + collationID := c.Env.CollationEnv().LookupByName(c.columnDefinition.Type.Options.Collate) + charset := c.Env.CollationEnv().LookupCharsetName(collationID) + if charset == "" { + return &UnknownColumnCollationCharsetError{Column: c.columnDefinition.Name.String(), Collation: c.columnDefinition.Type.Options.Collate} + } + c.columnDefinition.Type.Charset.Name = charset + } + if c.columnDefinition.Type.Charset.Name == "" { + // Still nothing? Assign the table's charset/collation. + c.columnDefinition.Type.Charset.Name = c.tableCharsetCollate.charset + if c.columnDefinition.Type.Options.Collate = c.tableCharsetCollate.collate; c.columnDefinition.Type.Options.Collate == "" { + collation := c.Env.CollationEnv().DefaultCollationForCharset(c.tableCharsetCollate.charset) + if collation == collations.Unknown { + return &UnknownColumnCharsetCollationError{Column: c.columnDefinition.Name.String(), Charset: c.tableCharsetCollate.charset} + } + c.columnDefinition.Type.Options.Collate = c.Env.CollationEnv().LookupName(collation) + } + } + return nil } // ColumnDiff compares this table statement with another table statement, and sees what it takes to @@ -98,100 +153,22 @@ func (c *ColumnDefinitionEntity) ColumnDiff( env *Environment, tableName string, other *ColumnDefinitionEntity, - t1cc *charsetCollate, - t2cc *charsetCollate, hints *DiffHints, ) (*ModifyColumnDiff, error) { + cClone := c // not real clone yet + otherClone := other // not real clone yet if c.IsTextual() || other.IsTextual() { - // We will now denormalize the columns charset & collate as needed (if empty, populate from table.) - // Normalizing _this_ column definition: - if c.columnDefinition.Type.Charset.Name != "" && c.columnDefinition.Type.Options.Collate == "" { - // Charset defined without collation. Assign the default collation for that charset. - collation := env.CollationEnv().DefaultCollationForCharset(c.columnDefinition.Type.Charset.Name) - if collation == collations.Unknown { - return nil, &UnknownColumnCharsetCollationError{Column: c.columnDefinition.Name.String(), Charset: t1cc.charset} - } - defer func() { - c.columnDefinition.Type.Options.Collate = "" - }() - c.columnDefinition.Type.Options.Collate = env.CollationEnv().LookupName(collation) - } - if c.columnDefinition.Type.Charset.Name == "" && c.columnDefinition.Type.Options.Collate != "" { - // Column has explicit collation but no charset. We can infer the charset from the collation. - collationID := env.CollationEnv().LookupByName(c.columnDefinition.Type.Options.Collate) - charset := env.CollationEnv().LookupCharsetName(collationID) - if charset == "" { - return nil, &UnknownColumnCollationCharsetError{Column: c.columnDefinition.Name.String(), Collation: c.columnDefinition.Type.Options.Collate} - } - defer func() { - c.columnDefinition.Type.Charset.Name = "" - }() - c.columnDefinition.Type.Charset.Name = charset - } - if c.columnDefinition.Type.Charset.Name == "" { - // Still nothing? Assign the table's charset/collation. - defer func() { - c.columnDefinition.Type.Charset.Name = "" - c.columnDefinition.Type.Options.Collate = "" - }() - c.columnDefinition.Type.Charset.Name = t1cc.charset - if c.columnDefinition.Type.Options.Collate == "" { - defer func() { - c.columnDefinition.Type.Options.Collate = "" - }() - c.columnDefinition.Type.Options.Collate = t1cc.collate - } - if c.columnDefinition.Type.Options.Collate = t1cc.collate; c.columnDefinition.Type.Options.Collate == "" { - collation := env.CollationEnv().DefaultCollationForCharset(t1cc.charset) - if collation == collations.Unknown { - return nil, &UnknownColumnCharsetCollationError{Column: c.columnDefinition.Name.String(), Charset: t1cc.charset} - } - c.columnDefinition.Type.Options.Collate = env.CollationEnv().LookupName(collation) - } + cClone = c.Clone() + if err := cClone.SetExplicitCharsetCollate(); err != nil { + return nil, err } - // Normalizing _the other_ column definition: - if other.columnDefinition.Type.Charset.Name != "" && other.columnDefinition.Type.Options.Collate == "" { - // Charset defined without collation. Assign the default collation for that charset. - collation := env.CollationEnv().DefaultCollationForCharset(other.columnDefinition.Type.Charset.Name) - if collation == collations.Unknown { - return nil, &UnknownColumnCharsetCollationError{Column: other.columnDefinition.Name.String(), Charset: t2cc.charset} - } - defer func() { - other.columnDefinition.Type.Options.Collate = "" - }() - other.columnDefinition.Type.Options.Collate = env.CollationEnv().LookupName(collation) - } - if other.columnDefinition.Type.Charset.Name == "" && other.columnDefinition.Type.Options.Collate != "" { - // Column has explicit collation but no charset. We can infer the charset from the collation. - collationID := env.CollationEnv().LookupByName(other.columnDefinition.Type.Options.Collate) - charset := env.CollationEnv().LookupCharsetName(collationID) - if charset == "" { - return nil, &UnknownColumnCollationCharsetError{Column: other.columnDefinition.Name.String(), Collation: other.columnDefinition.Type.Options.Collate} - } - defer func() { - other.columnDefinition.Type.Charset.Name = "" - }() - other.columnDefinition.Type.Charset.Name = charset - } - - if other.columnDefinition.Type.Charset.Name == "" { - // Still nothing? Assign the table's charset/collation. - defer func() { - other.columnDefinition.Type.Charset.Name = "" - other.columnDefinition.Type.Options.Collate = "" - }() - other.columnDefinition.Type.Charset.Name = t2cc.charset - if other.columnDefinition.Type.Options.Collate = t2cc.collate; other.columnDefinition.Type.Options.Collate == "" { - collation := env.CollationEnv().DefaultCollationForCharset(t2cc.charset) - if collation == collations.Unknown { - return nil, &UnknownColumnCharsetCollationError{Column: other.columnDefinition.Name.String(), Charset: t2cc.charset} - } - other.columnDefinition.Type.Options.Collate = env.CollationEnv().LookupName(collation) - } + otherClone = other.Clone() + if err := otherClone.SetExplicitCharsetCollate(); err != nil { + return nil, err } } - if sqlparser.Equals.RefOfColumnDefinition(c.columnDefinition, other.columnDefinition) { + if sqlparser.Equals.RefOfColumnDefinition(cClone.columnDefinition, otherClone.columnDefinition) { return nil, nil } @@ -204,11 +181,11 @@ func (c *ColumnDefinitionEntity) ColumnDiff( } switch hints.EnumReorderStrategy { case EnumReorderStrategyReject: - otherEnumValuesMap := getEnumValuesMap(other.columnDefinition.Type.EnumValues) - for ordinal, enumValue := range c.columnDefinition.Type.EnumValues { + otherEnumValuesMap := getEnumValuesMap(otherClone.columnDefinition.Type.EnumValues) + for ordinal, enumValue := range cClone.columnDefinition.Type.EnumValues { if otherOrdinal, ok := otherEnumValuesMap[enumValue]; ok { if ordinal != otherOrdinal { - return nil, &EnumValueOrdinalChangedError{Table: tableName, Column: c.columnDefinition.Name.String(), Value: enumValue, Ordinal: ordinal, NewOrdinal: otherOrdinal} + return nil, &EnumValueOrdinalChangedError{Table: tableName, Column: cClone.columnDefinition.Name.String(), Value: enumValue, Ordinal: ordinal, NewOrdinal: otherOrdinal} } } } diff --git a/go/vt/schemadiff/schema_diff.go b/go/vt/schemadiff/schema_diff.go index 60285265986..1c161ab56bf 100644 --- a/go/vt/schemadiff/schema_diff.go +++ b/go/vt/schemadiff/schema_diff.go @@ -88,28 +88,50 @@ Modified to have an early break // permutateDiffs calls `callback` with each permutation of a. If the function returns `true`, that means // the callback has returned `true` for an early break, thus possibly not all permutations have been evaluated. -func permutateDiffs(ctx context.Context, diffs []EntityDiff, hints *DiffHints, callback func([]EntityDiff, *DiffHints) (earlyBreak bool)) (earlyBreak bool, err error) { +// callback's `errorIndex` indicates the first index at which the permutation has error, or -1 if there's no such error. +// When `errorIndex` is non negative, then the algorithm skips any further recursive dives following `i`. +func permutateDiffs( + ctx context.Context, + diffs []EntityDiff, + hints *DiffHints, + callback func([]EntityDiff, *DiffHints) (earlyBreak bool, errorIndex int), +) (earlyBreak bool, err error) { if len(diffs) == 0 { return false, nil } // Sort by a heuristic (DROPs first, ALTERs next, CREATEs last). This ordering is then used first in the permutation // search and serves as seed for the rest of permutations. - return permDiff(ctx, diffs, hints, callback, 0) + earlyBreak, _, err = permDiff(ctx, diffs, hints, callback, 0) + return earlyBreak, err } // permDiff is a recursive function to permutate given `a` and call `callback` for each permutation. // If `callback` returns `true`, then so does this function, and this indicates a request for an early // break, in which case this function will not be called again. -func permDiff(ctx context.Context, a []EntityDiff, hints *DiffHints, callback func([]EntityDiff, *DiffHints) (earlyBreak bool), i int) (earlyBreak bool, err error) { +func permDiff( + ctx context.Context, + a []EntityDiff, + hints *DiffHints, + callback func([]EntityDiff, *DiffHints) (earlyBreak bool, errorIndex int), + i int, +) (earlyBreak bool, errorIndex int, err error) { if err := ctx.Err(); err != nil { - return true, err // early break + return true, -1, err // early break (due to context) } if i > len(a) { - return callback(a, hints), nil + earlyBreak, errorIndex := callback(a, hints) + return earlyBreak, errorIndex, nil } - if brk, err := permDiff(ctx, a, hints, callback, i+1); brk { - return true, err + earlyBreak, errorIndex, err = permDiff(ctx, a, hints, callback, i+1) + if errorIndex >= 0 && i > errorIndex { + // Means the current permutation failed at `errorIndex`, and we're beyond that point. There's no + // point in continuing to permutate the rest of the array. + return false, errorIndex, err + } + if earlyBreak { + // Found a valid permutation, no need to continue + return true, -1, err } for j := i + 1; j < len(a); j++ { // An optimization: we don't really need all possible permutations. We can skip some of the recursive search. @@ -150,12 +172,18 @@ func permDiff(ctx context.Context, a []EntityDiff, hints *DiffHints, callback fu } // End of optimization a[i], a[j] = a[j], a[i] - if brk, err := permDiff(ctx, a, hints, callback, i+1); brk { - return true, err + earlyBreak, errorIndex, err = permDiff(ctx, a, hints, callback, i+1) + if errorIndex >= 0 && i > errorIndex { + // Means the current permutation failed at `errorIndex`, and we're beyond that point. There's no + // point in continuing to permutate the rest of the array. + return false, errorIndex, err + } + if earlyBreak { + return true, -1, err } a[i], a[j] = a[j], a[i] } - return false, nil + return false, -1, nil } // SchemaDiff is a rich diff between two schemas. It includes the following: @@ -316,7 +344,7 @@ func (d *SchemaDiff) OrderedDiffs(ctx context.Context) ([]EntityDiff, error) { // We will now permutate the diffs in this equivalence class, and hopefully find // a valid permutation (one where if we apply the diffs in-order, the schema remains valid throughout the process) tryPermutateDiffs := func(hints *DiffHints) (bool, error) { - return permutateDiffs(ctx, classDiffs, hints, func(permutatedDiffs []EntityDiff, hints *DiffHints) bool { + return permutateDiffs(ctx, classDiffs, hints, func(permutatedDiffs []EntityDiff, hints *DiffHints) (bool, int) { permutationSchema := lastGoodSchema.copy() // We want to apply the changes one by one, and validate the schema after each change for i := range permutatedDiffs { @@ -338,14 +366,14 @@ func (d *SchemaDiff) OrderedDiffs(ctx context.Context) ([]EntityDiff, error) { } if err := permutationSchema.apply(permutatedDiffs[i:i+1], applyHints); err != nil { // permutation is invalid - return false // continue searching + return false, i // let the algorithm know there's no point in pursuing any path after `i` } } // Good news, we managed to apply all of the permutations! orderedDiffs = append(orderedDiffs, permutatedDiffs...) lastGoodSchema = permutationSchema - return true // early break! No need to keep searching + return true, -1 // early break! No need to keep searching }) } // We prefer stricter strategy, because that gives best chance of finding a valid path. diff --git a/go/vt/schemadiff/schema_diff_test.go b/go/vt/schemadiff/schema_diff_test.go index 8adc4fc8d68..10ad260100b 100644 --- a/go/vt/schemadiff/schema_diff_test.go +++ b/go/vt/schemadiff/schema_diff_test.go @@ -18,6 +18,8 @@ package schemadiff import ( "context" + "fmt" + "os" "strings" "testing" @@ -195,7 +197,7 @@ func TestPermutations(t *testing.T) { allDiffs := schemaDiff.UnorderedDiffs() originalSingleString := toSingleString(allDiffs) numEquals := 0 - earlyBreak, err := permutateDiffs(ctx, allDiffs, hints, func(pdiffs []EntityDiff, hints *DiffHints) (earlyBreak bool) { + earlyBreak, err := permutateDiffs(ctx, allDiffs, hints, func(pdiffs []EntityDiff, hints *DiffHints) (earlyBreak bool, errorIndex int) { defer func() { iteration++ }() // cover all permutations singleString := toSingleString(pdiffs) @@ -204,7 +206,7 @@ func TestPermutations(t *testing.T) { if originalSingleString == singleString { numEquals++ } - return false + return false, -1 }) assert.NoError(t, err) if len(allDiffs) > 0 { @@ -218,13 +220,13 @@ func TestPermutations(t *testing.T) { allPerms := map[string]bool{} allDiffs := schemaDiff.UnorderedDiffs() originalSingleString := toSingleString(allDiffs) - earlyBreak, err := permutateDiffs(ctx, allDiffs, hints, func(pdiffs []EntityDiff, hints *DiffHints) (earlyBreak bool) { + earlyBreak, err := permutateDiffs(ctx, allDiffs, hints, func(pdiffs []EntityDiff, hints *DiffHints) (earlyBreak bool, errorIndex int) { // Single visit allPerms[toSingleString(pdiffs)] = true // First permutation should be the same as original require.Equal(t, originalSingleString, toSingleString(pdiffs)) // early break; this callback function should not be invoked again - return true + return true, -1 }) assert.NoError(t, err) if len(allDiffs) > 0 { @@ -246,8 +248,8 @@ func TestPermutationsContext(t *testing.T) { hints := &DiffHints{RangeRotationStrategy: RangeRotationDistinctStatements} allDiffs := []EntityDiff{&DropViewEntityDiff{}} - earlyBreak, err := permutateDiffs(ctx, allDiffs, hints, func(pdiffs []EntityDiff, hints *DiffHints) (earlyBreak bool) { - return false + earlyBreak, err := permutateDiffs(ctx, allDiffs, hints, func(pdiffs []EntityDiff, hints *DiffHints) (earlyBreak bool, errorIndex int) { + return false, -1 }) assert.True(t, earlyBreak) // proves that termination was due to context cancel assert.Error(t, err) // proves that termination was due to context cancel @@ -1322,3 +1324,39 @@ func TestSchemaDiff(t *testing.T) { } } + +// TestDiffFiles diffs two schema files on the local file system. It requires the $TEST_SCHEMADIFF_DIFF_FILES +// environment variable to be set to a comma-separated list of two file paths, e.g. "/tmp/from.sql,/tmp/to.sql". +// If the variable is unspecified, the test is skipped. It is useful for ad-hoc testing of schema diffs. +func TestDiffFiles(t *testing.T) { + ctx := context.Background() + + envName := "TEST_SCHEMADIFF_DIFF_FILES" + filesVar := os.Getenv(envName) + if filesVar == "" { + t.Skipf("no diff files specified in $%s", envName) + } + files := strings.Split(filesVar, ",") + require.Len(t, files, 2, "expecting two files in $%s: ,", envName) + fromSchemaSQL, err := os.ReadFile(files[0]) + require.NoError(t, err) + toSchemaSQL, err := os.ReadFile(files[1]) + require.NoError(t, err) + + env := NewTestEnv() + fromSchema, err := NewSchemaFromSQL(env, string(fromSchemaSQL)) + require.NoError(t, err) + toSchema, err := NewSchemaFromSQL(env, string(toSchemaSQL)) + require.NoError(t, err) + + hints := &DiffHints{RangeRotationStrategy: RangeRotationDistinctStatements} + schemaDiff, err := fromSchema.SchemaDiff(toSchema, hints) + require.NoError(t, err) + t.Logf("diff length: %v", len(schemaDiff.UnorderedDiffs())) + orderedDiffs, err := schemaDiff.OrderedDiffs(ctx) + require.NoError(t, err) + t.Logf("ordered diffs length: %v", len(orderedDiffs)) + for _, diff := range orderedDiffs { + fmt.Printf("%s;\n", diff.CanonicalStatementString()) + } +} diff --git a/go/vt/schemadiff/table.go b/go/vt/schemadiff/table.go index 5d21d524704..5629210b6c1 100644 --- a/go/vt/schemadiff/table.go +++ b/go/vt/schemadiff/table.go @@ -454,6 +454,15 @@ func NewCreateTableEntity(env *Environment, c *sqlparser.CreateTable) (*CreateTa return entity, nil } +func (c *CreateTableEntity) ColumnDefinitionEntities() []*ColumnDefinitionEntity { + cc := getTableCharsetCollate(c.Env, &c.CreateTable.TableSpec.Options) + entities := make([]*ColumnDefinitionEntity, len(c.CreateTable.TableSpec.Columns)) + for i := range c.CreateTable.TableSpec.Columns { + entities[i] = NewColumnDefinitionEntity(c.Env, c.CreateTable.TableSpec.Columns[i], cc) + } + return entities +} + // normalize cleans up the table definition: // - setting names to all keys // - table option case (upper/lower/special) @@ -1731,11 +1740,11 @@ func (c *CreateTableEntity) diffColumns(alterTable *sqlparser.AlterTable, t2ColName := t2Col.Name.Lowered() // we know that column exists in both tables t1Col := t1ColumnsMap[t2ColName] - t1ColEntity := NewColumnDefinitionEntity(t1Col.col) - t2ColEntity := NewColumnDefinitionEntity(t2Col) + t1ColEntity := NewColumnDefinitionEntity(c.Env, t1Col.col, t1cc) + t2ColEntity := NewColumnDefinitionEntity(c.Env, t2Col, t2cc) // check diff between before/after columns: - modifyColumnDiff, err := t1ColEntity.ColumnDiff(c.Env, c.Name(), t2ColEntity, t1cc, t2cc, hints) + modifyColumnDiff, err := t1ColEntity.ColumnDiff(c.Env, c.Name(), t2ColEntity, hints) if err != nil { return err } diff --git a/go/vt/schemamanager/tablet_executor.go b/go/vt/schemamanager/tablet_executor.go index 0acae6459db..68270e0babc 100644 --- a/go/vt/schemamanager/tablet_executor.go +++ b/go/vt/schemamanager/tablet_executor.go @@ -248,7 +248,17 @@ func (exec *TabletExecutor) executeAlterMigrationThrottle(ctx context.Context, a if throttlerConfig.ThrottledApps == nil { throttlerConfig.ThrottledApps = make(map[string]*topodatapb.ThrottledAppRule) } - throttlerConfig.ThrottledApps[req.ThrottledApp.Name] = req.ThrottledApp + if req.ThrottledApp != nil && req.ThrottledApp.Name != "" { + // TODO(shlomi) in v22: replace the following line with the commented out block + throttlerConfig.ThrottledApps[req.ThrottledApp.Name] = req.ThrottledApp + // timeNow := time.Now() + // if protoutil.TimeFromProto(req.ThrottledApp.ExpiresAt).After(timeNow) { + // throttlerConfig.ThrottledApps[req.ThrottledApp.Name] = req.ThrottledApp + // } else { + // delete(throttlerConfig.ThrottledApps, req.ThrottledApp.Name) + // } + } + return throttlerConfig } // We have already locked the keyspace diff --git a/go/vt/servenv/run.go b/go/vt/servenv/run.go index 29b15a40008..cef81e87a99 100644 --- a/go/vt/servenv/run.go +++ b/go/vt/servenv/run.go @@ -59,7 +59,6 @@ func Run(bindAddress string, port int) { signal.Notify(ExitChan, syscall.SIGTERM, syscall.SIGINT) // Wait for signal <-ExitChan - l.Close() startTime := time.Now() log.Infof("Entering lameduck mode for at least %v", timeouts.LameduckPeriod) @@ -71,6 +70,7 @@ func Run(bindAddress string, port int) { log.Infof("Sleeping an extra %v after OnTermSync to finish lameduck period", remain) time.Sleep(remain) } + l.Close() log.Info("Shutting down gracefully") fireOnCloseHooks(timeouts.OnCloseTimeout) diff --git a/go/vt/sidecardb/schema/twopc/dt_state.sql b/go/vt/sidecardb/schema/twopc/dt_state.sql index dff9e4c3770..9247ea5fa3c 100644 --- a/go/vt/sidecardb/schema/twopc/dt_state.sql +++ b/go/vt/sidecardb/schema/twopc/dt_state.sql @@ -19,5 +19,6 @@ CREATE TABLE IF NOT EXISTS dt_state dtid varbinary(512) NOT NULL, state bigint NOT NULL, time_created bigint NOT NULL, - primary key(dtid) + primary key(dtid), + key (time_created) ) ENGINE = InnoDB diff --git a/go/vt/sqlparser/ast.go b/go/vt/sqlparser/ast.go index 76beb368943..4e5fcfcad88 100644 --- a/go/vt/sqlparser/ast.go +++ b/go/vt/sqlparser/ast.go @@ -19,6 +19,7 @@ package sqlparser import ( "vitess.io/vitess/go/mysql/datetime" "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/vt/vterrors" ) /* @@ -261,7 +262,11 @@ type ( Select struct { Cache *bool // a reference here so it can be nil Distinct bool + HighPriority bool StraightJoinHint bool + SQLSmallResult bool + SQLBigResult bool + SQLBufferResult bool SQLCalcFoundRows bool // The With field needs to come before the FROM clause, so any CTEs have been handled before we analyze it With *With @@ -1666,6 +1671,11 @@ type ( Filter *ShowFilter } + // ShowTransactionStatus is used to see the status of a distributed transaction in progress. + ShowTransactionStatus struct { + TransactionID string + } + // ShowCreate is of ShowInternal type, holds SHOW CREATE queries. ShowCreate struct { Command ShowCommandType @@ -1678,9 +1688,10 @@ type ( } ) -func (*ShowBasic) isShowInternal() {} -func (*ShowCreate) isShowInternal() {} -func (*ShowOther) isShowInternal() {} +func (*ShowBasic) isShowInternal() {} +func (*ShowCreate) isShowInternal() {} +func (*ShowOther) isShowInternal() {} +func (*ShowTransactionStatus) isShowInternal() {} // InsertRows represents the rows for an INSERT statement. type InsertRows interface { @@ -2573,6 +2584,21 @@ type ( Columns []*JtColumnDefinition } + // JSONArrayAgg is an aggregation expression that creates a JSON Array. + // For more information, visit https://dev.mysql.com/doc/refman/8.4/en/aggregate-functions.html#function_json-arrayagg + JSONArrayAgg struct { + Expr Expr + OverClause *OverClause + } + + // JSONObjectAgg is an aggregation expression that creates a JSON Object. + // For more information, visit https://dev.mysql.com/doc/refman/8.4/en/aggregate-functions.html#function_json-objectagg + JSONObjectAgg struct { + Key Expr + Value Expr + OverClause *OverClause + } + // JtOnResponseType describes the type of column: default, error or null JtOnResponseType int @@ -3225,7 +3251,9 @@ func (*JSONOverlapsExpr) IsExpr() {} func (*JSONSearchExpr) IsExpr() {} func (*JSONValueExpr) IsExpr() {} func (*JSONArrayExpr) IsExpr() {} +func (*JSONArrayAgg) IsExpr() {} func (*JSONObjectExpr) IsExpr() {} +func (*JSONObjectAgg) IsExpr() {} func (*JSONQuoteExpr) IsExpr() {} func (*JSONAttributesExpr) IsExpr() {} func (*JSONValueModifierExpr) IsExpr() {} @@ -3387,6 +3415,8 @@ func (varP *VarPop) GetArg() Expr { return varP.Arg } func (varS *VarSamp) GetArg() Expr { return varS.Arg } func (variance *Variance) GetArg() Expr { return variance.Arg } func (av *AnyValue) GetArg() Expr { return av.Arg } +func (jaa *JSONArrayAgg) GetArg() Expr { return jaa.Expr } +func (joa *JSONObjectAgg) GetArg() Expr { return joa.Key } func (sum *Sum) GetArgs() Exprs { return Exprs{sum.Arg} } func (min *Min) GetArgs() Exprs { return Exprs{min.Arg} } @@ -3406,6 +3436,8 @@ func (varP *VarPop) GetArgs() Exprs { return Exprs{varP.Arg} } func (varS *VarSamp) GetArgs() Exprs { return Exprs{varS.Arg} } func (variance *Variance) GetArgs() Exprs { return Exprs{variance.Arg} } func (av *AnyValue) GetArgs() Exprs { return Exprs{av.Arg} } +func (jaa *JSONArrayAgg) GetArgs() Exprs { return Exprs{jaa.Expr} } +func (joa *JSONObjectAgg) GetArgs() Exprs { return Exprs{joa.Key, joa.Value} } func (min *Min) SetArg(expr Expr) { min.Arg = expr } func (sum *Sum) SetArg(expr Expr) { sum.Arg = expr } @@ -3425,6 +3457,8 @@ func (varP *VarPop) SetArg(expr Expr) { varP.Arg = expr } func (varS *VarSamp) SetArg(expr Expr) { varS.Arg = expr } func (variance *Variance) SetArg(expr Expr) { variance.Arg = expr } func (av *AnyValue) SetArg(expr Expr) { av.Arg = expr } +func (jaa *JSONArrayAgg) SetArg(expr Expr) { jaa.Expr = expr } +func (joa *JSONObjectAgg) SetArg(expr Expr) { joa.Key = expr } func (min *Min) SetArgs(exprs Exprs) error { return setFuncArgs(min, exprs, "MIN") } func (sum *Sum) SetArgs(exprs Exprs) error { return setFuncArgs(sum, exprs, "SUM") } @@ -3442,6 +3476,15 @@ func (varP *VarPop) SetArgs(exprs Exprs) error { return setFuncArgs(varP, func (varS *VarSamp) SetArgs(exprs Exprs) error { return setFuncArgs(varS, exprs, "VAR_SAMP") } func (variance *Variance) SetArgs(exprs Exprs) error { return setFuncArgs(variance, exprs, "VARIANCE") } func (av *AnyValue) SetArgs(exprs Exprs) error { return setFuncArgs(av, exprs, "ANY_VALUE") } +func (jaa *JSONArrayAgg) SetArgs(exprs Exprs) error { return setFuncArgs(jaa, exprs, "JSON_ARRAYARG") } +func (joa *JSONObjectAgg) SetArgs(exprs Exprs) error { + if len(exprs) != 2 { + return vterrors.VT13001("JSONObjectAgg takes in 2 expressions") + } + joa.Key = exprs[0] + joa.Value = exprs[1] + return nil +} func (count *Count) SetArgs(exprs Exprs) error { count.Args = exprs @@ -3484,6 +3527,8 @@ func (*VarPop) AggrName() string { return "var_pop" } func (*VarSamp) AggrName() string { return "var_samp" } func (*Variance) AggrName() string { return "variance" } func (*AnyValue) AggrName() string { return "any_value" } +func (*JSONArrayAgg) AggrName() string { return "json_arrayagg" } +func (*JSONObjectAgg) AggrName() string { return "json_objectagg" } // Exprs represents a list of value expressions. // It's not a valid expression because it's not parenthesized. diff --git a/go/vt/sqlparser/ast_clone.go b/go/vt/sqlparser/ast_clone.go index ab215fdf994..7a59832b867 100644 --- a/go/vt/sqlparser/ast_clone.go +++ b/go/vt/sqlparser/ast_clone.go @@ -233,6 +233,8 @@ func CloneSQLNode(in SQLNode) SQLNode { return CloneRefOfIntroducerExpr(in) case *IsExpr: return CloneRefOfIsExpr(in) + case *JSONArrayAgg: + return CloneRefOfJSONArrayAgg(in) case *JSONArrayExpr: return CloneRefOfJSONArrayExpr(in) case *JSONAttributesExpr: @@ -245,6 +247,8 @@ func CloneSQLNode(in SQLNode) SQLNode { return CloneRefOfJSONExtractExpr(in) case *JSONKeysExpr: return CloneRefOfJSONKeysExpr(in) + case *JSONObjectAgg: + return CloneRefOfJSONObjectAgg(in) case *JSONObjectExpr: return CloneRefOfJSONObjectExpr(in) case *JSONObjectParam: @@ -457,6 +461,8 @@ func CloneSQLNode(in SQLNode) SQLNode { return CloneRefOfShowThrottledApps(in) case *ShowThrottlerStatus: return CloneRefOfShowThrottlerStatus(in) + case *ShowTransactionStatus: + return CloneRefOfShowTransactionStatus(in) case *StarExpr: return CloneRefOfStarExpr(in) case *Std: @@ -1692,6 +1698,17 @@ func CloneRefOfIsExpr(n *IsExpr) *IsExpr { return &out } +// CloneRefOfJSONArrayAgg creates a deep clone of the input. +func CloneRefOfJSONArrayAgg(n *JSONArrayAgg) *JSONArrayAgg { + if n == nil { + return nil + } + out := *n + out.Expr = CloneExpr(n.Expr) + out.OverClause = CloneRefOfOverClause(n.OverClause) + return &out +} + // CloneRefOfJSONArrayExpr creates a deep clone of the input. func CloneRefOfJSONArrayExpr(n *JSONArrayExpr) *JSONArrayExpr { if n == nil { @@ -1759,6 +1776,18 @@ func CloneRefOfJSONKeysExpr(n *JSONKeysExpr) *JSONKeysExpr { return &out } +// CloneRefOfJSONObjectAgg creates a deep clone of the input. +func CloneRefOfJSONObjectAgg(n *JSONObjectAgg) *JSONObjectAgg { + if n == nil { + return nil + } + out := *n + out.Key = CloneExpr(n.Key) + out.Value = CloneExpr(n.Value) + out.OverClause = CloneRefOfOverClause(n.OverClause) + return &out +} + // CloneRefOfJSONObjectExpr creates a deep clone of the input. func CloneRefOfJSONObjectExpr(n *JSONObjectExpr) *JSONObjectExpr { if n == nil { @@ -2882,6 +2911,15 @@ func CloneRefOfShowThrottlerStatus(n *ShowThrottlerStatus) *ShowThrottlerStatus return &out } +// CloneRefOfShowTransactionStatus creates a deep clone of the input. +func CloneRefOfShowTransactionStatus(n *ShowTransactionStatus) *ShowTransactionStatus { + if n == nil { + return nil + } + out := *n + return &out +} + // CloneRefOfStarExpr creates a deep clone of the input. func CloneRefOfStarExpr(n *StarExpr) *StarExpr { if n == nil { @@ -3460,6 +3498,10 @@ func CloneAggrFunc(in AggrFunc) AggrFunc { return CloneRefOfCountStar(in) case *GroupConcatExpr: return CloneRefOfGroupConcatExpr(in) + case *JSONArrayAgg: + return CloneRefOfJSONArrayAgg(in) + case *JSONObjectAgg: + return CloneRefOfJSONObjectAgg(in) case *Max: return CloneRefOfMax(in) case *Min: @@ -3904,6 +3946,8 @@ func CloneExpr(in Expr) Expr { return CloneRefOfIntroducerExpr(in) case *IsExpr: return CloneRefOfIsExpr(in) + case *JSONArrayAgg: + return CloneRefOfJSONArrayAgg(in) case *JSONArrayExpr: return CloneRefOfJSONArrayExpr(in) case *JSONAttributesExpr: @@ -3916,6 +3960,8 @@ func CloneExpr(in Expr) Expr { return CloneRefOfJSONExtractExpr(in) case *JSONKeysExpr: return CloneRefOfJSONKeysExpr(in) + case *JSONObjectAgg: + return CloneRefOfJSONObjectAgg(in) case *JSONObjectExpr: return CloneRefOfJSONObjectExpr(in) case *JSONOverlapsExpr: @@ -4112,6 +4158,8 @@ func CloneShowInternal(in ShowInternal) ShowInternal { return CloneRefOfShowCreate(in) case *ShowOther: return CloneRefOfShowOther(in) + case *ShowTransactionStatus: + return CloneRefOfShowTransactionStatus(in) default: // this should never happen return nil diff --git a/go/vt/sqlparser/ast_copy_on_rewrite.go b/go/vt/sqlparser/ast_copy_on_rewrite.go index 68eea685405..caa00181f9e 100644 --- a/go/vt/sqlparser/ast_copy_on_rewrite.go +++ b/go/vt/sqlparser/ast_copy_on_rewrite.go @@ -232,6 +232,8 @@ func (c *cow) copyOnRewriteSQLNode(n SQLNode, parent SQLNode) (out SQLNode, chan return c.copyOnRewriteRefOfIntroducerExpr(n, parent) case *IsExpr: return c.copyOnRewriteRefOfIsExpr(n, parent) + case *JSONArrayAgg: + return c.copyOnRewriteRefOfJSONArrayAgg(n, parent) case *JSONArrayExpr: return c.copyOnRewriteRefOfJSONArrayExpr(n, parent) case *JSONAttributesExpr: @@ -244,6 +246,8 @@ func (c *cow) copyOnRewriteSQLNode(n SQLNode, parent SQLNode) (out SQLNode, chan return c.copyOnRewriteRefOfJSONExtractExpr(n, parent) case *JSONKeysExpr: return c.copyOnRewriteRefOfJSONKeysExpr(n, parent) + case *JSONObjectAgg: + return c.copyOnRewriteRefOfJSONObjectAgg(n, parent) case *JSONObjectExpr: return c.copyOnRewriteRefOfJSONObjectExpr(n, parent) case *JSONObjectParam: @@ -456,6 +460,8 @@ func (c *cow) copyOnRewriteSQLNode(n SQLNode, parent SQLNode) (out SQLNode, chan return c.copyOnRewriteRefOfShowThrottledApps(n, parent) case *ShowThrottlerStatus: return c.copyOnRewriteRefOfShowThrottlerStatus(n, parent) + case *ShowTransactionStatus: + return c.copyOnRewriteRefOfShowTransactionStatus(n, parent) case *StarExpr: return c.copyOnRewriteRefOfStarExpr(n, parent) case *Std: @@ -2966,6 +2972,30 @@ func (c *cow) copyOnRewriteRefOfIsExpr(n *IsExpr, parent SQLNode) (out SQLNode, } return } +func (c *cow) copyOnRewriteRefOfJSONArrayAgg(n *JSONArrayAgg, parent SQLNode) (out SQLNode, changed bool) { + if n == nil || c.cursor.stop { + return n, false + } + out = n + if c.pre == nil || c.pre(n, parent) { + _Expr, changedExpr := c.copyOnRewriteExpr(n.Expr, n) + _OverClause, changedOverClause := c.copyOnRewriteRefOfOverClause(n.OverClause, n) + if changedExpr || changedOverClause { + res := *n + res.Expr, _ = _Expr.(Expr) + res.OverClause, _ = _OverClause.(*OverClause) + out = &res + if c.cloned != nil { + c.cloned(n, out) + } + changed = true + } + } + if c.post != nil { + out, changed = c.postVisit(out, parent, changed) + } + return +} func (c *cow) copyOnRewriteRefOfJSONArrayExpr(n *JSONArrayExpr, parent SQLNode) (out SQLNode, changed bool) { if n == nil || c.cursor.stop { return n, false @@ -3136,6 +3166,32 @@ func (c *cow) copyOnRewriteRefOfJSONKeysExpr(n *JSONKeysExpr, parent SQLNode) (o } return } +func (c *cow) copyOnRewriteRefOfJSONObjectAgg(n *JSONObjectAgg, parent SQLNode) (out SQLNode, changed bool) { + if n == nil || c.cursor.stop { + return n, false + } + out = n + if c.pre == nil || c.pre(n, parent) { + _Key, changedKey := c.copyOnRewriteExpr(n.Key, n) + _Value, changedValue := c.copyOnRewriteExpr(n.Value, n) + _OverClause, changedOverClause := c.copyOnRewriteRefOfOverClause(n.OverClause, n) + if changedKey || changedValue || changedOverClause { + res := *n + res.Key, _ = _Key.(Expr) + res.Value, _ = _Value.(Expr) + res.OverClause, _ = _OverClause.(*OverClause) + out = &res + if c.cloned != nil { + c.cloned(n, out) + } + changed = true + } + } + if c.post != nil { + out, changed = c.postVisit(out, parent, changed) + } + return +} func (c *cow) copyOnRewriteRefOfJSONObjectExpr(n *JSONObjectExpr, parent SQLNode) (out SQLNode, changed bool) { if n == nil || c.cursor.stop { return n, false @@ -5471,6 +5527,18 @@ func (c *cow) copyOnRewriteRefOfShowThrottlerStatus(n *ShowThrottlerStatus, pare } return } +func (c *cow) copyOnRewriteRefOfShowTransactionStatus(n *ShowTransactionStatus, parent SQLNode) (out SQLNode, changed bool) { + if n == nil || c.cursor.stop { + return n, false + } + out = n + if c.pre == nil || c.pre(n, parent) { + } + if c.post != nil { + out, changed = c.postVisit(out, parent, changed) + } + return +} func (c *cow) copyOnRewriteRefOfStarExpr(n *StarExpr, parent SQLNode) (out SQLNode, changed bool) { if n == nil || c.cursor.stop { return n, false @@ -6706,6 +6774,10 @@ func (c *cow) copyOnRewriteAggrFunc(n AggrFunc, parent SQLNode) (out SQLNode, ch return c.copyOnRewriteRefOfCountStar(n, parent) case *GroupConcatExpr: return c.copyOnRewriteRefOfGroupConcatExpr(n, parent) + case *JSONArrayAgg: + return c.copyOnRewriteRefOfJSONArrayAgg(n, parent) + case *JSONObjectAgg: + return c.copyOnRewriteRefOfJSONObjectAgg(n, parent) case *Max: return c.copyOnRewriteRefOfMax(n, parent) case *Min: @@ -7134,6 +7206,8 @@ func (c *cow) copyOnRewriteExpr(n Expr, parent SQLNode) (out SQLNode, changed bo return c.copyOnRewriteRefOfIntroducerExpr(n, parent) case *IsExpr: return c.copyOnRewriteRefOfIsExpr(n, parent) + case *JSONArrayAgg: + return c.copyOnRewriteRefOfJSONArrayAgg(n, parent) case *JSONArrayExpr: return c.copyOnRewriteRefOfJSONArrayExpr(n, parent) case *JSONAttributesExpr: @@ -7146,6 +7220,8 @@ func (c *cow) copyOnRewriteExpr(n Expr, parent SQLNode) (out SQLNode, changed bo return c.copyOnRewriteRefOfJSONExtractExpr(n, parent) case *JSONKeysExpr: return c.copyOnRewriteRefOfJSONKeysExpr(n, parent) + case *JSONObjectAgg: + return c.copyOnRewriteRefOfJSONObjectAgg(n, parent) case *JSONObjectExpr: return c.copyOnRewriteRefOfJSONObjectExpr(n, parent) case *JSONOverlapsExpr: @@ -7334,6 +7410,8 @@ func (c *cow) copyOnRewriteShowInternal(n ShowInternal, parent SQLNode) (out SQL return c.copyOnRewriteRefOfShowCreate(n, parent) case *ShowOther: return c.copyOnRewriteRefOfShowOther(n, parent) + case *ShowTransactionStatus: + return c.copyOnRewriteRefOfShowTransactionStatus(n, parent) default: // this should never happen return nil, false diff --git a/go/vt/sqlparser/ast_equals.go b/go/vt/sqlparser/ast_equals.go index a775cb7f8bf..f098b4e19d4 100644 --- a/go/vt/sqlparser/ast_equals.go +++ b/go/vt/sqlparser/ast_equals.go @@ -656,6 +656,12 @@ func (cmp *Comparator) SQLNode(inA, inB SQLNode) bool { return false } return cmp.RefOfIsExpr(a, b) + case *JSONArrayAgg: + b, ok := inB.(*JSONArrayAgg) + if !ok { + return false + } + return cmp.RefOfJSONArrayAgg(a, b) case *JSONArrayExpr: b, ok := inB.(*JSONArrayExpr) if !ok { @@ -692,6 +698,12 @@ func (cmp *Comparator) SQLNode(inA, inB SQLNode) bool { return false } return cmp.RefOfJSONKeysExpr(a, b) + case *JSONObjectAgg: + b, ok := inB.(*JSONObjectAgg) + if !ok { + return false + } + return cmp.RefOfJSONObjectAgg(a, b) case *JSONObjectExpr: b, ok := inB.(*JSONObjectExpr) if !ok { @@ -1328,6 +1340,12 @@ func (cmp *Comparator) SQLNode(inA, inB SQLNode) bool { return false } return cmp.RefOfShowThrottlerStatus(a, b) + case *ShowTransactionStatus: + b, ok := inB.(*ShowTransactionStatus) + if !ok { + return false + } + return cmp.RefOfShowTransactionStatus(a, b) case *StarExpr: b, ok := inB.(*StarExpr) if !ok { @@ -2966,6 +2984,18 @@ func (cmp *Comparator) RefOfIsExpr(a, b *IsExpr) bool { a.Right == b.Right } +// RefOfJSONArrayAgg does deep equals between the two objects. +func (cmp *Comparator) RefOfJSONArrayAgg(a, b *JSONArrayAgg) bool { + if a == b { + return true + } + if a == nil || b == nil { + return false + } + return cmp.Expr(a.Expr, b.Expr) && + cmp.RefOfOverClause(a.OverClause, b.OverClause) +} + // RefOfJSONArrayExpr does deep equals between the two objects. func (cmp *Comparator) RefOfJSONArrayExpr(a, b *JSONArrayExpr) bool { if a == b { @@ -3040,6 +3070,19 @@ func (cmp *Comparator) RefOfJSONKeysExpr(a, b *JSONKeysExpr) bool { cmp.Expr(a.Path, b.Path) } +// RefOfJSONObjectAgg does deep equals between the two objects. +func (cmp *Comparator) RefOfJSONObjectAgg(a, b *JSONObjectAgg) bool { + if a == b { + return true + } + if a == nil || b == nil { + return false + } + return cmp.Expr(a.Key, b.Key) && + cmp.Expr(a.Value, b.Value) && + cmp.RefOfOverClause(a.OverClause, b.OverClause) +} + // RefOfJSONObjectExpr does deep equals between the two objects. func (cmp *Comparator) RefOfJSONObjectExpr(a, b *JSONObjectExpr) bool { if a == b { @@ -4147,7 +4190,11 @@ func (cmp *Comparator) RefOfSelect(a, b *Select) bool { return false } return a.Distinct == b.Distinct && + a.HighPriority == b.HighPriority && a.StraightJoinHint == b.StraightJoinHint && + a.SQLSmallResult == b.SQLSmallResult && + a.SQLBigResult == b.SQLBigResult && + a.SQLBufferResult == b.SQLBufferResult && a.SQLCalcFoundRows == b.SQLCalcFoundRows && cmp.RefOfBool(a.Cache, b.Cache) && cmp.RefOfWith(a.With, b.With) && @@ -4326,6 +4373,17 @@ func (cmp *Comparator) RefOfShowThrottlerStatus(a, b *ShowThrottlerStatus) bool return cmp.Comments(a.Comments, b.Comments) } +// RefOfShowTransactionStatus does deep equals between the two objects. +func (cmp *Comparator) RefOfShowTransactionStatus(a, b *ShowTransactionStatus) bool { + if a == b { + return true + } + if a == nil || b == nil { + return false + } + return a.TransactionID == b.TransactionID +} + // RefOfStarExpr does deep equals between the two objects. func (cmp *Comparator) RefOfStarExpr(a, b *StarExpr) bool { if a == b { @@ -5009,6 +5067,18 @@ func (cmp *Comparator) AggrFunc(inA, inB AggrFunc) bool { return false } return cmp.RefOfGroupConcatExpr(a, b) + case *JSONArrayAgg: + b, ok := inB.(*JSONArrayAgg) + if !ok { + return false + } + return cmp.RefOfJSONArrayAgg(a, b) + case *JSONObjectAgg: + b, ok := inB.(*JSONObjectAgg) + if !ok { + return false + } + return cmp.RefOfJSONObjectAgg(a, b) case *Max: b, ok := inB.(*Max) if !ok { @@ -6173,6 +6243,12 @@ func (cmp *Comparator) Expr(inA, inB Expr) bool { return false } return cmp.RefOfIsExpr(a, b) + case *JSONArrayAgg: + b, ok := inB.(*JSONArrayAgg) + if !ok { + return false + } + return cmp.RefOfJSONArrayAgg(a, b) case *JSONArrayExpr: b, ok := inB.(*JSONArrayExpr) if !ok { @@ -6209,6 +6285,12 @@ func (cmp *Comparator) Expr(inA, inB Expr) bool { return false } return cmp.RefOfJSONKeysExpr(a, b) + case *JSONObjectAgg: + b, ok := inB.(*JSONObjectAgg) + if !ok { + return false + } + return cmp.RefOfJSONObjectAgg(a, b) case *JSONObjectExpr: b, ok := inB.(*JSONObjectExpr) if !ok { @@ -6713,6 +6795,12 @@ func (cmp *Comparator) ShowInternal(inA, inB ShowInternal) bool { return false } return cmp.RefOfShowOther(a, b) + case *ShowTransactionStatus: + b, ok := inB.(*ShowTransactionStatus) + if !ok { + return false + } + return cmp.RefOfShowTransactionStatus(a, b) default: // this should never happen return false diff --git a/go/vt/sqlparser/ast_format.go b/go/vt/sqlparser/ast_format.go index 8d8a01a6eb2..f92dc89ab50 100644 --- a/go/vt/sqlparser/ast_format.go +++ b/go/vt/sqlparser/ast_format.go @@ -37,9 +37,21 @@ func (node *Select) Format(buf *TrackedBuffer) { buf.literal(SQLNoCacheStr) } } + if node.HighPriority { + buf.literal(HighPriorityStr) + } if node.StraightJoinHint { buf.literal(StraightJoinHint) } + if node.SQLSmallResult { + buf.literal(SQLSmallResultStr) + } + if node.SQLBigResult { + buf.literal(SQLBigResultStr) + } + if node.SQLBufferResult { + buf.literal(SQLBufferResultStr) + } if node.SQLCalcFoundRows { buf.literal(SQLCalcFoundRowsStr) } @@ -284,6 +296,8 @@ func (node *AlterMigration) Format(buf *TrackedBuffer) { alterType = "retry" case CleanupMigrationType: alterType = "cleanup" + case CleanupAllMigrationType: + alterType = "cleanup all" case LaunchMigrationType: alterType = "launch" case LaunchAllMigrationType: @@ -839,7 +853,9 @@ func (idx *IndexDefinition) Format(buf *TrackedBuffer) { buf.astPrintf(idx, ")") for _, opt := range idx.Options { - buf.astPrintf(idx, " %s", opt.Name) + if opt.Name != "" { + buf.astPrintf(idx, " %s", opt.Name) + } if opt.String != "" { buf.astPrintf(idx, " %#s", opt.String) } else if opt.Value != nil { @@ -1359,6 +1375,64 @@ func (node *Literal) Format(buf *TrackedBuffer) { // Format formats the node. func (node *Argument) Format(buf *TrackedBuffer) { + // We need to make sure that any value used still returns + // the right type when interpolated. For example, if we have a + // decimal type with 0 scale, we don't want it to be interpreted + // as an integer after interpolation as that would the default + // literal interpretation in MySQL. + switch { + case node.Type == sqltypes.Unknown: + // Ensure we handle unknown first as we don't want to treat + // the type as a bitmask for the further tests. + // do nothing, the default literal will be correct. + case sqltypes.IsDecimal(node.Type) && node.Scale == 0: + buf.WriteString("CAST(") + buf.WriteArg(":", node.Name) + buf.astPrintf(node, " AS DECIMAL(%d, %d))", node.Size, node.Scale) + return + case sqltypes.IsUnsigned(node.Type): + buf.WriteString("CAST(") + buf.WriteArg(":", node.Name) + buf.WriteString(" AS UNSIGNED)") + return + case node.Type == sqltypes.Float64: + buf.WriteString("CAST(") + buf.WriteArg(":", node.Name) + buf.WriteString(" AS DOUBLE)") + return + case node.Type == sqltypes.Float32: + buf.WriteString("CAST(") + buf.WriteArg(":", node.Name) + buf.WriteString(" AS FLOAT)") + return + case node.Type == sqltypes.Timestamp, node.Type == sqltypes.Datetime: + buf.WriteString("CAST(") + buf.WriteArg(":", node.Name) + buf.WriteString(" AS DATETIME") + if node.Size == 0 { + buf.WriteString(")") + return + } + buf.astPrintf(node, "(%d))", node.Size) + return + case sqltypes.IsDate(node.Type): + buf.WriteString("CAST(") + buf.WriteArg(":", node.Name) + buf.WriteString(" AS DATE") + buf.WriteString(")") + return + case node.Type == sqltypes.Time: + buf.WriteString("CAST(") + buf.WriteArg(":", node.Name) + buf.WriteString(" AS TIME") + if node.Size == 0 { + buf.WriteString(")") + return + } + buf.astPrintf(node, "(%d))", node.Size) + return + } + // Nothing special to do, the default literal will be correct. buf.WriteArg(":", node.Name) if node.Type >= 0 { // For bind variables that are statically typed, emit their type as an adjacent comment. @@ -2077,6 +2151,10 @@ func (node *ShowBasic) Format(buf *TrackedBuffer) { buf.astPrintf(node, "%v", node.Filter) } +func (node *ShowTransactionStatus) Format(buf *TrackedBuffer) { + buf.astPrintf(node, "show transaction status for '%#s'", node.TransactionID) +} + // Format formats the node. func (node *ShowCreate) Format(buf *TrackedBuffer) { buf.astPrintf(node, "show%s %v", node.Command.ToString(), node.Op) @@ -2564,6 +2642,22 @@ func (node *JSONArrayExpr) Format(buf *TrackedBuffer) { buf.WriteByte(')') } +// Format formats the node. +func (node *JSONArrayAgg) Format(buf *TrackedBuffer) { + buf.astPrintf(node, "json_arrayagg(%v)", node.Expr) + if node.OverClause != nil { + buf.astPrintf(node, " %v", node.OverClause) + } +} + +// Format formats the node. +func (node *JSONObjectAgg) Format(buf *TrackedBuffer) { + buf.astPrintf(node, "json_objectagg(%v, %v)", node.Key, node.Value) + if node.OverClause != nil { + buf.astPrintf(node, " %v", node.OverClause) + } +} + // Format formats the node. func (node *JSONObjectExpr) Format(buf *TrackedBuffer) { buf.literal("json_object(") diff --git a/go/vt/sqlparser/ast_format_fast.go b/go/vt/sqlparser/ast_format_fast.go index 4be0bfd75f7..5d5dbb2fd74 100644 --- a/go/vt/sqlparser/ast_format_fast.go +++ b/go/vt/sqlparser/ast_format_fast.go @@ -41,9 +41,21 @@ func (node *Select) FormatFast(buf *TrackedBuffer) { buf.WriteString(SQLNoCacheStr) } } + if node.HighPriority { + buf.WriteString(HighPriorityStr) + } if node.StraightJoinHint { buf.WriteString(StraightJoinHint) } + if node.SQLSmallResult { + buf.WriteString(SQLSmallResultStr) + } + if node.SQLBigResult { + buf.WriteString(SQLBigResultStr) + } + if node.SQLBufferResult { + buf.WriteString(SQLBufferResultStr) + } if node.SQLCalcFoundRows { buf.WriteString(SQLCalcFoundRowsStr) } @@ -410,6 +422,8 @@ func (node *AlterMigration) FormatFast(buf *TrackedBuffer) { alterType = "retry" case CleanupMigrationType: alterType = "cleanup" + case CleanupAllMigrationType: + alterType = "cleanup all" case LaunchMigrationType: alterType = "launch" case LaunchAllMigrationType: @@ -1132,8 +1146,10 @@ func (idx *IndexDefinition) FormatFast(buf *TrackedBuffer) { buf.WriteByte(')') for _, opt := range idx.Options { - buf.WriteByte(' ') - buf.WriteString(opt.Name) + if opt.Name != "" { + buf.WriteByte(' ') + buf.WriteString(opt.Name) + } if opt.String != "" { buf.WriteByte(' ') buf.WriteString(opt.String) @@ -1778,6 +1794,72 @@ func (node *Literal) FormatFast(buf *TrackedBuffer) { // FormatFast formats the node. func (node *Argument) FormatFast(buf *TrackedBuffer) { + // We need to make sure that any value used still returns + // the right type when interpolated. For example, if we have a + // decimal type with 0 scale, we don't want it to be interpreted + // as an integer after interpolation as that would the default + // literal interpretation in MySQL. + switch { + case node.Type == sqltypes.Unknown: + // Ensure we handle unknown first as we don't want to treat + // the type as a bitmask for the further tests. + // do nothing, the default literal will be correct. + case sqltypes.IsDecimal(node.Type) && node.Scale == 0: + buf.WriteString("CAST(") + buf.WriteArg(":", node.Name) + buf.WriteString(" AS DECIMAL(") + buf.WriteString(fmt.Sprintf("%d", node.Size)) + buf.WriteString(", ") + buf.WriteString(fmt.Sprintf("%d", node.Scale)) + buf.WriteString("))") + return + case sqltypes.IsUnsigned(node.Type): + buf.WriteString("CAST(") + buf.WriteArg(":", node.Name) + buf.WriteString(" AS UNSIGNED)") + return + case node.Type == sqltypes.Float64: + buf.WriteString("CAST(") + buf.WriteArg(":", node.Name) + buf.WriteString(" AS DOUBLE)") + return + case node.Type == sqltypes.Float32: + buf.WriteString("CAST(") + buf.WriteArg(":", node.Name) + buf.WriteString(" AS FLOAT)") + return + case node.Type == sqltypes.Timestamp, node.Type == sqltypes.Datetime: + buf.WriteString("CAST(") + buf.WriteArg(":", node.Name) + buf.WriteString(" AS DATETIME") + if node.Size == 0 { + buf.WriteString(")") + return + } + buf.WriteByte('(') + buf.WriteString(fmt.Sprintf("%d", node.Size)) + buf.WriteString("))") + return + case sqltypes.IsDate(node.Type): + buf.WriteString("CAST(") + buf.WriteArg(":", node.Name) + buf.WriteString(" AS DATE") + buf.WriteString(")") + return + case node.Type == sqltypes.Time: + buf.WriteString("CAST(") + buf.WriteArg(":", node.Name) + buf.WriteString(" AS TIME") + if node.Size == 0 { + buf.WriteString(")") + return + } + buf.WriteByte('(') + buf.WriteString(fmt.Sprintf("%d", node.Size)) + buf.WriteString("))") + return + } + // Nothing special to do, the default literal will be correct. buf.WriteArg(":", node.Name) if node.Type >= 0 { // For bind variables that are statically typed, emit their type as an adjacent comment. @@ -2749,6 +2831,12 @@ func (node *ShowBasic) FormatFast(buf *TrackedBuffer) { node.Filter.FormatFast(buf) } +func (node *ShowTransactionStatus) FormatFast(buf *TrackedBuffer) { + buf.WriteString("show transaction status for '") + buf.WriteString(node.TransactionID) + buf.WriteByte('\'') +} + // FormatFast formats the node. func (node *ShowCreate) FormatFast(buf *TrackedBuffer) { buf.WriteString("show") @@ -3379,6 +3467,30 @@ func (node *JSONArrayExpr) FormatFast(buf *TrackedBuffer) { buf.WriteByte(')') } +// FormatFast formats the node. +func (node *JSONArrayAgg) FormatFast(buf *TrackedBuffer) { + buf.WriteString("json_arrayagg(") + buf.printExpr(node, node.Expr, true) + buf.WriteByte(')') + if node.OverClause != nil { + buf.WriteByte(' ') + node.OverClause.FormatFast(buf) + } +} + +// FormatFast formats the node. +func (node *JSONObjectAgg) FormatFast(buf *TrackedBuffer) { + buf.WriteString("json_objectagg(") + buf.printExpr(node, node.Key, true) + buf.WriteString(", ") + buf.printExpr(node, node.Value, true) + buf.WriteByte(')') + if node.OverClause != nil { + buf.WriteByte(' ') + node.OverClause.FormatFast(buf) + } +} + // FormatFast formats the node. func (node *JSONObjectExpr) FormatFast(buf *TrackedBuffer) { buf.WriteString("json_object(") diff --git a/go/vt/sqlparser/ast_funcs.go b/go/vt/sqlparser/ast_funcs.go index f4f1e3a5455..cd4d5304047 100644 --- a/go/vt/sqlparser/ast_funcs.go +++ b/go/vt/sqlparser/ast_funcs.go @@ -293,6 +293,8 @@ func SQLTypeToQueryType(typeName string, unsigned bool) querypb.Type { return sqltypes.Set case JSON: return sqltypes.TypeJSON + case VECTOR: + return sqltypes.Vector case GEOMETRY: return sqltypes.Geometry case POINT: @@ -800,7 +802,7 @@ func NewSelect( windows NamedWindows, ) *Select { var cache *bool - var distinct, straightJoinHint, sqlFoundRows bool + var distinct, highPriority, straightJoinHint, sqlSmallResult, sqlBigResult, SQLBufferResult, sqlFoundRows bool for _, option := range selectOptions { switch strings.ToLower(option) { case DistinctStr: @@ -811,8 +813,16 @@ func NewSelect( case SQLNoCacheStr: truth := false cache = &truth + case HighPriorityStr: + highPriority = true case StraightJoinHint: straightJoinHint = true + case SQLSmallResultStr: + sqlSmallResult = true + case SQLBigResultStr: + sqlBigResult = true + case SQLBufferResultStr: + SQLBufferResult = true case SQLCalcFoundRowsStr: sqlFoundRows = true } @@ -821,7 +831,11 @@ func NewSelect( Cache: cache, Comments: comments.Parsed(), Distinct: distinct, + HighPriority: highPriority, StraightJoinHint: straightJoinHint, + SQLSmallResult: sqlSmallResult, + SQLBigResult: sqlBigResult, + SQLBufferResult: SQLBufferResult, SQLCalcFoundRows: sqlFoundRows, SelectExprs: exprs, Into: into, diff --git a/go/vt/sqlparser/ast_rewrite.go b/go/vt/sqlparser/ast_rewrite.go index 8f0926951f3..0cad7237455 100644 --- a/go/vt/sqlparser/ast_rewrite.go +++ b/go/vt/sqlparser/ast_rewrite.go @@ -232,6 +232,8 @@ func (a *application) rewriteSQLNode(parent SQLNode, node SQLNode, replacer repl return a.rewriteRefOfIntroducerExpr(parent, node, replacer) case *IsExpr: return a.rewriteRefOfIsExpr(parent, node, replacer) + case *JSONArrayAgg: + return a.rewriteRefOfJSONArrayAgg(parent, node, replacer) case *JSONArrayExpr: return a.rewriteRefOfJSONArrayExpr(parent, node, replacer) case *JSONAttributesExpr: @@ -244,6 +246,8 @@ func (a *application) rewriteSQLNode(parent SQLNode, node SQLNode, replacer repl return a.rewriteRefOfJSONExtractExpr(parent, node, replacer) case *JSONKeysExpr: return a.rewriteRefOfJSONKeysExpr(parent, node, replacer) + case *JSONObjectAgg: + return a.rewriteRefOfJSONObjectAgg(parent, node, replacer) case *JSONObjectExpr: return a.rewriteRefOfJSONObjectExpr(parent, node, replacer) case *JSONObjectParam: @@ -456,6 +460,8 @@ func (a *application) rewriteSQLNode(parent SQLNode, node SQLNode, replacer repl return a.rewriteRefOfShowThrottledApps(parent, node, replacer) case *ShowThrottlerStatus: return a.rewriteRefOfShowThrottlerStatus(parent, node, replacer) + case *ShowTransactionStatus: + return a.rewriteRefOfShowTransactionStatus(parent, node, replacer) case *StarExpr: return a.rewriteRefOfStarExpr(parent, node, replacer) case *Std: @@ -4104,6 +4110,43 @@ func (a *application) rewriteRefOfIsExpr(parent SQLNode, node *IsExpr, replacer } return true } +func (a *application) rewriteRefOfJSONArrayAgg(parent SQLNode, node *JSONArrayAgg, replacer replacerFunc) bool { + if node == nil { + return true + } + if a.pre != nil { + a.cur.replacer = replacer + a.cur.parent = parent + a.cur.node = node + kontinue := !a.pre(&a.cur) + if a.cur.revisit { + a.cur.revisit = false + return a.rewriteExpr(parent, a.cur.node.(Expr), replacer) + } + if kontinue { + return true + } + } + if !a.rewriteExpr(node, node.Expr, func(newNode, parent SQLNode) { + parent.(*JSONArrayAgg).Expr = newNode.(Expr) + }) { + return false + } + if !a.rewriteRefOfOverClause(node, node.OverClause, func(newNode, parent SQLNode) { + parent.(*JSONArrayAgg).OverClause = newNode.(*OverClause) + }) { + return false + } + if a.post != nil { + a.cur.replacer = replacer + a.cur.parent = parent + a.cur.node = node + if !a.post(&a.cur) { + return false + } + } + return true +} func (a *application) rewriteRefOfJSONArrayExpr(parent SQLNode, node *JSONArrayExpr, replacer replacerFunc) bool { if node == nil { return true @@ -4343,6 +4386,48 @@ func (a *application) rewriteRefOfJSONKeysExpr(parent SQLNode, node *JSONKeysExp } return true } +func (a *application) rewriteRefOfJSONObjectAgg(parent SQLNode, node *JSONObjectAgg, replacer replacerFunc) bool { + if node == nil { + return true + } + if a.pre != nil { + a.cur.replacer = replacer + a.cur.parent = parent + a.cur.node = node + kontinue := !a.pre(&a.cur) + if a.cur.revisit { + a.cur.revisit = false + return a.rewriteExpr(parent, a.cur.node.(Expr), replacer) + } + if kontinue { + return true + } + } + if !a.rewriteExpr(node, node.Key, func(newNode, parent SQLNode) { + parent.(*JSONObjectAgg).Key = newNode.(Expr) + }) { + return false + } + if !a.rewriteExpr(node, node.Value, func(newNode, parent SQLNode) { + parent.(*JSONObjectAgg).Value = newNode.(Expr) + }) { + return false + } + if !a.rewriteRefOfOverClause(node, node.OverClause, func(newNode, parent SQLNode) { + parent.(*JSONObjectAgg).OverClause = newNode.(*OverClause) + }) { + return false + } + if a.post != nil { + a.cur.replacer = replacer + a.cur.parent = parent + a.cur.node = node + if !a.post(&a.cur) { + return false + } + } + return true +} func (a *application) rewriteRefOfJSONObjectExpr(parent SQLNode, node *JSONObjectExpr, replacer replacerFunc) bool { if node == nil { return true @@ -7851,6 +7936,30 @@ func (a *application) rewriteRefOfShowThrottlerStatus(parent SQLNode, node *Show } return true } +func (a *application) rewriteRefOfShowTransactionStatus(parent SQLNode, node *ShowTransactionStatus, replacer replacerFunc) bool { + if node == nil { + return true + } + if a.pre != nil { + a.cur.replacer = replacer + a.cur.parent = parent + a.cur.node = node + if !a.pre(&a.cur) { + return true + } + } + if a.post != nil { + if a.pre == nil { + a.cur.replacer = replacer + a.cur.parent = parent + a.cur.node = node + } + if !a.post(&a.cur) { + return false + } + } + return true +} func (a *application) rewriteRefOfStarExpr(parent SQLNode, node *StarExpr, replacer replacerFunc) bool { if node == nil { return true @@ -9654,6 +9763,10 @@ func (a *application) rewriteAggrFunc(parent SQLNode, node AggrFunc, replacer re return a.rewriteRefOfCountStar(parent, node, replacer) case *GroupConcatExpr: return a.rewriteRefOfGroupConcatExpr(parent, node, replacer) + case *JSONArrayAgg: + return a.rewriteRefOfJSONArrayAgg(parent, node, replacer) + case *JSONObjectAgg: + return a.rewriteRefOfJSONObjectAgg(parent, node, replacer) case *Max: return a.rewriteRefOfMax(parent, node, replacer) case *Min: @@ -10082,6 +10195,8 @@ func (a *application) rewriteExpr(parent SQLNode, node Expr, replacer replacerFu return a.rewriteRefOfIntroducerExpr(parent, node, replacer) case *IsExpr: return a.rewriteRefOfIsExpr(parent, node, replacer) + case *JSONArrayAgg: + return a.rewriteRefOfJSONArrayAgg(parent, node, replacer) case *JSONArrayExpr: return a.rewriteRefOfJSONArrayExpr(parent, node, replacer) case *JSONAttributesExpr: @@ -10094,6 +10209,8 @@ func (a *application) rewriteExpr(parent SQLNode, node Expr, replacer replacerFu return a.rewriteRefOfJSONExtractExpr(parent, node, replacer) case *JSONKeysExpr: return a.rewriteRefOfJSONKeysExpr(parent, node, replacer) + case *JSONObjectAgg: + return a.rewriteRefOfJSONObjectAgg(parent, node, replacer) case *JSONObjectExpr: return a.rewriteRefOfJSONObjectExpr(parent, node, replacer) case *JSONOverlapsExpr: @@ -10282,6 +10399,8 @@ func (a *application) rewriteShowInternal(parent SQLNode, node ShowInternal, rep return a.rewriteRefOfShowCreate(parent, node, replacer) case *ShowOther: return a.rewriteRefOfShowOther(parent, node, replacer) + case *ShowTransactionStatus: + return a.rewriteRefOfShowTransactionStatus(parent, node, replacer) default: // this should never happen return true diff --git a/go/vt/sqlparser/ast_visit.go b/go/vt/sqlparser/ast_visit.go index 07013a3f2d8..d73ed076dbb 100644 --- a/go/vt/sqlparser/ast_visit.go +++ b/go/vt/sqlparser/ast_visit.go @@ -232,6 +232,8 @@ func VisitSQLNode(in SQLNode, f Visit) error { return VisitRefOfIntroducerExpr(in, f) case *IsExpr: return VisitRefOfIsExpr(in, f) + case *JSONArrayAgg: + return VisitRefOfJSONArrayAgg(in, f) case *JSONArrayExpr: return VisitRefOfJSONArrayExpr(in, f) case *JSONAttributesExpr: @@ -244,6 +246,8 @@ func VisitSQLNode(in SQLNode, f Visit) error { return VisitRefOfJSONExtractExpr(in, f) case *JSONKeysExpr: return VisitRefOfJSONKeysExpr(in, f) + case *JSONObjectAgg: + return VisitRefOfJSONObjectAgg(in, f) case *JSONObjectExpr: return VisitRefOfJSONObjectExpr(in, f) case *JSONObjectParam: @@ -456,6 +460,8 @@ func VisitSQLNode(in SQLNode, f Visit) error { return VisitRefOfShowThrottledApps(in, f) case *ShowThrottlerStatus: return VisitRefOfShowThrottlerStatus(in, f) + case *ShowTransactionStatus: + return VisitRefOfShowTransactionStatus(in, f) case *StarExpr: return VisitRefOfStarExpr(in, f) case *Std: @@ -2086,6 +2092,21 @@ func VisitRefOfIsExpr(in *IsExpr, f Visit) error { } return nil } +func VisitRefOfJSONArrayAgg(in *JSONArrayAgg, f Visit) error { + if in == nil { + return nil + } + if cont, err := f(in); err != nil || !cont { + return err + } + if err := VisitExpr(in.Expr, f); err != nil { + return err + } + if err := VisitRefOfOverClause(in.OverClause, f); err != nil { + return err + } + return nil +} func VisitRefOfJSONArrayExpr(in *JSONArrayExpr, f Visit) error { if in == nil { return nil @@ -2185,6 +2206,24 @@ func VisitRefOfJSONKeysExpr(in *JSONKeysExpr, f Visit) error { } return nil } +func VisitRefOfJSONObjectAgg(in *JSONObjectAgg, f Visit) error { + if in == nil { + return nil + } + if cont, err := f(in); err != nil || !cont { + return err + } + if err := VisitExpr(in.Key, f); err != nil { + return err + } + if err := VisitExpr(in.Value, f); err != nil { + return err + } + if err := VisitRefOfOverClause(in.OverClause, f); err != nil { + return err + } + return nil +} func VisitRefOfJSONObjectExpr(in *JSONObjectExpr, f Visit) error { if in == nil { return nil @@ -3677,6 +3716,15 @@ func VisitRefOfShowThrottlerStatus(in *ShowThrottlerStatus, f Visit) error { } return nil } +func VisitRefOfShowTransactionStatus(in *ShowTransactionStatus, f Visit) error { + if in == nil { + return nil + } + if cont, err := f(in); err != nil || !cont { + return err + } + return nil +} func VisitRefOfStarExpr(in *StarExpr, f Visit) error { if in == nil { return nil @@ -4457,6 +4505,10 @@ func VisitAggrFunc(in AggrFunc, f Visit) error { return VisitRefOfCountStar(in, f) case *GroupConcatExpr: return VisitRefOfGroupConcatExpr(in, f) + case *JSONArrayAgg: + return VisitRefOfJSONArrayAgg(in, f) + case *JSONObjectAgg: + return VisitRefOfJSONObjectAgg(in, f) case *Max: return VisitRefOfMax(in, f) case *Min: @@ -4885,6 +4937,8 @@ func VisitExpr(in Expr, f Visit) error { return VisitRefOfIntroducerExpr(in, f) case *IsExpr: return VisitRefOfIsExpr(in, f) + case *JSONArrayAgg: + return VisitRefOfJSONArrayAgg(in, f) case *JSONArrayExpr: return VisitRefOfJSONArrayExpr(in, f) case *JSONAttributesExpr: @@ -4897,6 +4951,8 @@ func VisitExpr(in Expr, f Visit) error { return VisitRefOfJSONExtractExpr(in, f) case *JSONKeysExpr: return VisitRefOfJSONKeysExpr(in, f) + case *JSONObjectAgg: + return VisitRefOfJSONObjectAgg(in, f) case *JSONObjectExpr: return VisitRefOfJSONObjectExpr(in, f) case *JSONOverlapsExpr: @@ -5085,6 +5141,8 @@ func VisitShowInternal(in ShowInternal, f Visit) error { return VisitRefOfShowCreate(in, f) case *ShowOther: return VisitRefOfShowOther(in, f) + case *ShowTransactionStatus: + return VisitRefOfShowTransactionStatus(in, f) default: // this should never happen return nil diff --git a/go/vt/sqlparser/cached_size.go b/go/vt/sqlparser/cached_size.go index 94e004e5e5b..676e40dc7a1 100644 --- a/go/vt/sqlparser/cached_size.go +++ b/go/vt/sqlparser/cached_size.go @@ -1981,6 +1981,22 @@ func (cached *IsExpr) CachedSize(alloc bool) int64 { } return size } +func (cached *JSONArrayAgg) CachedSize(alloc bool) int64 { + if cached == nil { + return int64(0) + } + size := int64(0) + if alloc { + size += int64(24) + } + // field Expr vitess.io/vitess/go/vt/sqlparser.Expr + if cc, ok := cached.Expr.(cachedObject); ok { + size += cc.CachedSize(true) + } + // field OverClause *vitess.io/vitess/go/vt/sqlparser.OverClause + size += cached.OverClause.CachedSize(true) + return size +} func (cached *JSONArrayExpr) CachedSize(alloc bool) int64 { if cached == nil { return int64(0) @@ -2113,6 +2129,26 @@ func (cached *JSONKeysExpr) CachedSize(alloc bool) int64 { } return size } +func (cached *JSONObjectAgg) CachedSize(alloc bool) int64 { + if cached == nil { + return int64(0) + } + size := int64(0) + if alloc { + size += int64(48) + } + // field Key vitess.io/vitess/go/vt/sqlparser.Expr + if cc, ok := cached.Key.(cachedObject); ok { + size += cc.CachedSize(true) + } + // field Value vitess.io/vitess/go/vt/sqlparser.Expr + if cc, ok := cached.Value.(cachedObject); ok { + size += cc.CachedSize(true) + } + // field OverClause *vitess.io/vitess/go/vt/sqlparser.OverClause + size += cached.OverClause.CachedSize(true) + return size +} func (cached *JSONObjectExpr) CachedSize(alloc bool) int64 { if cached == nil { return int64(0) @@ -3886,6 +3922,18 @@ func (cached *ShowThrottlerStatus) CachedSize(alloc bool) int64 { } return size } +func (cached *ShowTransactionStatus) CachedSize(alloc bool) int64 { + if cached == nil { + return int64(0) + } + size := int64(0) + if alloc { + size += int64(16) + } + // field TransactionID string + size += hack.RuntimeAllocSize(int64(len(cached.TransactionID))) + return size +} func (cached *StarExpr) CachedSize(alloc bool) int64 { if cached == nil { return int64(0) diff --git a/go/vt/sqlparser/constants.go b/go/vt/sqlparser/constants.go index 024a2148c33..fa243c88d86 100644 --- a/go/vt/sqlparser/constants.go +++ b/go/vt/sqlparser/constants.go @@ -23,7 +23,11 @@ const ( // Select.Distinct AllStr = "all " DistinctStr = "distinct " + HighPriorityStr = "high_priority " StraightJoinHint = "straight_join " + SQLSmallResultStr = "sql_small_result " + SQLBigResultStr = "sql_big_result " + SQLBufferResultStr = "sql_buffer_result " SQLCalcFoundRowsStr = "sql_calc_found_rows " // Select.Lock @@ -478,6 +482,9 @@ const ( // KillType strings ConnectionStr = "connection" QueryStr = "query" + + // GroupConcatDefaultSeparator is the default separator for GroupConcatExpr. + GroupConcatDefaultSeparator = "," ) // Constants for Enum Type - Insert.Action @@ -942,6 +949,7 @@ const ( CancelMigrationType CancelAllMigrationType CleanupMigrationType + CleanupAllMigrationType ThrottleMigrationType ThrottleAllMigrationType UnthrottleMigrationType diff --git a/go/vt/sqlparser/keywords.go b/go/vt/sqlparser/keywords.go index 2f83d026fbc..54a5a06d84e 100644 --- a/go/vt/sqlparser/keywords.go +++ b/go/vt/sqlparser/keywords.go @@ -315,7 +315,7 @@ var keywords = []keyword{ {"hash", HASH}, {"having", HAVING}, {"header", HEADER}, - {"high_priority", UNUSED}, + {"high_priority", HIGH_PRIORITY}, {"hosts", HOSTS}, {"hour", HOUR}, {"hour_microsecond", HOUR_MICROSECOND}, @@ -356,6 +356,7 @@ var keywords = []keyword{ {"join", JOIN}, {"json", JSON}, {"json_array", JSON_ARRAY}, + {"json_arrayagg", JSON_ARRAYAGG}, {"json_array_append", JSON_ARRAY_APPEND}, {"json_array_insert", JSON_ARRAY_INSERT}, {"json_contains", JSON_CONTAINS}, @@ -363,12 +364,13 @@ var keywords = []keyword{ {"json_depth", JSON_DEPTH}, {"json_extract", JSON_EXTRACT}, {"json_insert", JSON_INSERT}, - {"json_length", JSON_LENGTH}, {"json_keys", JSON_KEYS}, + {"json_length", JSON_LENGTH}, {"json_merge", JSON_MERGE}, {"json_merge_patch", JSON_MERGE_PATCH}, {"json_merge_preserve", JSON_MERGE_PRESERVE}, {"json_object", JSON_OBJECT}, + {"json_objectagg", JSON_OBJECTAGG}, {"json_overlaps", JSON_OVERLAPS}, {"json_pretty", JSON_PRETTY}, {"json_remove", JSON_REMOVE}, @@ -592,11 +594,12 @@ var keywords = []keyword{ {"sqlexception", UNUSED}, {"sqlstate", UNUSED}, {"sqlwarning", UNUSED}, - {"sql_big_result", UNUSED}, + {"sql_big_result", SQL_BIG_RESULT}, {"sql_cache", SQL_CACHE}, {"sql_calc_found_rows", SQL_CALC_FOUND_ROWS}, {"sql_no_cache", SQL_NO_CACHE}, - {"sql_small_result", UNUSED}, + {"sql_small_result", SQL_SMALL_RESULT}, + {"sql_buffer_result", SQL_BUFFER_RESULT}, {"sql_tsi_day", SQL_TSI_DAY}, {"sql_tsi_week", SQL_TSI_WEEK}, {"sql_tsi_hour", SQL_TSI_HOUR}, @@ -749,6 +752,7 @@ var keywords = []keyword{ {"varcharacter", UNUSED}, {"variance", VARIANCE}, {"varying", UNUSED}, + {"vector", VECTOR}, {"vexplain", VEXPLAIN}, {"vgtid_executed", VGTID_EXECUTED}, {"virtual", VIRTUAL}, diff --git a/go/vt/sqlparser/normalizer_test.go b/go/vt/sqlparser/normalizer_test.go index 19b0cfbcac6..c574b00832d 100644 --- a/go/vt/sqlparser/normalizer_test.go +++ b/go/vt/sqlparser/normalizer_test.go @@ -82,17 +82,24 @@ func TestNormalize(t *testing.T) { }, { // datetime val in: "select * from t where foobar = timestamp'2012-02-29 12:34:56.123456'", - outstmt: "select * from t where foobar = :foobar /* DATETIME(6) */", + outstmt: "select * from t where foobar = CAST(:foobar AS DATETIME(6))", outbv: map[string]*querypb.BindVariable{ "foobar": sqltypes.ValueBindVariable(sqltypes.NewDatetime("2012-02-29 12:34:56.123456")), }, }, { // time val in: "select * from t where foobar = time'12:34:56.123456'", - outstmt: "select * from t where foobar = :foobar /* TIME(6) */", + outstmt: "select * from t where foobar = CAST(:foobar AS TIME(6))", outbv: map[string]*querypb.BindVariable{ "foobar": sqltypes.ValueBindVariable(sqltypes.NewTime("12:34:56.123456")), }, + }, { + // time val + in: "select * from t where foobar = time'12:34:56'", + outstmt: "select * from t where foobar = CAST(:foobar AS TIME)", + outbv: map[string]*querypb.BindVariable{ + "foobar": sqltypes.ValueBindVariable(sqltypes.NewTime("12:34:56")), + }, }, { // multiple vals in: "select * from t where foo = 1.2 and bar = 2", @@ -334,21 +341,21 @@ func TestNormalize(t *testing.T) { }, { // DateVal should also be normalized in: `select date'2022-08-06'`, - outstmt: `select :bv1 /* DATE */ from dual`, + outstmt: `select CAST(:bv1 AS DATE) from dual`, outbv: map[string]*querypb.BindVariable{ "bv1": sqltypes.ValueBindVariable(sqltypes.MakeTrusted(sqltypes.Date, []byte("2022-08-06"))), }, }, { // TimeVal should also be normalized in: `select time'17:05:12'`, - outstmt: `select :bv1 /* TIME */ from dual`, + outstmt: `select CAST(:bv1 AS TIME) from dual`, outbv: map[string]*querypb.BindVariable{ "bv1": sqltypes.ValueBindVariable(sqltypes.MakeTrusted(sqltypes.Time, []byte("17:05:12"))), }, }, { // TimestampVal should also be normalized in: `select timestamp'2022-08-06 17:05:12'`, - outstmt: `select :bv1 /* DATETIME */ from dual`, + outstmt: `select CAST(:bv1 AS DATETIME) from dual`, outbv: map[string]*querypb.BindVariable{ "bv1": sqltypes.ValueBindVariable(sqltypes.MakeTrusted(sqltypes.Datetime, []byte("2022-08-06 17:05:12"))), }, diff --git a/go/vt/sqlparser/parse_test.go b/go/vt/sqlparser/parse_test.go index 0fef81f4514..55a54b4a60a 100644 --- a/go/vt/sqlparser/parse_test.go +++ b/go/vt/sqlparser/parse_test.go @@ -1089,7 +1089,7 @@ var ( output: "select /* quote quote in string */ 'a\\'a' from t", }, { input: "select /* double quote quote in string */ \"a\"\"a\" from t", - output: "select /* double quote quote in string */ 'a\\\"a' from t", + output: "select /* double quote quote in string */ 'a\"a' from t", }, { input: "select /* quote in double quoted string */ \"a'a\" from t", output: "select /* quote in double quoted string */ 'a\\'a' from t", @@ -1098,7 +1098,8 @@ var ( }, { input: "select /* literal backslash in string */ 'a\\\\na' from t", }, { - input: "select /* all escapes */ '\\0\\'\\\"\\b\\n\\r\\t\\Z\\\\' from t", + input: "select /* all escapes */ '\\0\\'\\\"\\b\\n\\r\\t\\Z\\\\' from t", + output: "select /* all escapes */ '\\0\\'\"\\b\\n\\r\\t\\Z\\\\' from t", }, { input: "select /* non-escape */ '\\x' from t", output: "select /* non-escape */ 'x' from t", @@ -1227,6 +1228,9 @@ var ( input: "select /* bool in order by */ * from t order by a is null or b asc", }, { input: "select /* string in case statement */ if(max(case a when 'foo' then 1 else 0 end) = 1, 'foo', 'bar') as foobar from t", + }, { + input: "select 1 as vector", + output: "select 1 as `vector` from dual", }, { input: "/*!show databases*/", output: "show databases", @@ -2427,6 +2431,17 @@ var ( input: "show vitess_migrations like '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90'", }, { input: "show vitess_migration '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90' logs", + }, { + input: "show transaction status for 'ks:-80:232323238342'", + }, { + input: "show transaction status for \"ks:-80:232323238342\"", + output: "show transaction status for 'ks:-80:232323238342'", + }, { + input: "show transaction status 'ks:-80:232323238342'", + output: "show transaction status for 'ks:-80:232323238342'", + }, { + input: "show transaction status \"ks:-80:232323238342\"", + output: "show transaction status for 'ks:-80:232323238342'", }, { input: "revert vitess_migration '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90'", }, { @@ -2435,6 +2450,8 @@ var ( input: "alter vitess_migration '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90' retry", }, { input: "alter vitess_migration '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90' cleanup", + }, { + input: "alter vitess_migration cleanup all", }, { input: "alter vitess_migration '9748c3b7_7fdb_11eb_ac2c_f875a4d24e90' launch", }, { @@ -2645,9 +2662,24 @@ var ( }, { input: "select sql_no_cache straight_join distinct 'foo' from t", output: "select distinct sql_no_cache straight_join 'foo' from t", + }, { + input: "select sql_buffer_result 'foo' from t", + output: "select sql_buffer_result 'foo' from t", + }, { + input: "select high_priority 'foo' from t", + output: "select high_priority 'foo' from t", }, { input: "select straight_join distinct sql_no_cache 'foo' from t", output: "select distinct sql_no_cache straight_join 'foo' from t", + }, { + input: "select sql_small_result 'foo' from t", + output: "select sql_small_result 'foo' from t", + }, { + input: "select distinct sql_small_result 'foo' from t", + output: "select distinct sql_small_result 'foo' from t", + }, { + input: "select sql_big_result 'foo' from t", + output: "select sql_big_result 'foo' from t", }, { input: "select sql_calc_found_rows 'foo' from t", output: "select sql_calc_found_rows 'foo' from t", @@ -2926,12 +2958,24 @@ var ( }, { input: "DROP /* comment */ PREPARE stmt1", output: "deallocate /* comment */ prepare stmt1", + }, { + input: "select count(1) from user where x_id = 'abc' group by n_id having json_arrayagg(indexes) = '[]'", + output: "select count(1) from `user` where x_id = 'abc' group by n_id having json_arrayagg(`indexes`) = '[]'", + }, { + input: "select count(1) from user where x_id = 'abc' group by n_id having json_arrayagg(x + 'abc') over w = '[]'", + output: "select count(1) from `user` where x_id = 'abc' group by n_id having json_arrayagg(x + 'abc') over w = '[]'", + }, { + input: "select count(1) from user where x_id = 'abc' group by n_id having json_objectagg(a, b) over w = '[]'", + output: "select count(1) from `user` where x_id = 'abc' group by n_id having json_objectagg(a, b) over w = '[]'", + }, { + input: "select count(1) from user where x_id = 'abc' group by n_id having json_objectagg(a, b) = '[]'", + output: "select count(1) from `user` where x_id = 'abc' group by n_id having json_objectagg(a, b) = '[]'", }, { input: `SELECT JSON_PRETTY('{"a":"10","b":"15","x":"25"}')`, - output: `select json_pretty('{\"a\":\"10\",\"b\":\"15\",\"x\":\"25\"}') from dual`, + output: `select json_pretty('{"a":"10","b":"15","x":"25"}') from dual`, }, { input: `SELECT JSON_PRETTY(N'{"a":"10","b":"15","x":"25"}')`, - output: `select json_pretty(N'{\"a\":\"10\",\"b\":\"15\",\"x\":\"25\"}') from dual`, + output: `select json_pretty(N'{"a":"10","b":"15","x":"25"}') from dual`, /*We need to ignore this test because, after the normalizer, we change the produced NChar string into an introducer expression, so the vttablet will never see a NChar string */ ignoreNormalizerTest: true, @@ -2946,13 +2990,13 @@ var ( output: "select jcol, json_storage_size(jcol) as Size from jtable", }, { input: `SELECT jcol, JSON_STORAGE_SIZE(N'{"a":"10","b":"15","x":"25"}') AS Size FROM jtable`, - output: `select jcol, json_storage_size(N'{\"a\":\"10\",\"b\":\"15\",\"x\":\"25\"}') as Size from jtable`, + output: `select jcol, json_storage_size(N'{"a":"10","b":"15","x":"25"}') as Size from jtable`, /*We need to ignore this test because, after the normalizer, we change the produced NChar string into an introducer expression, so the vttablet will never see a NChar string */ ignoreNormalizerTest: true, }, { input: `SELECT JSON_STORAGE_SIZE('[100, "sakila", [1, 3, 5], 425.05]') AS A, JSON_STORAGE_SIZE('{"a": 1000, "b": "a", "c": "[1, 3, 5, 7]"}') AS B, JSON_STORAGE_SIZE('{"a": 1000, "b": "wxyz", "c": "[1, 3, 5, 7]"}') AS C,JSON_STORAGE_SIZE('[100, "json", [[10, 20, 30], 3, 5], 425.05]') AS D`, - output: `select json_storage_size('[100, \"sakila\", [1, 3, 5], 425.05]') as A, json_storage_size('{\"a\": 1000, \"b\": \"a\", \"c\": \"[1, 3, 5, 7]\"}') as B, json_storage_size('{\"a\": 1000, \"b\": \"wxyz\", \"c\": \"[1, 3, 5, 7]\"}') as C, json_storage_size('[100, \"json\", [[10, 20, 30], 3, 5], 425.05]') as D from dual`, + output: `select json_storage_size('[100, "sakila", [1, 3, 5], 425.05]') as A, json_storage_size('{"a": 1000, "b": "a", "c": "[1, 3, 5, 7]"}') as B, json_storage_size('{"a": 1000, "b": "wxyz", "c": "[1, 3, 5, 7]"}') as C, json_storage_size('[100, "json", [[10, 20, 30], 3, 5], 425.05]') as D from dual`, }, { input: "SELECT JSON_STORAGE_SIZE(@j)", output: "select json_storage_size(@j) from dual", @@ -2961,10 +3005,10 @@ var ( output: "select json_storage_free(jcol) from jtable", }, { input: `SELECT JSON_STORAGE_FREE('{"a":"10","b":"15","x":"25"}')`, - output: `select json_storage_free('{\"a\":\"10\",\"b\":\"15\",\"x\":\"25\"}') from dual`, + output: `select json_storage_free('{"a":"10","b":"15","x":"25"}') from dual`, }, { input: `SELECT JSON_STORAGE_FREE(N'{"a":"10","b":"15","x":"25"}')`, - output: `select json_storage_free(N'{\"a\":\"10\",\"b\":\"15\",\"x\":\"25\"}') from dual`, + output: `select json_storage_free(N'{"a":"10","b":"15","x":"25"}') from dual`, /*We need to ignore this test because, after the normalizer, we change the produced NChar string into an introducer expression, so the vttablet will never see a NChar string */ ignoreNormalizerTest: true, @@ -3003,13 +3047,13 @@ var ( output: "select trim(both 'a' from 'abc') from dual", }, { input: `SELECT * FROM JSON_TABLE('[ {"c1": null} ]','$[*]' COLUMNS( c1 INT PATH '$.c1' ERROR ON ERROR )) as jt`, - output: `select * from json_table('[ {\"c1\": null} ]', '$[*]' columns( + output: `select * from json_table('[ {"c1": null} ]', '$[*]' columns( c1 INT path '$.c1' error on error ) ) as jt`, }, { input: `SELECT * FROM JSON_TABLE( '[{"a": 1, "b": [11,111]}, {"a": 2, "b": [22,222]}]', '$[*]' COLUMNS(a INT PATH '$.a', NESTED PATH '$.b[*]' COLUMNS (b1 INT PATH '$'), NESTED PATH '$.b[*]' COLUMNS (b2 INT PATH '$'))) AS jt`, - output: `select * from json_table('[{\"a\": 1, \"b\": [11,111]}, {\"a\": 2, \"b\": [22,222]}]', '$[*]' columns( + output: `select * from json_table('[{"a": 1, "b": [11,111]}, {"a": 2, "b": [22,222]}]', '$[*]' columns( a INT path '$.a' , nested path '$.b[*]' columns( b1 INT path '$' @@ -3021,22 +3065,22 @@ var ( ) as jt`, }, { input: `SELECT * FROM JSON_TABLE('[ {"c1": null} ]','$[*]' COLUMNS( c1 INT PATH '$.c1' ERROR ON ERROR )) as jt`, - output: `select * from json_table('[ {\"c1\": null} ]', '$[*]' columns( + output: `select * from json_table('[ {"c1": null} ]', '$[*]' columns( c1 INT path '$.c1' error on error ) ) as jt`, }, { input: `SELECT * FROM JSON_TABLE('[{"a":"3"},{"a":2},{"b":1},{"a":0},{"a":[1,2]}]', "$[*]" COLUMNS(rowid FOR ORDINALITY, ac VARCHAR(100) PATH "$.a" DEFAULT '111' ON EMPTY DEFAULT '999' ON ERROR, aj JSON PATH "$.a" DEFAULT '{"x": 333}' ON EMPTY, bx INT EXISTS PATH "$.b" ) ) AS tt`, - output: `select * from json_table('[{\"a\":\"3\"},{\"a\":2},{\"b\":1},{\"a\":0},{\"a\":[1,2]}]', '$[*]' columns( + output: `select * from json_table('[{"a":"3"},{"a":2},{"b":1},{"a":0},{"a":[1,2]}]', '$[*]' columns( rowid for ordinality, ac VARCHAR(100) path '$.a' default '111' on empty default '999' on error , - aj JSON path '$.a' default '{\"x\": 333}' on empty , + aj JSON path '$.a' default '{"x": 333}' on empty , bx INT exists path '$.b' ) ) as tt`, }, { input: `SELECT * FROM JSON_TABLE( '[ {"a": 1, "b": [11,111]}, {"a": 2, "b": [22,222]}, {"a":3}]', '$[*]' COLUMNS( a INT PATH '$.a', NESTED PATH '$.b[*]' COLUMNS (b INT PATH '$') ) ) AS jt WHERE b IS NOT NULL`, - output: `select * from json_table('[ {\"a\": 1, \"b\": [11,111]}, {\"a\": 2, \"b\": [22,222]}, {\"a\":3}]', '$[*]' columns( + output: `select * from json_table('[ {"a": 1, "b": [11,111]}, {"a": 2, "b": [22,222]}, {"a":3}]', '$[*]' columns( a INT path '$.a' , nested path '$.b[*]' columns( b INT path '$' @@ -3045,14 +3089,14 @@ var ( ) as jt where b is not null`, }, { input: `SELECT * FROM JSON_TABLE( '[{"x":2,"y":"8"},{"x":"3","y":"7"},{"x":"4","y":6}]', "$[1]" COLUMNS( xval VARCHAR(100) PATH "$.x", yval VARCHAR(100) PATH "$.y" ) ) AS jt1`, - output: `select * from json_table('[{\"x\":2,\"y\":\"8\"},{\"x\":\"3\",\"y\":\"7\"},{\"x\":\"4\",\"y\":6}]', '$[1]' columns( + output: `select * from json_table('[{"x":2,"y":"8"},{"x":"3","y":"7"},{"x":"4","y":6}]', '$[1]' columns( xval VARCHAR(100) path '$.x' , yval VARCHAR(100) path '$.y' ) ) as jt1`, }, { input: `SELECT * FROM JSON_TABLE( '[{"a": "a_val","b": [{"c": "c_val", "l": [1,2]}]},{"a": "a_val", "b": [{"c": "c_val","l": [11]}, {"c": "c_val", "l": [22]}]}]', '$[*]' COLUMNS( top_ord FOR ORDINALITY, apath VARCHAR(10) PATH '$.a', NESTED PATH '$.b[*]' COLUMNS ( bpath VARCHAR(10) PATH '$.c', ord FOR ORDINALITY, NESTED PATH '$.l[*]' COLUMNS (lpath varchar(10) PATH '$') ) )) as jt`, - output: `select * from json_table('[{\"a\": \"a_val\",\"b\": [{\"c\": \"c_val\", \"l\": [1,2]}]},{\"a\": \"a_val\", \"b\": [{\"c\": \"c_val\",\"l\": [11]}, {\"c\": \"c_val\", \"l\": [22]}]}]', '$[*]' columns( + output: `select * from json_table('[{"a": "a_val","b": [{"c": "c_val", "l": [1,2]}]},{"a": "a_val", "b": [{"c": "c_val","l": [11]}, {"c": "c_val", "l": [22]}]}]', '$[*]' columns( top_ord for ordinality, apath VARCHAR(10) path '$.a' , nested path '$.b[*]' columns( @@ -3066,7 +3110,7 @@ var ( ) as jt`, }, { input: `SELECT * FROM JSON_TABLE('[{"x":2,"y":"8"},{"x":"3","y":"7"},{"x":"4","y":6}]', "$[1]" COLUMNS( xval VARCHAR(100) PATH "$.x", yval VARCHAR(100) PATH "$.y")) AS jt1;`, - output: `select * from json_table('[{\"x\":2,\"y\":\"8\"},{\"x\":\"3\",\"y\":\"7\"},{\"x\":\"4\",\"y\":6}]', '$[1]' columns( + output: `select * from json_table('[{"x":2,"y":"8"},{"x":"3","y":"7"},{"x":"4","y":6}]', '$[1]' columns( xval VARCHAR(100) path '$.x' , yval VARCHAR(100) path '$.y' ) @@ -3106,7 +3150,7 @@ var ( output: "select json_quote(BIN(11)) from dual", }, { input: `SELECT JSON_QUOTE('null'), JSON_QUOTE('"null"')`, - output: `select json_quote('null'), json_quote('\"null\"') from dual`, + output: `select json_quote('null'), json_quote('"null"') from dual`, }, { input: "select t1.a, dt.a from t1, lateral (select t1.a+t2.a as a from t2) dt", output: "select t1.a, dt.a from t1, lateral (select t1.a + t2.a as a from t2) as dt", @@ -3115,37 +3159,37 @@ var ( output: "select b from v1 as vq1, lateral (select count(*) from v1 as vq2 having vq1.b = 3) as dt", }, { input: `SELECT JSON_SCHEMA_VALID('{"type":"string","pattern":"("}', '"abc"')`, - output: `select json_schema_valid('{\"type\":\"string\",\"pattern\":\"(\"}', '\"abc\"') from dual`, + output: `select json_schema_valid('{"type":"string","pattern":"("}', '"abc"') from dual`, }, { input: `SELECT JSON_SCHEMA_VALID('{"type":"string","pattern":"("}', @a)`, - output: `select json_schema_valid('{\"type\":\"string\",\"pattern\":\"(\"}', @a) from dual`, + output: `select json_schema_valid('{"type":"string","pattern":"("}', @a) from dual`, }, { input: `SELECT JSON_SCHEMA_VALID(@b, BIN(1))`, output: `select json_schema_valid(@b, BIN(1)) from dual`, }, { input: `SELECT JSON_SCHEMA_VALID(N'{"type":"string","pattern":"("}', '"abc"')`, - output: `select json_schema_valid(N'{\"type\":\"string\",\"pattern\":\"(\"}', '\"abc\"') from dual`, + output: `select json_schema_valid(N'{"type":"string","pattern":"("}', '"abc"') from dual`, /*We need to ignore this test because, after the normalizer, we change the produced NChar string into an introducer expression, so the vttablet will never see a NChar string */ ignoreNormalizerTest: true, }, { input: `SELECT JSON_SCHEMA_VALIDATION_REPORT('{"type":"string","pattern":"("}', '"abc"')`, - output: `select json_schema_validation_report('{\"type\":\"string\",\"pattern\":\"(\"}', '\"abc\"') from dual`, + output: `select json_schema_validation_report('{"type":"string","pattern":"("}', '"abc"') from dual`, }, { input: `SELECT JSON_SCHEMA_VALIDATION_REPORT('{"type":"string","pattern":"("}', @a)`, - output: `select json_schema_validation_report('{\"type\":\"string\",\"pattern\":\"(\"}', @a) from dual`, + output: `select json_schema_validation_report('{"type":"string","pattern":"("}', @a) from dual`, }, { input: `SELECT JSON_SCHEMA_VALIDATION_REPORT(@b, BIN(1))`, output: `select json_schema_validation_report(@b, BIN(1)) from dual`, }, { input: `SELECT JSON_SCHEMA_VALIDATION_REPORT(N'{"type":"string","pattern":"("}', '"abc"')`, - output: `select json_schema_validation_report(N'{\"type\":\"string\",\"pattern\":\"(\"}', '\"abc\"') from dual`, + output: `select json_schema_validation_report(N'{"type":"string","pattern":"("}', '"abc"') from dual`, /*We need to ignore this test because, after the normalizer, we change the produced NChar string into an introducer expression, so the vttablet will never see a NChar string */ ignoreNormalizerTest: true, }, { input: `SELECT JSON_CONTAINS('{"a": 1, "b": 2, "c": {"d": 4}}', '1')`, - output: `select json_contains('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', '1') from dual`, + output: `select json_contains('{"a": 1, "b": 2, "c": {"d": 4}}', '1') from dual`, }, { input: "SELECT JSON_CONTAINS(@j, @j2)", output: "select json_contains(@j, @j2) from dual", @@ -3157,7 +3201,7 @@ var ( output: "select json_contains_path(@j, 'one', '$.a', '$.e') from dual", }, { input: `SELECT JSON_CONTAINS_PATH('{"a": 1, "b": 2, "c": {"d": 4}}', 'one', '$.a', '$.e')`, - output: `select json_contains_path('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', 'one', '$.a', '$.e') from dual`, + output: `select json_contains_path('{"a": 1, "b": 2, "c": {"d": 4}}', 'one', '$.a', '$.e') from dual`, }, { input: "SELECT JSON_CONTAINS_PATH(@j, TRIM('one'), '$.a', '$.e')", output: "select json_contains_path(@j, trim('one'), '$.a', '$.e') from dual", @@ -3172,19 +3216,19 @@ var ( output: "select c, json_extract(c, '$.id'), g from jemp where json_extract(c, '$.id') > 1 order by json_extract(c, '$.name') asc", }, { input: `SELECT JSON_EXTRACT('{"a": 1, "b": 2, "c": {"d": 4}}', '$.a', @j)`, - output: `select json_extract('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', '$.a', @j) from dual`, + output: `select json_extract('{"a": 1, "b": 2, "c": {"d": 4}}', '$.a', @j) from dual`, }, { input: "SELECT JSON_EXTRACT(@k, TRIM('abc'))", output: `select json_extract(@k, trim('abc')) from dual`, }, { input: `SELECT JSON_KEYS('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', '$.a')`, - output: `select json_keys('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', '$.a') from dual`, + output: `select json_keys('{"a": 1, "b": 2, "c": {"d": 4}}', '$.a') from dual`, }, { input: `SELECT JSON_KEYS('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}')`, - output: `select json_keys('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}') from dual`, + output: `select json_keys('{"a": 1, "b": 2, "c": {"d": 4}}') from dual`, }, { input: `SELECT JSON_OVERLAPS('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', '$.a')`, - output: `select json_overlaps('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', '$.a') from dual`, + output: `select json_overlaps('{"a": 1, "b": 2, "c": {"d": 4}}', '$.a') from dual`, }, { input: "SELECT JSON_OVERLAPS(@j, @k)", output: "select json_overlaps(@j, @k) from dual", @@ -3196,10 +3240,10 @@ var ( output: "select json_search(@j, 'one', 'abc') from dual", }, { input: `SELECT JSON_SEARCH('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', @j, BIN(2))`, - output: `select json_search('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', @j, BIN(2)) from dual`, + output: `select json_search('{"a": 1, "b": 2, "c": {"d": 4}}', @j, BIN(2)) from dual`, }, { input: `SELECT JSON_SEARCH('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', 'all', '10', NULL)`, - output: `select json_search('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', 'all', '10', null) from dual`, + output: `select json_search('{"a": 1, "b": 2, "c": {"d": 4}}', 'all', '10', null) from dual`, }, { input: "SELECT JSON_SEARCH(@j, 'all', '%b%', '', '$[3]')", output: "select json_search(@j, 'all', '%b%', '', '$[3]') from dual", @@ -3208,7 +3252,7 @@ var ( output: "select json_search(@j, 'all', '%b%', 'a', '$[3]') from dual", }, { input: `SELECT JSON_VALUE('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', '$.a')`, - output: `select json_value('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', '$.a') from dual`, + output: `select json_value('{"a": 1, "b": 2, "c": {"d": 4}}', '$.a') from dual`, }, { input: `SELECT JSON_VALUE(@j, @k)`, output: `select json_value(@j, @k) from dual`, @@ -3220,40 +3264,40 @@ var ( output: `select json_value(@j, @k returning DECIMAL(4, 2)) from dual`, }, { input: `SELECT JSON_VALUE('{"fname": "Joe", "lname": "Palmer"}', '$.fname' returning char(49) Charset utf8mb4 error on error)`, - output: `select json_value('{\"fname\": \"Joe\", \"lname\": \"Palmer\"}', '$.fname' returning char(49) character set utf8mb4 error on error) from dual`, + output: `select json_value('{"fname": "Joe", "lname": "Palmer"}', '$.fname' returning char(49) character set utf8mb4 error on error) from dual`, }, { input: `SELECT JSON_VALUE('{"item": "shoes", "price": "49.95"}', '$.price' NULL ON EMPTY) `, - output: `select json_value('{\"item\": \"shoes\", \"price\": \"49.95\"}', '$.price' null on empty) from dual`, + output: `select json_value('{"item": "shoes", "price": "49.95"}', '$.price' null on empty) from dual`, }, { input: `SELECT JSON_VALUE('{"item": "shoes", "price": "49.95"}', '$.price' NULL ON ERROR) `, - output: `select json_value('{\"item\": \"shoes\", \"price\": \"49.95\"}', '$.price' null on error) from dual`, + output: `select json_value('{"item": "shoes", "price": "49.95"}', '$.price' null on error) from dual`, }, { input: `SELECT JSON_VALUE('{"item": "shoes", "price": "49.95"}', '$.price' NULL ON EMPTY ERROR ON ERROR) `, - output: `select json_value('{\"item\": \"shoes\", \"price\": \"49.95\"}', '$.price' null on empty error on error) from dual`, + output: `select json_value('{"item": "shoes", "price": "49.95"}', '$.price' null on empty error on error) from dual`, }, { input: `select json_value(@j, @k RETURNING FLOAT NULL ON EMPTY ERROR ON ERROR) from dual`, output: `select json_value(@j, @k returning FLOAT null on empty error on error) from dual`, }, { input: `SELECT 17 MEMBER OF ('[23, "abc", 17, "ab", 10]')`, - output: `select 17 member of ('[23, \"abc\", 17, \"ab\", 10]') from dual`, + output: `select 17 member of ('[23, "abc", 17, "ab", 10]') from dual`, }, { input: "SELECT @j MEMBER OF (@k)", output: "select @j member of (@k) from dual", }, { input: `SELECT 17 MEMBER OF('[23, "abc", "17", "ab", 10]'), "17" MEMBER OF('[23, "abc", 17, "ab", 10]')`, - output: `select 17 member of ('[23, \"abc\", \"17\", \"ab\", 10]'), '17' member of ('[23, \"abc\", 17, \"ab\", 10]') from dual`, + output: `select 17 member of ('[23, "abc", "17", "ab", 10]'), '17' member of ('[23, "abc", 17, "ab", 10]') from dual`, }, { input: `SELECT JSON_DEPTH('{}'), JSON_DEPTH('[]'), JSON_DEPTH('true')`, output: `select json_depth('{}'), json_depth('[]'), json_depth('true') from dual`, }, { input: `SELECT JSON_LENGTH('{"a": 1, "b": {"c": 30}}')`, - output: `select json_length('{\"a\": 1, \"b\": {\"c\": 30}}') from dual`, + output: `select json_length('{"a": 1, "b": {"c": 30}}') from dual`, }, { input: `SELECT JSON_LENGTH('{"a": 1, "b": {"c": 30}}', '$.b');`, - output: `select json_length('{\"a\": 1, \"b\": {\"c\": 30}}', '$.b') from dual`, + output: `select json_length('{"a": 1, "b": {"c": 30}}', '$.b') from dual`, }, { input: `SELECT JSON_LENGTH('{\"a\": 1, \"b\": {\"c\": 30}}', @j);`, - output: `select json_length('{\"a\": 1, \"b\": {\"c\": 30}}', @j) from dual`, + output: `select json_length('{"a": 1, "b": {"c": 30}}', @j) from dual`, }, { input: `SELECT jcol, JSON_LENGTH(jcol)`, output: `select jcol, json_length(jcol) from dual`, @@ -3265,49 +3309,49 @@ var ( output: `select json_type(json_extract(@j, '$.a[0]')) from dual`, }, { input: `SELECT JSON_VALID('{\"a\": 1}')`, - output: `select json_valid('{\"a\": 1}') from dual`, + output: `select json_valid('{"a": 1}') from dual`, }, { input: "SELECT JSON_VALID(@j)", output: "select json_valid(@j) from dual", }, { input: `SELECT JSON_ARRAY_APPEND('{ "a": 1, "b": [2, 3]}','$[1]', 'x')`, - output: `select json_array_append('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x') from dual`, + output: `select json_array_append('{ "a": 1, "b": [2, 3]}', '$[1]', 'x') from dual`, }, { input: `SELECT JSON_ARRAY_APPEND('{ "a": 1, "b": [2, 3]}','$[1]', 'x', '$[2]', 1)`, - output: `select json_array_append('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x', '$[2]', 1) from dual`, + output: `select json_array_append('{ "a": 1, "b": [2, 3]}', '$[1]', 'x', '$[2]', 1) from dual`, }, { input: `SELECT JSON_ARRAY_APPEND('{ "a": 1, "b": [2, 3]}','$[1]', 'x', @i, @j)`, - output: `select json_array_append('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x', @i, @j) from dual`, + output: `select json_array_append('{ "a": 1, "b": [2, 3]}', '$[1]', 'x', @i, @j) from dual`, }, { input: `SELECT JSON_ARRAY_APPEND('{ "a": 1, "b": [2, 3]}', @j, 1)`, - output: `select json_array_append('{ \"a\": 1, \"b\": [2, 3]}', @j, 1) from dual`, + output: `select json_array_append('{ "a": 1, "b": [2, 3]}', @j, 1) from dual`, }, { input: `SELECT JSON_ARRAY_APPEND('{ "a": 1, "b": [2, 3]}', '$[1]', @j)`, - output: `select json_array_append('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', @j) from dual`, + output: `select json_array_append('{ "a": 1, "b": [2, 3]}', '$[1]', @j) from dual`, }, { input: `SELECT JSON_ARRAY_APPEND('{ "a": 1, "b": [2, 3]}', @j, @k)`, - output: `select json_array_append('{ \"a\": 1, \"b\": [2, 3]}', @j, @k) from dual`, + output: `select json_array_append('{ "a": 1, "b": [2, 3]}', @j, @k) from dual`, }, { input: "SELECT JSON_ARRAY_APPEND(@i,@j,@k)", output: `select json_array_append(@i, @j, @k) from dual`, }, { input: `SELECT JSON_ARRAY_INSERT('{ "a": 1, "b": [2, 3]}','$[1]', 'x')`, - output: `select json_array_insert('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x') from dual`, + output: `select json_array_insert('{ "a": 1, "b": [2, 3]}', '$[1]', 'x') from dual`, }, { input: `SELECT JSON_ARRAY_INSERT('{ "a": 1, "b": [2, 3]}','$[1]', 'x', '$[2]', 1)`, - output: `select json_array_insert('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x', '$[2]', 1) from dual`, + output: `select json_array_insert('{ "a": 1, "b": [2, 3]}', '$[1]', 'x', '$[2]', 1) from dual`, }, { input: `SELECT JSON_ARRAY_INSERT('{ "a": 1, "b": [2, 3]}','$[1]', 'x', @i, @j)`, - output: `select json_array_insert('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x', @i, @j) from dual`, + output: `select json_array_insert('{ "a": 1, "b": [2, 3]}', '$[1]', 'x', @i, @j) from dual`, }, { input: `SELECT JSON_ARRAY_INSERT('{ "a": 1, "b": [2, 3]}', @j, 1)`, - output: `select json_array_insert('{ \"a\": 1, \"b\": [2, 3]}', @j, 1) from dual`, + output: `select json_array_insert('{ "a": 1, "b": [2, 3]}', @j, 1) from dual`, }, { input: `SELECT JSON_ARRAY_INSERT('{ "a": 1, "b": [2, 3]}', '$[1]', @j)`, - output: `select json_array_insert('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', @j) from dual`, + output: `select json_array_insert('{ "a": 1, "b": [2, 3]}', '$[1]', @j) from dual`, }, { input: `SELECT JSON_ARRAY_INSERT('{ "a": 1, "b": [2, 3]}', @j, @k)`, - output: `select json_array_insert('{ \"a\": 1, \"b\": [2, 3]}', @j, @k) from dual`, + output: `select json_array_insert('{ "a": 1, "b": [2, 3]}', @j, @k) from dual`, }, { input: "SELECT JSON_ARRAY_INSERT(@i,@j,@k)", output: "select json_array_insert(@i, @j, @k) from dual", @@ -3316,22 +3360,22 @@ var ( output: "select json_array_insert(@j, '$[0]', 'x', '$[2][1]', 'y') from dual", }, { input: `SELECT JSON_INSERT('{ "a": 1, "b": [2, 3]}','$[1]', 'x')`, - output: `select json_insert('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x') from dual`, + output: `select json_insert('{ "a": 1, "b": [2, 3]}', '$[1]', 'x') from dual`, }, { input: `SELECT JSON_INSERT('{ "a": 1, "b": [2, 3]}','$[1]', 'x', '$[2]', 1)`, - output: `select json_insert('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x', '$[2]', 1) from dual`, + output: `select json_insert('{ "a": 1, "b": [2, 3]}', '$[1]', 'x', '$[2]', 1) from dual`, }, { input: `SELECT JSON_INSERT('{ "a": 1, "b": [2, 3]}','$[1]', 'x', @i, @j)`, - output: `select json_insert('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x', @i, @j) from dual`, + output: `select json_insert('{ "a": 1, "b": [2, 3]}', '$[1]', 'x', @i, @j) from dual`, }, { input: `SELECT JSON_INSERT('{ "a": 1, "b": [2, 3]}', @j, 1)`, - output: `select json_insert('{ \"a\": 1, \"b\": [2, 3]}', @j, 1) from dual`, + output: `select json_insert('{ "a": 1, "b": [2, 3]}', @j, 1) from dual`, }, { input: `SELECT JSON_INSERT('{ "a": 1, "b": [2, 3]}', '$[1]', @j)`, - output: `select json_insert('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', @j) from dual`, + output: `select json_insert('{ "a": 1, "b": [2, 3]}', '$[1]', @j) from dual`, }, { input: `SELECT JSON_INSERT('{ "a": 1, "b": [2, 3]}', @j, @k)`, - output: `select json_insert('{ \"a\": 1, \"b\": [2, 3]}', @j, @k) from dual`, + output: `select json_insert('{ "a": 1, "b": [2, 3]}', @j, @k) from dual`, }, { input: "SELECT JSON_INSERT(@i,@j,@k)", output: "select json_insert(@i, @j, @k) from dual", @@ -3340,22 +3384,22 @@ var ( output: "select json_insert(@j, '$.a', 10, '$.c', '[true, false]') from dual", }, { input: `SELECT JSON_REPLACE('{ "a": 1, "b": [2, 3]}','$[1]', 'x')`, - output: `select json_replace('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x') from dual`, + output: `select json_replace('{ "a": 1, "b": [2, 3]}', '$[1]', 'x') from dual`, }, { input: `SELECT JSON_REPLACE('{ "a": 1, "b": [2, 3]}','$[1]', 'x', '$[2]', 1)`, - output: `select json_replace('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x', '$[2]', 1) from dual`, + output: `select json_replace('{ "a": 1, "b": [2, 3]}', '$[1]', 'x', '$[2]', 1) from dual`, }, { input: `SELECT JSON_REPLACE('{ "a": 1, "b": [2, 3]}','$[1]', 'x', @i, @j)`, - output: `select json_replace('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x', @i, @j) from dual`, + output: `select json_replace('{ "a": 1, "b": [2, 3]}', '$[1]', 'x', @i, @j) from dual`, }, { input: `SELECT JSON_REPLACE('{ "a": 1, "b": [2, 3]}', @j, 1)`, - output: `select json_replace('{ \"a\": 1, \"b\": [2, 3]}', @j, 1) from dual`, + output: `select json_replace('{ "a": 1, "b": [2, 3]}', @j, 1) from dual`, }, { input: `SELECT JSON_REPLACE('{ "a": 1, "b": [2, 3]}', '$[1]', @j)`, - output: `select json_replace('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', @j) from dual`, + output: `select json_replace('{ "a": 1, "b": [2, 3]}', '$[1]', @j) from dual`, }, { input: `SELECT JSON_REPLACE('{ "a": 1, "b": [2, 3]}', @j, @k)`, - output: `select json_replace('{ \"a\": 1, \"b\": [2, 3]}', @j, @k) from dual`, + output: `select json_replace('{ "a": 1, "b": [2, 3]}', @j, @k) from dual`, }, { input: "SELECT JSON_REPLACE(@i,@j,@k)", output: "select json_replace(@i, @j, @k) from dual", @@ -3364,22 +3408,22 @@ var ( output: "select json_replace(@j, '$.a', 10, '$.c', '[true, false]') from dual", }, { input: `SELECT JSON_SET('{ "a": 1, "b": [2, 3]}','$[1]', 'x')`, - output: `select json_set('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x') from dual`, + output: `select json_set('{ "a": 1, "b": [2, 3]}', '$[1]', 'x') from dual`, }, { input: `SELECT JSON_SET('{ "a": 1, "b": [2, 3]}','$[1]', 'x', '$[2]', 1)`, - output: `select json_set('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x', '$[2]', 1) from dual`, + output: `select json_set('{ "a": 1, "b": [2, 3]}', '$[1]', 'x', '$[2]', 1) from dual`, }, { input: `SELECT JSON_SET('{ "a": 1, "b": [2, 3]}','$[1]', 'x', @i, @j)`, - output: `select json_set('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', 'x', @i, @j) from dual`, + output: `select json_set('{ "a": 1, "b": [2, 3]}', '$[1]', 'x', @i, @j) from dual`, }, { input: `SELECT JSON_SET('{ "a": 1, "b": [2, 3]}', @j, 1)`, - output: `select json_set('{ \"a\": 1, \"b\": [2, 3]}', @j, 1) from dual`, + output: `select json_set('{ "a": 1, "b": [2, 3]}', @j, 1) from dual`, }, { input: `SELECT JSON_SET('{ "a": 1, "b": [2, 3]}', '$[1]', @j)`, - output: `select json_set('{ \"a\": 1, \"b\": [2, 3]}', '$[1]', @j) from dual`, + output: `select json_set('{ "a": 1, "b": [2, 3]}', '$[1]', @j) from dual`, }, { input: `SELECT JSON_SET('{ "a": 1, "b": [2, 3]}', @j, @k)`, - output: `select json_set('{ \"a\": 1, \"b\": [2, 3]}', @j, @k) from dual`, + output: `select json_set('{ "a": 1, "b": [2, 3]}', @j, @k) from dual`, }, { input: "SELECT JSON_SET(@i,@j,@k)", output: "select json_set(@i, @j, @k) from dual", @@ -3406,10 +3450,10 @@ var ( output: "select json_merge(@i, '[true, false]') from dual", }, { input: `SELECT JSON_MERGE_PATCH('{"name": "x"}', '{"id": 47}')`, - output: `select json_merge_patch('{\"name\": \"x\"}', '{\"id\": 47}') from dual`, + output: `select json_merge_patch('{"name": "x"}', '{"id": 47}') from dual`, }, { input: `SELECT JSON_MERGE_PATCH('{ "a": 1, "b":2 }','{ "a": 3, "c":4 }','{ "a": 5, "d":6 }');`, - output: `select json_merge_patch('{ \"a\": 1, \"b\":2 }', '{ \"a\": 3, \"c\":4 }', '{ \"a\": 5, \"d\":6 }') from dual`, + output: `select json_merge_patch('{ "a": 1, "b":2 }', '{ "a": 3, "c":4 }', '{ "a": 5, "d":6 }') from dual`, }, { input: "SELECT JSON_MERGE_PATCH('[1, 2]', '[true, false]', 'hello')", output: "select json_merge_patch('[1, 2]', '[true, false]', 'hello') from dual", @@ -3424,10 +3468,10 @@ var ( output: "select json_merge_patch(@i, '[true, false]') from dual", }, { input: `SELECT JSON_MERGE_PRESERVE('{"name": "x"}', '{"id": 47}')`, - output: `select json_merge_preserve('{\"name\": \"x\"}', '{\"id\": 47}') from dual`, + output: `select json_merge_preserve('{"name": "x"}', '{"id": 47}') from dual`, }, { input: `SELECT JSON_MERGE_PRESERVE('{ "a": 1, "b":2 }','{ "a": 3, "c":4 }','{ "a": 5, "d":6 }');`, - output: `select json_merge_preserve('{ \"a\": 1, \"b\":2 }', '{ \"a\": 3, \"c\":4 }', '{ \"a\": 5, \"d\":6 }') from dual`, + output: `select json_merge_preserve('{ "a": 1, "b":2 }', '{ "a": 3, "c":4 }', '{ "a": 5, "d":6 }') from dual`, }, { input: "SELECT JSON_MERGE_PRESERVE('[1, 2]', '[true, false]', 'hello')", output: "select json_merge_preserve('[1, 2]', '[true, false]', 'hello') from dual", @@ -3445,19 +3489,19 @@ var ( output: "select json_remove(@i, '$[1]') from dual", }, { input: `SELECT JSON_REMOVE('["a", ["b", "c"], "d"]', '$[1]')`, - output: `select json_remove('[\"a\", [\"b\", \"c\"], \"d\"]', '$[1]') from dual`, + output: `select json_remove('["a", ["b", "c"], "d"]', '$[1]') from dual`, }, { input: `SELECT JSON_REMOVE('["a", ["b", "c"], "d"]', @i)`, - output: `select json_remove('[\"a\", [\"b\", \"c\"], \"d\"]', @i) from dual`, + output: `select json_remove('["a", ["b", "c"], "d"]', @i) from dual`, }, { input: `SELECT JSON_REMOVE('["a", ["b", "c"], "d"]', @i, @j, '$[0]', '$[1]','$[2]')`, - output: `select json_remove('[\"a\", [\"b\", \"c\"], \"d\"]', @i, @j, '$[0]', '$[1]', '$[2]') from dual`, + output: `select json_remove('["a", ["b", "c"], "d"]', @i, @j, '$[0]', '$[1]', '$[2]') from dual`, }, { input: "SELECT JSON_UNQUOTE('abc')", output: "select json_unquote('abc') from dual", }, { input: `SELECT JSON_UNQUOTE('\"\\\\t\\\\u0032\"')`, - output: `select json_unquote('\"\\\\t\\\\u0032\"') from dual`, + output: `select json_unquote('"\\\\t\\\\u0032"') from dual`, }, { input: "SELECT JSON_UNQUOTE(@j)", output: "select json_unquote(@j) from dual", @@ -3787,7 +3831,7 @@ var ( output: "select `time`, subject, variance(val) over ( partition by `time`, subject) as window_result from observations group by `time`, subject", }, { input: "SELECT id, coalesce( (SELECT Json_arrayagg(Json_array(id)) FROM (SELECT *, Row_number() over (ORDER BY users.order ASC) FROM unsharded as users WHERE users.purchaseorderid = orders.id) users), json_array()) AS users, coalesce( (SELECT json_arrayagg(json_array(id)) FROM (SELECT *, row_number() over (ORDER BY tests.order ASC) FROM unsharded as tests WHERE tests.purchaseorderid = orders.id) tests), json_array()) AS tests FROM unsharded as orders WHERE orders.id = 'xxx'", - output: "select id, coalesce((select Json_arrayagg(json_array(id)) from (select *, row_number() over ( order by users.`order` asc) from unsharded as users where users.purchaseorderid = orders.id) as users), json_array()) as users, coalesce((select json_arrayagg(json_array(id)) from (select *, row_number() over ( order by tests.`order` asc) from unsharded as tests where tests.purchaseorderid = orders.id) as tests), json_array()) as tests from unsharded as orders where orders.id = 'xxx'", + output: "select id, coalesce((select json_arrayagg(json_array(id)) from (select *, row_number() over ( order by users.`order` asc) from unsharded as users where users.purchaseorderid = orders.id) as users), json_array()) as users, coalesce((select json_arrayagg(json_array(id)) from (select *, row_number() over ( order by tests.`order` asc) from unsharded as tests where tests.purchaseorderid = orders.id) as tests), json_array()) as tests from unsharded as orders where orders.id = 'xxx'", }, { input: `kill connection 18446744073709551615`, }, { @@ -4537,7 +4581,8 @@ func TestSelectInto(t *testing.T) { input: "select * from t order by name limit 100 into outfile s3 'out_file_name'", output: "select * from t order by `name` asc limit 100 into outfile s3 'out_file_name'", }, { - input: `select * from TestPerson into outfile s3 's3://test-bucket/export_import/export/users.csv' fields terminated by ',' enclosed by '\"' escaped by '\\' overwrite on`, + input: `select * from TestPerson into outfile s3 's3://test-bucket/export_import/export/users.csv' fields terminated by ',' enclosed by '\"' escaped by '\\' overwrite on`, + output: `select * from TestPerson into outfile s3 's3://test-bucket/export_import/export/users.csv' fields terminated by ',' enclosed by '"' escaped by '\\' overwrite on`, }, { input: "select * from t into dumpfile 'out_file_name'", }, { @@ -5880,6 +5925,14 @@ partition by range (YEAR(purchased)) subpartition by hash (TO_DAYS(purchased)) input: "create table t (id int, info JSON, INDEX zips((CAST(info->'$.field' AS unsigned ARRAY))))", output: "create table t (\n\tid int,\n\tinfo JSON,\n\tkey zips ((cast(info -> '$.field' as unsigned array)))\n)", }, + { + input: "create table t (id int, s varchar(255) default 'foo\"bar')", + output: "create table t (\n\tid int,\n\ts varchar(255) default 'foo\"bar'\n)", + }, + { + input: "create table t (id int, vec VECTOR(4))", + output: "create table t (\n\tid int,\n\tvec VECTOR(4)\n)", + }, } parser := NewTestParser() for _, test := range createTableQueries { @@ -6046,6 +6099,12 @@ var ( }, { input: "select next id from a", output: "expecting value after next at position 15 near 'id'", + }, { + input: "select count(1) from user where x_id = 'abc' group by n_id having json_arrayagg(x, y) = '[]'", + output: "syntax error at position 83", + }, { + input: "select count(1) from user where x_id = 'abc' group by n_id having json_objectagg(x, y, z) = '[]'", + output: "syntax error at position 87", }, { input: "select next 1+1 values from a", output: "syntax error at position 15", @@ -6402,8 +6461,11 @@ func testFile(t *testing.T, filename, tempDir string) { errPresent := "" if err != nil { errPresent = err.Error() + expected.WriteString(fmt.Sprintf("ERROR\n%s\nEND\n", escapeNewLines(errPresent))) + } else { + out := String(tree) + expected.WriteString(fmt.Sprintf("OUTPUT\n%s\nEND\n", escapeNewLines(out))) } - expected.WriteString(fmt.Sprintf("ERROR\n%s\nEND\n", escapeNewLines(errPresent))) if err == nil || tcase.errStr != err.Error() { fail = true t.Errorf("File: %s, Line: %d\nDiff:\n%s\n[%s] \n[%s]", filename, tcase.lineno, cmp.Diff(tcase.errStr, errPresent), tcase.errStr, errPresent) diff --git a/go/vt/sqlparser/parsed_query_test.go b/go/vt/sqlparser/parsed_query_test.go index ef59676883f..8ade9d4d31c 100644 --- a/go/vt/sqlparser/parsed_query_test.go +++ b/go/vt/sqlparser/parsed_query_test.go @@ -20,10 +20,11 @@ import ( "reflect" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/sqltypes" querypb "vitess.io/vitess/go/vt/proto/query" - - "github.com/stretchr/testify/assert" ) func TestNewParsedQuery(t *testing.T) { @@ -205,3 +206,92 @@ func TestParseAndBind(t *testing.T) { }) } } + +func TestCastBindVars(t *testing.T) { + testcases := []struct { + typ sqltypes.Type + size int + binds map[string]*querypb.BindVariable + out string + }{ + { + typ: sqltypes.Decimal, + binds: map[string]*querypb.BindVariable{"arg": sqltypes.DecimalBindVariable("50")}, + out: "select CAST(50 AS DECIMAL(0, 0)) from ", + }, + { + typ: sqltypes.Uint32, + binds: map[string]*querypb.BindVariable{"arg": {Type: sqltypes.Uint32, Value: sqltypes.NewUint32(42).Raw()}}, + out: "select CAST(42 AS UNSIGNED) from ", + }, + { + typ: sqltypes.Float64, + binds: map[string]*querypb.BindVariable{"arg": {Type: sqltypes.Float64, Value: sqltypes.NewFloat64(42.42).Raw()}}, + out: "select CAST(42.42 AS DOUBLE) from ", + }, + { + typ: sqltypes.Float32, + binds: map[string]*querypb.BindVariable{"arg": {Type: sqltypes.Float32, Value: sqltypes.NewFloat32(42).Raw()}}, + out: "select CAST(42 AS FLOAT) from ", + }, + { + typ: sqltypes.Date, + binds: map[string]*querypb.BindVariable{"arg": {Type: sqltypes.Date, Value: sqltypes.NewDate("2021-10-30").Raw()}}, + out: "select CAST('2021-10-30' AS DATE) from ", + }, + { + typ: sqltypes.Time, + binds: map[string]*querypb.BindVariable{"arg": {Type: sqltypes.Time, Value: sqltypes.NewTime("12:00:00").Raw()}}, + out: "select CAST('12:00:00' AS TIME) from ", + }, + { + typ: sqltypes.Time, + size: 6, + binds: map[string]*querypb.BindVariable{"arg": {Type: sqltypes.Time, Value: sqltypes.NewTime("12:00:00").Raw()}}, + out: "select CAST('12:00:00' AS TIME(6)) from ", + }, + { + typ: sqltypes.Timestamp, + binds: map[string]*querypb.BindVariable{"arg": {Type: sqltypes.Timestamp, Value: sqltypes.NewTimestamp("2021-10-22 12:00:00").Raw()}}, + out: "select CAST('2021-10-22 12:00:00' AS DATETIME) from ", + }, + { + typ: sqltypes.Timestamp, + size: 6, + binds: map[string]*querypb.BindVariable{"arg": {Type: sqltypes.Timestamp, Value: sqltypes.NewTimestamp("2021-10-22 12:00:00").Raw()}}, + out: "select CAST('2021-10-22 12:00:00' AS DATETIME(6)) from ", + }, + { + typ: sqltypes.Datetime, + binds: map[string]*querypb.BindVariable{"arg": {Type: sqltypes.Datetime, Value: sqltypes.NewDatetime("2021-10-22 12:00:00").Raw()}}, + out: "select CAST('2021-10-22 12:00:00' AS DATETIME) from ", + }, + { + typ: sqltypes.Datetime, + size: 6, + binds: map[string]*querypb.BindVariable{"arg": {Type: sqltypes.Datetime, Value: sqltypes.NewDatetime("2021-10-22 12:00:00").Raw()}}, + out: "select CAST('2021-10-22 12:00:00' AS DATETIME(6)) from ", + }, + } + + for _, testcase := range testcases { + t.Run(testcase.out, func(t *testing.T) { + argument := NewTypedArgument("arg", testcase.typ) + if testcase.size > 0 { + argument.Size = int32(testcase.size) + } + + s := &Select{ + SelectExprs: SelectExprs{ + NewAliasedExpr(argument, ""), + }, + } + + pq := NewParsedQuery(s) + out, err := pq.GenerateQuery(testcase.binds, nil) + + require.NoError(t, err) + require.Equal(t, testcase.out, out) + }) + } +} diff --git a/go/vt/sqlparser/sql.go b/go/vt/sqlparser/sql.go index 75f5c204ac9..12b9ff7013e 100644 --- a/go/vt/sqlparser/sql.go +++ b/go/vt/sqlparser/sql.go @@ -40,720 +40,728 @@ const MULTIPLE_TEXT_LITERAL = 57347 const FUNCTION_CALL_NON_KEYWORD = 57348 const STRING_TYPE_PREFIX_NON_KEYWORD = 57349 const ANY_SOME = 57350 -const LEX_ERROR = 57351 -const UNION = 57352 -const SELECT = 57353 -const STREAM = 57354 -const VSTREAM = 57355 -const INSERT = 57356 -const UPDATE = 57357 -const DELETE = 57358 -const FROM = 57359 -const WHERE = 57360 -const GROUP = 57361 -const HAVING = 57362 -const ORDER = 57363 -const BY = 57364 -const LIMIT = 57365 -const OFFSET = 57366 -const FOR = 57367 -const DISTINCT = 57368 -const AS = 57369 -const EXISTS = 57370 -const ASC = 57371 -const DESC = 57372 -const INTO = 57373 -const DUPLICATE = 57374 -const DEFAULT = 57375 -const SET = 57376 -const LOCK = 57377 -const UNLOCK = 57378 -const KEYS = 57379 -const DO = 57380 -const CALL = 57381 -const ALL = 57382 -const ANY = 57383 -const SOME = 57384 -const DISTINCTROW = 57385 -const PARSER = 57386 -const GENERATED = 57387 -const ALWAYS = 57388 -const OUTFILE = 57389 -const S3 = 57390 -const DATA = 57391 -const LOAD = 57392 -const LINES = 57393 -const TERMINATED = 57394 -const ESCAPED = 57395 -const ENCLOSED = 57396 -const DUMPFILE = 57397 -const CSV = 57398 -const HEADER = 57399 -const MANIFEST = 57400 -const OVERWRITE = 57401 -const STARTING = 57402 -const OPTIONALLY = 57403 -const VALUES = 57404 -const LAST_INSERT_ID = 57405 -const NEXT = 57406 -const VALUE = 57407 -const SHARE = 57408 -const MODE = 57409 -const SQL_NO_CACHE = 57410 -const SQL_CACHE = 57411 -const SQL_CALC_FOUND_ROWS = 57412 -const JOIN = 57413 -const STRAIGHT_JOIN = 57414 -const LEFT = 57415 -const RIGHT = 57416 -const INNER = 57417 -const OUTER = 57418 -const CROSS = 57419 -const NATURAL = 57420 -const USE = 57421 -const FORCE = 57422 -const ON = 57423 -const USING = 57424 -const INPLACE = 57425 -const COPY = 57426 -const INSTANT = 57427 -const ALGORITHM = 57428 -const NONE = 57429 -const SHARED = 57430 -const EXCLUSIVE = 57431 -const SUBQUERY_AS_EXPR = 57432 -const STRING = 57433 -const ID = 57434 -const AT_ID = 57435 -const AT_AT_ID = 57436 -const HEX = 57437 -const NCHAR_STRING = 57438 -const INTEGRAL = 57439 -const FLOAT = 57440 -const DECIMAL = 57441 -const HEXNUM = 57442 -const COMMENT = 57443 -const COMMENT_KEYWORD = 57444 -const BITNUM = 57445 -const BIT_LITERAL = 57446 -const COMPRESSION = 57447 -const VALUE_ARG = 57448 -const LIST_ARG = 57449 -const OFFSET_ARG = 57450 -const JSON_PRETTY = 57451 -const JSON_STORAGE_SIZE = 57452 -const JSON_STORAGE_FREE = 57453 -const JSON_CONTAINS = 57454 -const JSON_CONTAINS_PATH = 57455 -const JSON_EXTRACT = 57456 -const JSON_KEYS = 57457 -const JSON_OVERLAPS = 57458 -const JSON_SEARCH = 57459 -const JSON_VALUE = 57460 -const EXTRACT = 57461 -const NULL = 57462 -const UNKNOWN = 57463 -const TRUE = 57464 -const FALSE = 57465 -const OFF = 57466 -const DISCARD = 57467 -const IMPORT = 57468 -const ENABLE = 57469 -const DISABLE = 57470 -const TABLESPACE = 57471 -const VIRTUAL = 57472 -const STORED = 57473 -const BOTH = 57474 -const LEADING = 57475 -const TRAILING = 57476 -const KILL = 57477 -const EMPTY_FROM_CLAUSE = 57478 -const LOWER_THAN_CHARSET = 57479 -const CHARSET = 57480 -const UNIQUE = 57481 -const KEY = 57482 -const EXPRESSION_PREC_SETTER = 57483 -const OR = 57484 -const XOR = 57485 -const AND = 57486 -const NOT = 57487 -const BETWEEN = 57488 -const CASE = 57489 -const WHEN = 57490 -const THEN = 57491 -const ELSE = 57492 -const END = 57493 -const LE = 57494 -const GE = 57495 -const NE = 57496 -const NULL_SAFE_EQUAL = 57497 -const IS = 57498 -const LIKE = 57499 -const REGEXP = 57500 -const RLIKE = 57501 -const IN = 57502 -const ASSIGNMENT_OPT = 57503 -const SHIFT_LEFT = 57504 -const SHIFT_RIGHT = 57505 -const DIV = 57506 -const MOD = 57507 -const UNARY = 57508 -const COLLATE = 57509 -const BINARY = 57510 -const UNDERSCORE_ARMSCII8 = 57511 -const UNDERSCORE_ASCII = 57512 -const UNDERSCORE_BIG5 = 57513 -const UNDERSCORE_BINARY = 57514 -const UNDERSCORE_CP1250 = 57515 -const UNDERSCORE_CP1251 = 57516 -const UNDERSCORE_CP1256 = 57517 -const UNDERSCORE_CP1257 = 57518 -const UNDERSCORE_CP850 = 57519 -const UNDERSCORE_CP852 = 57520 -const UNDERSCORE_CP866 = 57521 -const UNDERSCORE_CP932 = 57522 -const UNDERSCORE_DEC8 = 57523 -const UNDERSCORE_EUCJPMS = 57524 -const UNDERSCORE_EUCKR = 57525 -const UNDERSCORE_GB18030 = 57526 -const UNDERSCORE_GB2312 = 57527 -const UNDERSCORE_GBK = 57528 -const UNDERSCORE_GEOSTD8 = 57529 -const UNDERSCORE_GREEK = 57530 -const UNDERSCORE_HEBREW = 57531 -const UNDERSCORE_HP8 = 57532 -const UNDERSCORE_KEYBCS2 = 57533 -const UNDERSCORE_KOI8R = 57534 -const UNDERSCORE_KOI8U = 57535 -const UNDERSCORE_LATIN1 = 57536 -const UNDERSCORE_LATIN2 = 57537 -const UNDERSCORE_LATIN5 = 57538 -const UNDERSCORE_LATIN7 = 57539 -const UNDERSCORE_MACCE = 57540 -const UNDERSCORE_MACROMAN = 57541 -const UNDERSCORE_SJIS = 57542 -const UNDERSCORE_SWE7 = 57543 -const UNDERSCORE_TIS620 = 57544 -const UNDERSCORE_UCS2 = 57545 -const UNDERSCORE_UJIS = 57546 -const UNDERSCORE_UTF16 = 57547 -const UNDERSCORE_UTF16LE = 57548 -const UNDERSCORE_UTF32 = 57549 -const UNDERSCORE_UTF8 = 57550 -const UNDERSCORE_UTF8MB4 = 57551 -const UNDERSCORE_UTF8MB3 = 57552 -const INTERVAL = 57553 -const WINDOW_EXPR = 57554 -const JSON_EXTRACT_OP = 57555 -const JSON_UNQUOTE_EXTRACT_OP = 57556 -const CREATE = 57557 -const ALTER = 57558 -const DROP = 57559 -const RENAME = 57560 -const ANALYZE = 57561 -const ADD = 57562 -const FLUSH = 57563 -const CHANGE = 57564 -const MODIFY = 57565 -const DEALLOCATE = 57566 -const REVERT = 57567 -const QUERIES = 57568 -const SCHEMA = 57569 -const TABLE = 57570 -const INDEX = 57571 -const VIEW = 57572 -const TO = 57573 -const IGNORE = 57574 -const IF = 57575 -const PRIMARY = 57576 -const COLUMN = 57577 -const SPATIAL = 57578 -const FULLTEXT = 57579 -const KEY_BLOCK_SIZE = 57580 -const CHECK = 57581 -const INDEXES = 57582 -const ACTION = 57583 -const CASCADE = 57584 -const CONSTRAINT = 57585 -const FOREIGN = 57586 -const NO = 57587 -const REFERENCES = 57588 -const RESTRICT = 57589 -const SHOW = 57590 -const DESCRIBE = 57591 -const EXPLAIN = 57592 -const DATE = 57593 -const ESCAPE = 57594 -const REPAIR = 57595 -const OPTIMIZE = 57596 -const TRUNCATE = 57597 -const COALESCE = 57598 -const EXCHANGE = 57599 -const REBUILD = 57600 -const PARTITIONING = 57601 -const REMOVE = 57602 -const PREPARE = 57603 -const EXECUTE = 57604 -const MAXVALUE = 57605 -const PARTITION = 57606 -const REORGANIZE = 57607 -const LESS = 57608 -const THAN = 57609 -const PROCEDURE = 57610 -const TRIGGER = 57611 -const VINDEX = 57612 -const VINDEXES = 57613 -const DIRECTORY = 57614 -const NAME = 57615 -const UPGRADE = 57616 -const STATUS = 57617 -const VARIABLES = 57618 -const WARNINGS = 57619 -const CASCADED = 57620 -const DEFINER = 57621 -const OPTION = 57622 -const SQL = 57623 -const UNDEFINED = 57624 -const SEQUENCE = 57625 -const MERGE = 57626 -const TEMPORARY = 57627 -const TEMPTABLE = 57628 -const INVOKER = 57629 -const SECURITY = 57630 -const FIRST = 57631 -const AFTER = 57632 -const LAST = 57633 -const VITESS_MIGRATION = 57634 -const CANCEL = 57635 -const RETRY = 57636 -const LAUNCH = 57637 -const COMPLETE = 57638 -const CLEANUP = 57639 -const THROTTLE = 57640 -const UNTHROTTLE = 57641 -const FORCE_CUTOVER = 57642 -const EXPIRE = 57643 -const RATIO = 57644 -const VITESS_THROTTLER = 57645 -const BEGIN = 57646 -const START = 57647 -const TRANSACTION = 57648 -const COMMIT = 57649 -const ROLLBACK = 57650 -const SAVEPOINT = 57651 -const RELEASE = 57652 -const WORK = 57653 -const CONSISTENT = 57654 -const SNAPSHOT = 57655 -const BIT = 57656 -const TINYINT = 57657 -const SMALLINT = 57658 -const MEDIUMINT = 57659 -const INT = 57660 -const INTEGER = 57661 -const BIGINT = 57662 -const INTNUM = 57663 -const REAL = 57664 -const DOUBLE = 57665 -const FLOAT_TYPE = 57666 -const FLOAT4_TYPE = 57667 -const FLOAT8_TYPE = 57668 -const DECIMAL_TYPE = 57669 -const NUMERIC = 57670 -const TIME = 57671 -const TIMESTAMP = 57672 -const DATETIME = 57673 -const YEAR = 57674 -const CHAR = 57675 -const VARCHAR = 57676 -const BOOL = 57677 -const CHARACTER = 57678 -const VARBINARY = 57679 -const NCHAR = 57680 -const TEXT = 57681 -const TINYTEXT = 57682 -const MEDIUMTEXT = 57683 -const LONGTEXT = 57684 -const BLOB = 57685 -const TINYBLOB = 57686 -const MEDIUMBLOB = 57687 -const LONGBLOB = 57688 -const JSON = 57689 -const JSON_SCHEMA_VALID = 57690 -const JSON_SCHEMA_VALIDATION_REPORT = 57691 -const ENUM = 57692 -const GEOMETRY = 57693 -const POINT = 57694 -const LINESTRING = 57695 -const POLYGON = 57696 -const GEOMCOLLECTION = 57697 -const GEOMETRYCOLLECTION = 57698 -const MULTIPOINT = 57699 -const MULTILINESTRING = 57700 -const MULTIPOLYGON = 57701 -const ASCII = 57702 -const UNICODE = 57703 -const NULLX = 57704 -const AUTO_INCREMENT = 57705 -const APPROXNUM = 57706 -const SIGNED = 57707 -const UNSIGNED = 57708 -const ZEROFILL = 57709 -const PURGE = 57710 -const BEFORE = 57711 -const CODE = 57712 -const COLLATION = 57713 -const COLUMNS = 57714 -const DATABASES = 57715 -const ENGINES = 57716 -const EVENT = 57717 -const EXTENDED = 57718 -const FIELDS = 57719 -const FULL = 57720 -const FUNCTION = 57721 -const GTID_EXECUTED = 57722 -const KEYSPACES = 57723 -const OPEN = 57724 -const PLUGINS = 57725 -const PRIVILEGES = 57726 -const PROCESSLIST = 57727 -const SCHEMAS = 57728 -const TABLES = 57729 -const TRIGGERS = 57730 -const USER = 57731 -const VGTID_EXECUTED = 57732 -const VITESS_KEYSPACES = 57733 -const VITESS_METADATA = 57734 -const VITESS_MIGRATIONS = 57735 -const VITESS_REPLICATION_STATUS = 57736 -const VITESS_SHARDS = 57737 -const VITESS_TABLETS = 57738 -const VITESS_TARGET = 57739 -const VSCHEMA = 57740 -const VITESS_THROTTLED_APPS = 57741 -const NAMES = 57742 -const GLOBAL = 57743 -const SESSION = 57744 -const ISOLATION = 57745 -const LEVEL = 57746 -const READ = 57747 -const WRITE = 57748 -const ONLY = 57749 -const REPEATABLE = 57750 -const COMMITTED = 57751 -const UNCOMMITTED = 57752 -const SERIALIZABLE = 57753 -const ADDDATE = 57754 -const CURRENT_TIMESTAMP = 57755 -const DATABASE = 57756 -const CURRENT_DATE = 57757 -const CURDATE = 57758 -const DATE_ADD = 57759 -const DATE_SUB = 57760 -const NOW = 57761 -const SUBDATE = 57762 -const CURTIME = 57763 -const CURRENT_TIME = 57764 -const LOCALTIME = 57765 -const LOCALTIMESTAMP = 57766 -const CURRENT_USER = 57767 -const UTC_DATE = 57768 -const UTC_TIME = 57769 -const UTC_TIMESTAMP = 57770 -const SYSDATE = 57771 -const DAY = 57772 -const DAY_HOUR = 57773 -const DAY_MICROSECOND = 57774 -const DAY_MINUTE = 57775 -const DAY_SECOND = 57776 -const HOUR = 57777 -const HOUR_MICROSECOND = 57778 -const HOUR_MINUTE = 57779 -const HOUR_SECOND = 57780 -const MICROSECOND = 57781 -const MINUTE = 57782 -const MINUTE_MICROSECOND = 57783 -const MINUTE_SECOND = 57784 -const MONTH = 57785 -const QUARTER = 57786 -const SECOND = 57787 -const SECOND_MICROSECOND = 57788 -const YEAR_MONTH = 57789 -const WEEK = 57790 -const SQL_TSI_DAY = 57791 -const SQL_TSI_WEEK = 57792 -const SQL_TSI_HOUR = 57793 -const SQL_TSI_MINUTE = 57794 -const SQL_TSI_MONTH = 57795 -const SQL_TSI_QUARTER = 57796 -const SQL_TSI_SECOND = 57797 -const SQL_TSI_MICROSECOND = 57798 -const SQL_TSI_YEAR = 57799 -const REPLACE = 57800 -const CONVERT = 57801 -const CAST = 57802 -const SUBSTR = 57803 -const SUBSTRING = 57804 -const MID = 57805 -const SEPARATOR = 57806 -const TIMESTAMPADD = 57807 -const TIMESTAMPDIFF = 57808 -const WEIGHT_STRING = 57809 -const LTRIM = 57810 -const RTRIM = 57811 -const TRIM = 57812 -const JSON_ARRAY = 57813 -const JSON_OBJECT = 57814 -const JSON_QUOTE = 57815 -const JSON_DEPTH = 57816 -const JSON_TYPE = 57817 -const JSON_LENGTH = 57818 -const JSON_VALID = 57819 -const JSON_ARRAY_APPEND = 57820 -const JSON_ARRAY_INSERT = 57821 -const JSON_INSERT = 57822 -const JSON_MERGE = 57823 -const JSON_MERGE_PATCH = 57824 -const JSON_MERGE_PRESERVE = 57825 -const JSON_REMOVE = 57826 -const JSON_REPLACE = 57827 -const JSON_SET = 57828 -const JSON_UNQUOTE = 57829 -const COUNT = 57830 -const AVG = 57831 -const MAX = 57832 -const MIN = 57833 -const SUM = 57834 -const GROUP_CONCAT = 57835 -const BIT_AND = 57836 -const BIT_OR = 57837 -const BIT_XOR = 57838 -const STD = 57839 -const STDDEV = 57840 -const STDDEV_POP = 57841 -const STDDEV_SAMP = 57842 -const VAR_POP = 57843 -const VAR_SAMP = 57844 -const VARIANCE = 57845 -const ANY_VALUE = 57846 -const REGEXP_INSTR = 57847 -const REGEXP_LIKE = 57848 -const REGEXP_REPLACE = 57849 -const REGEXP_SUBSTR = 57850 -const ExtractValue = 57851 -const UpdateXML = 57852 -const GET_LOCK = 57853 -const RELEASE_LOCK = 57854 -const RELEASE_ALL_LOCKS = 57855 -const IS_FREE_LOCK = 57856 -const IS_USED_LOCK = 57857 -const LOCATE = 57858 -const POSITION = 57859 -const ST_GeometryCollectionFromText = 57860 -const ST_GeometryFromText = 57861 -const ST_LineStringFromText = 57862 -const ST_MultiLineStringFromText = 57863 -const ST_MultiPointFromText = 57864 -const ST_MultiPolygonFromText = 57865 -const ST_PointFromText = 57866 -const ST_PolygonFromText = 57867 -const ST_GeometryCollectionFromWKB = 57868 -const ST_GeometryFromWKB = 57869 -const ST_LineStringFromWKB = 57870 -const ST_MultiLineStringFromWKB = 57871 -const ST_MultiPointFromWKB = 57872 -const ST_MultiPolygonFromWKB = 57873 -const ST_PointFromWKB = 57874 -const ST_PolygonFromWKB = 57875 -const ST_AsBinary = 57876 -const ST_AsText = 57877 -const ST_Dimension = 57878 -const ST_Envelope = 57879 -const ST_IsSimple = 57880 -const ST_IsEmpty = 57881 -const ST_GeometryType = 57882 -const ST_X = 57883 -const ST_Y = 57884 -const ST_Latitude = 57885 -const ST_Longitude = 57886 -const ST_EndPoint = 57887 -const ST_IsClosed = 57888 -const ST_Length = 57889 -const ST_NumPoints = 57890 -const ST_StartPoint = 57891 -const ST_PointN = 57892 -const ST_Area = 57893 -const ST_Centroid = 57894 -const ST_ExteriorRing = 57895 -const ST_InteriorRingN = 57896 -const ST_NumInteriorRings = 57897 -const ST_NumGeometries = 57898 -const ST_GeometryN = 57899 -const ST_LongFromGeoHash = 57900 -const ST_PointFromGeoHash = 57901 -const ST_LatFromGeoHash = 57902 -const ST_GeoHash = 57903 -const ST_AsGeoJSON = 57904 -const ST_GeomFromGeoJSON = 57905 -const MATCH = 57906 -const AGAINST = 57907 -const BOOLEAN = 57908 -const LANGUAGE = 57909 -const WITH = 57910 -const QUERY = 57911 -const EXPANSION = 57912 -const WITHOUT = 57913 -const VALIDATION = 57914 -const ROLLUP = 57915 -const UNUSED = 57916 -const ARRAY = 57917 -const BYTE = 57918 -const CUME_DIST = 57919 -const DESCRIPTION = 57920 -const DENSE_RANK = 57921 -const EMPTY = 57922 -const EXCEPT = 57923 -const FIRST_VALUE = 57924 -const GROUPING = 57925 -const GROUPS = 57926 -const JSON_TABLE = 57927 -const LAG = 57928 -const LAST_VALUE = 57929 -const LATERAL = 57930 -const LEAD = 57931 -const NTH_VALUE = 57932 -const NTILE = 57933 -const OF = 57934 -const OVER = 57935 -const PERCENT_RANK = 57936 -const RANK = 57937 -const RECURSIVE = 57938 -const ROW_NUMBER = 57939 -const SYSTEM = 57940 -const WINDOW = 57941 -const ACTIVE = 57942 -const ADMIN = 57943 -const AUTOEXTEND_SIZE = 57944 -const BUCKETS = 57945 -const CLONE = 57946 -const COLUMN_FORMAT = 57947 -const COMPONENT = 57948 -const DEFINITION = 57949 -const ENFORCED = 57950 -const ENGINE_ATTRIBUTE = 57951 -const EXCLUDE = 57952 -const FOLLOWING = 57953 -const GET_MASTER_PUBLIC_KEY = 57954 -const HISTOGRAM = 57955 -const HISTORY = 57956 -const INACTIVE = 57957 -const INVISIBLE = 57958 -const LOCKED = 57959 -const MASTER_COMPRESSION_ALGORITHMS = 57960 -const MASTER_PUBLIC_KEY_PATH = 57961 -const MASTER_TLS_CIPHERSUITES = 57962 -const MASTER_ZSTD_COMPRESSION_LEVEL = 57963 -const NESTED = 57964 -const NETWORK_NAMESPACE = 57965 -const NOWAIT = 57966 -const NULLS = 57967 -const OJ = 57968 -const OLD = 57969 -const OPTIONAL = 57970 -const ORDINALITY = 57971 -const ORGANIZATION = 57972 -const OTHERS = 57973 -const PARTIAL = 57974 -const PATH = 57975 -const PERSIST = 57976 -const PERSIST_ONLY = 57977 -const PRECEDING = 57978 -const PRIVILEGE_CHECKS_USER = 57979 -const PROCESS = 57980 -const RANDOM = 57981 -const REFERENCE = 57982 -const REQUIRE_ROW_FORMAT = 57983 -const RESOURCE = 57984 -const RESPECT = 57985 -const RESTART = 57986 -const RETAIN = 57987 -const REUSE = 57988 -const ROLE = 57989 -const SECONDARY = 57990 -const SECONDARY_ENGINE = 57991 -const SECONDARY_ENGINE_ATTRIBUTE = 57992 -const SECONDARY_LOAD = 57993 -const SECONDARY_UNLOAD = 57994 -const SIMPLE = 57995 -const SKIP = 57996 -const SRID = 57997 -const THREAD_PRIORITY = 57998 -const TIES = 57999 -const UNBOUNDED = 58000 -const VCPU = 58001 -const VISIBLE = 58002 -const RETURNING = 58003 -const FORMAT_BYTES = 58004 -const FORMAT_PICO_TIME = 58005 -const PS_CURRENT_THREAD_ID = 58006 -const PS_THREAD_ID = 58007 -const GTID_SUBSET = 58008 -const GTID_SUBTRACT = 58009 -const WAIT_FOR_EXECUTED_GTID_SET = 58010 -const WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS = 58011 -const FORMAT = 58012 -const TREE = 58013 -const VITESS = 58014 -const TRADITIONAL = 58015 -const VTEXPLAIN = 58016 -const VEXPLAIN = 58017 -const PLAN = 58018 -const LOCAL = 58019 -const LOW_PRIORITY = 58020 -const NO_WRITE_TO_BINLOG = 58021 -const LOGS = 58022 -const ERROR = 58023 -const GENERAL = 58024 -const HOSTS = 58025 -const OPTIMIZER_COSTS = 58026 -const USER_RESOURCES = 58027 -const SLOW = 58028 -const CHANNEL = 58029 -const RELAY = 58030 -const EXPORT = 58031 -const CURRENT = 58032 -const ROW = 58033 -const ROWS = 58034 -const AVG_ROW_LENGTH = 58035 -const CONNECTION = 58036 -const CHECKSUM = 58037 -const DELAY_KEY_WRITE = 58038 -const ENCRYPTION = 58039 -const ENGINE = 58040 -const INSERT_METHOD = 58041 -const MAX_ROWS = 58042 -const MIN_ROWS = 58043 -const PACK_KEYS = 58044 -const PASSWORD = 58045 -const FIXED = 58046 -const DYNAMIC = 58047 -const COMPRESSED = 58048 -const REDUNDANT = 58049 -const COMPACT = 58050 -const ROW_FORMAT = 58051 -const STATS_AUTO_RECALC = 58052 -const STATS_PERSISTENT = 58053 -const STATS_SAMPLE_PAGES = 58054 -const STORAGE = 58055 -const MEMORY = 58056 -const DISK = 58057 -const PARTITIONS = 58058 -const LINEAR = 58059 -const RANGE = 58060 -const LIST = 58061 -const SUBPARTITION = 58062 -const SUBPARTITIONS = 58063 -const HASH = 58064 +const SELECT_OPTIONS = 57351 +const LEX_ERROR = 57352 +const UNION = 57353 +const SELECT = 57354 +const STREAM = 57355 +const VSTREAM = 57356 +const INSERT = 57357 +const UPDATE = 57358 +const DELETE = 57359 +const FROM = 57360 +const WHERE = 57361 +const GROUP = 57362 +const HAVING = 57363 +const ORDER = 57364 +const BY = 57365 +const LIMIT = 57366 +const OFFSET = 57367 +const FOR = 57368 +const DISTINCT = 57369 +const AS = 57370 +const EXISTS = 57371 +const ASC = 57372 +const DESC = 57373 +const INTO = 57374 +const DUPLICATE = 57375 +const DEFAULT = 57376 +const SET = 57377 +const LOCK = 57378 +const UNLOCK = 57379 +const KEYS = 57380 +const DO = 57381 +const CALL = 57382 +const ALL = 57383 +const ANY = 57384 +const SOME = 57385 +const DISTINCTROW = 57386 +const PARSER = 57387 +const GENERATED = 57388 +const ALWAYS = 57389 +const OUTFILE = 57390 +const S3 = 57391 +const DATA = 57392 +const LOAD = 57393 +const LINES = 57394 +const TERMINATED = 57395 +const ESCAPED = 57396 +const ENCLOSED = 57397 +const DUMPFILE = 57398 +const CSV = 57399 +const HEADER = 57400 +const MANIFEST = 57401 +const OVERWRITE = 57402 +const STARTING = 57403 +const OPTIONALLY = 57404 +const VALUES = 57405 +const LAST_INSERT_ID = 57406 +const NEXT = 57407 +const VALUE = 57408 +const SHARE = 57409 +const MODE = 57410 +const SQL_NO_CACHE = 57411 +const SQL_CACHE = 57412 +const SQL_CALC_FOUND_ROWS = 57413 +const SQL_SMALL_RESULT = 57414 +const SQL_BIG_RESULT = 57415 +const HIGH_PRIORITY = 57416 +const JOIN = 57417 +const STRAIGHT_JOIN = 57418 +const LEFT = 57419 +const RIGHT = 57420 +const INNER = 57421 +const OUTER = 57422 +const CROSS = 57423 +const NATURAL = 57424 +const USE = 57425 +const FORCE = 57426 +const ON = 57427 +const USING = 57428 +const INPLACE = 57429 +const COPY = 57430 +const INSTANT = 57431 +const ALGORITHM = 57432 +const NONE = 57433 +const SHARED = 57434 +const EXCLUSIVE = 57435 +const SUBQUERY_AS_EXPR = 57436 +const STRING = 57437 +const SQL_BUFFER_RESULT = 57438 +const ID = 57439 +const AT_ID = 57440 +const AT_AT_ID = 57441 +const HEX = 57442 +const NCHAR_STRING = 57443 +const INTEGRAL = 57444 +const FLOAT = 57445 +const DECIMAL = 57446 +const HEXNUM = 57447 +const COMMENT = 57448 +const COMMENT_KEYWORD = 57449 +const BITNUM = 57450 +const BIT_LITERAL = 57451 +const COMPRESSION = 57452 +const VALUE_ARG = 57453 +const LIST_ARG = 57454 +const OFFSET_ARG = 57455 +const JSON_PRETTY = 57456 +const JSON_STORAGE_SIZE = 57457 +const JSON_STORAGE_FREE = 57458 +const JSON_CONTAINS = 57459 +const JSON_CONTAINS_PATH = 57460 +const JSON_EXTRACT = 57461 +const JSON_KEYS = 57462 +const JSON_OVERLAPS = 57463 +const JSON_SEARCH = 57464 +const JSON_VALUE = 57465 +const JSON_ARRAYAGG = 57466 +const JSON_OBJECTAGG = 57467 +const EXTRACT = 57468 +const NULL = 57469 +const UNKNOWN = 57470 +const TRUE = 57471 +const FALSE = 57472 +const OFF = 57473 +const DISCARD = 57474 +const IMPORT = 57475 +const ENABLE = 57476 +const DISABLE = 57477 +const TABLESPACE = 57478 +const VIRTUAL = 57479 +const STORED = 57480 +const BOTH = 57481 +const LEADING = 57482 +const TRAILING = 57483 +const KILL = 57484 +const EMPTY_FROM_CLAUSE = 57485 +const LOWER_THAN_CHARSET = 57486 +const CHARSET = 57487 +const UNIQUE = 57488 +const KEY = 57489 +const EXPRESSION_PREC_SETTER = 57490 +const OR = 57491 +const XOR = 57492 +const AND = 57493 +const NOT = 57494 +const BETWEEN = 57495 +const CASE = 57496 +const WHEN = 57497 +const THEN = 57498 +const ELSE = 57499 +const END = 57500 +const LE = 57501 +const GE = 57502 +const NE = 57503 +const NULL_SAFE_EQUAL = 57504 +const IS = 57505 +const LIKE = 57506 +const REGEXP = 57507 +const RLIKE = 57508 +const IN = 57509 +const ASSIGNMENT_OPT = 57510 +const SHIFT_LEFT = 57511 +const SHIFT_RIGHT = 57512 +const DIV = 57513 +const MOD = 57514 +const UNARY = 57515 +const COLLATE = 57516 +const BINARY = 57517 +const UNDERSCORE_ARMSCII8 = 57518 +const UNDERSCORE_ASCII = 57519 +const UNDERSCORE_BIG5 = 57520 +const UNDERSCORE_BINARY = 57521 +const UNDERSCORE_CP1250 = 57522 +const UNDERSCORE_CP1251 = 57523 +const UNDERSCORE_CP1256 = 57524 +const UNDERSCORE_CP1257 = 57525 +const UNDERSCORE_CP850 = 57526 +const UNDERSCORE_CP852 = 57527 +const UNDERSCORE_CP866 = 57528 +const UNDERSCORE_CP932 = 57529 +const UNDERSCORE_DEC8 = 57530 +const UNDERSCORE_EUCJPMS = 57531 +const UNDERSCORE_EUCKR = 57532 +const UNDERSCORE_GB18030 = 57533 +const UNDERSCORE_GB2312 = 57534 +const UNDERSCORE_GBK = 57535 +const UNDERSCORE_GEOSTD8 = 57536 +const UNDERSCORE_GREEK = 57537 +const UNDERSCORE_HEBREW = 57538 +const UNDERSCORE_HP8 = 57539 +const UNDERSCORE_KEYBCS2 = 57540 +const UNDERSCORE_KOI8R = 57541 +const UNDERSCORE_KOI8U = 57542 +const UNDERSCORE_LATIN1 = 57543 +const UNDERSCORE_LATIN2 = 57544 +const UNDERSCORE_LATIN5 = 57545 +const UNDERSCORE_LATIN7 = 57546 +const UNDERSCORE_MACCE = 57547 +const UNDERSCORE_MACROMAN = 57548 +const UNDERSCORE_SJIS = 57549 +const UNDERSCORE_SWE7 = 57550 +const UNDERSCORE_TIS620 = 57551 +const UNDERSCORE_UCS2 = 57552 +const UNDERSCORE_UJIS = 57553 +const UNDERSCORE_UTF16 = 57554 +const UNDERSCORE_UTF16LE = 57555 +const UNDERSCORE_UTF32 = 57556 +const UNDERSCORE_UTF8 = 57557 +const UNDERSCORE_UTF8MB4 = 57558 +const UNDERSCORE_UTF8MB3 = 57559 +const INTERVAL = 57560 +const WINDOW_EXPR = 57561 +const JSON_EXTRACT_OP = 57562 +const JSON_UNQUOTE_EXTRACT_OP = 57563 +const CREATE = 57564 +const ALTER = 57565 +const DROP = 57566 +const RENAME = 57567 +const ANALYZE = 57568 +const ADD = 57569 +const FLUSH = 57570 +const CHANGE = 57571 +const MODIFY = 57572 +const DEALLOCATE = 57573 +const REVERT = 57574 +const QUERIES = 57575 +const SCHEMA = 57576 +const TABLE = 57577 +const INDEX = 57578 +const VIEW = 57579 +const TO = 57580 +const IGNORE = 57581 +const IF = 57582 +const PRIMARY = 57583 +const COLUMN = 57584 +const SPATIAL = 57585 +const FULLTEXT = 57586 +const KEY_BLOCK_SIZE = 57587 +const CHECK = 57588 +const INDEXES = 57589 +const ACTION = 57590 +const CASCADE = 57591 +const CONSTRAINT = 57592 +const FOREIGN = 57593 +const NO = 57594 +const REFERENCES = 57595 +const RESTRICT = 57596 +const SHOW = 57597 +const DESCRIBE = 57598 +const EXPLAIN = 57599 +const DATE = 57600 +const ESCAPE = 57601 +const REPAIR = 57602 +const OPTIMIZE = 57603 +const TRUNCATE = 57604 +const COALESCE = 57605 +const EXCHANGE = 57606 +const REBUILD = 57607 +const PARTITIONING = 57608 +const REMOVE = 57609 +const PREPARE = 57610 +const EXECUTE = 57611 +const MAXVALUE = 57612 +const PARTITION = 57613 +const REORGANIZE = 57614 +const LESS = 57615 +const THAN = 57616 +const PROCEDURE = 57617 +const TRIGGER = 57618 +const VINDEX = 57619 +const VINDEXES = 57620 +const DIRECTORY = 57621 +const NAME = 57622 +const UPGRADE = 57623 +const STATUS = 57624 +const VARIABLES = 57625 +const WARNINGS = 57626 +const CASCADED = 57627 +const DEFINER = 57628 +const OPTION = 57629 +const SQL = 57630 +const UNDEFINED = 57631 +const SEQUENCE = 57632 +const MERGE = 57633 +const TEMPORARY = 57634 +const TEMPTABLE = 57635 +const INVOKER = 57636 +const SECURITY = 57637 +const FIRST = 57638 +const AFTER = 57639 +const LAST = 57640 +const VITESS_MIGRATION = 57641 +const CANCEL = 57642 +const RETRY = 57643 +const LAUNCH = 57644 +const COMPLETE = 57645 +const CLEANUP = 57646 +const THROTTLE = 57647 +const UNTHROTTLE = 57648 +const FORCE_CUTOVER = 57649 +const EXPIRE = 57650 +const RATIO = 57651 +const VITESS_THROTTLER = 57652 +const BEGIN = 57653 +const START = 57654 +const TRANSACTION = 57655 +const COMMIT = 57656 +const ROLLBACK = 57657 +const SAVEPOINT = 57658 +const RELEASE = 57659 +const WORK = 57660 +const CONSISTENT = 57661 +const SNAPSHOT = 57662 +const BIT = 57663 +const TINYINT = 57664 +const SMALLINT = 57665 +const MEDIUMINT = 57666 +const INT = 57667 +const INTEGER = 57668 +const BIGINT = 57669 +const INTNUM = 57670 +const REAL = 57671 +const DOUBLE = 57672 +const FLOAT_TYPE = 57673 +const FLOAT4_TYPE = 57674 +const FLOAT8_TYPE = 57675 +const DECIMAL_TYPE = 57676 +const NUMERIC = 57677 +const TIME = 57678 +const TIMESTAMP = 57679 +const DATETIME = 57680 +const YEAR = 57681 +const CHAR = 57682 +const VARCHAR = 57683 +const BOOL = 57684 +const CHARACTER = 57685 +const VARBINARY = 57686 +const NCHAR = 57687 +const TEXT = 57688 +const TINYTEXT = 57689 +const MEDIUMTEXT = 57690 +const LONGTEXT = 57691 +const BLOB = 57692 +const TINYBLOB = 57693 +const MEDIUMBLOB = 57694 +const LONGBLOB = 57695 +const JSON = 57696 +const JSON_SCHEMA_VALID = 57697 +const JSON_SCHEMA_VALIDATION_REPORT = 57698 +const ENUM = 57699 +const GEOMETRY = 57700 +const POINT = 57701 +const LINESTRING = 57702 +const POLYGON = 57703 +const GEOMCOLLECTION = 57704 +const GEOMETRYCOLLECTION = 57705 +const MULTIPOINT = 57706 +const MULTILINESTRING = 57707 +const MULTIPOLYGON = 57708 +const ASCII = 57709 +const UNICODE = 57710 +const VECTOR = 57711 +const NULLX = 57712 +const AUTO_INCREMENT = 57713 +const APPROXNUM = 57714 +const SIGNED = 57715 +const UNSIGNED = 57716 +const ZEROFILL = 57717 +const PURGE = 57718 +const BEFORE = 57719 +const CODE = 57720 +const COLLATION = 57721 +const COLUMNS = 57722 +const DATABASES = 57723 +const ENGINES = 57724 +const EVENT = 57725 +const EXTENDED = 57726 +const FIELDS = 57727 +const FULL = 57728 +const FUNCTION = 57729 +const GTID_EXECUTED = 57730 +const KEYSPACES = 57731 +const OPEN = 57732 +const PLUGINS = 57733 +const PRIVILEGES = 57734 +const PROCESSLIST = 57735 +const SCHEMAS = 57736 +const TABLES = 57737 +const TRIGGERS = 57738 +const USER = 57739 +const VGTID_EXECUTED = 57740 +const VITESS_KEYSPACES = 57741 +const VITESS_METADATA = 57742 +const VITESS_MIGRATIONS = 57743 +const VITESS_REPLICATION_STATUS = 57744 +const VITESS_SHARDS = 57745 +const VITESS_TABLETS = 57746 +const VITESS_TARGET = 57747 +const VSCHEMA = 57748 +const VITESS_THROTTLED_APPS = 57749 +const NAMES = 57750 +const GLOBAL = 57751 +const SESSION = 57752 +const ISOLATION = 57753 +const LEVEL = 57754 +const READ = 57755 +const WRITE = 57756 +const ONLY = 57757 +const REPEATABLE = 57758 +const COMMITTED = 57759 +const UNCOMMITTED = 57760 +const SERIALIZABLE = 57761 +const ADDDATE = 57762 +const CURRENT_TIMESTAMP = 57763 +const DATABASE = 57764 +const CURRENT_DATE = 57765 +const CURDATE = 57766 +const DATE_ADD = 57767 +const DATE_SUB = 57768 +const NOW = 57769 +const SUBDATE = 57770 +const CURTIME = 57771 +const CURRENT_TIME = 57772 +const LOCALTIME = 57773 +const LOCALTIMESTAMP = 57774 +const CURRENT_USER = 57775 +const UTC_DATE = 57776 +const UTC_TIME = 57777 +const UTC_TIMESTAMP = 57778 +const SYSDATE = 57779 +const DAY = 57780 +const DAY_HOUR = 57781 +const DAY_MICROSECOND = 57782 +const DAY_MINUTE = 57783 +const DAY_SECOND = 57784 +const HOUR = 57785 +const HOUR_MICROSECOND = 57786 +const HOUR_MINUTE = 57787 +const HOUR_SECOND = 57788 +const MICROSECOND = 57789 +const MINUTE = 57790 +const MINUTE_MICROSECOND = 57791 +const MINUTE_SECOND = 57792 +const MONTH = 57793 +const QUARTER = 57794 +const SECOND = 57795 +const SECOND_MICROSECOND = 57796 +const YEAR_MONTH = 57797 +const WEEK = 57798 +const SQL_TSI_DAY = 57799 +const SQL_TSI_WEEK = 57800 +const SQL_TSI_HOUR = 57801 +const SQL_TSI_MINUTE = 57802 +const SQL_TSI_MONTH = 57803 +const SQL_TSI_QUARTER = 57804 +const SQL_TSI_SECOND = 57805 +const SQL_TSI_MICROSECOND = 57806 +const SQL_TSI_YEAR = 57807 +const REPLACE = 57808 +const CONVERT = 57809 +const CAST = 57810 +const SUBSTR = 57811 +const SUBSTRING = 57812 +const MID = 57813 +const SEPARATOR = 57814 +const TIMESTAMPADD = 57815 +const TIMESTAMPDIFF = 57816 +const WEIGHT_STRING = 57817 +const LTRIM = 57818 +const RTRIM = 57819 +const TRIM = 57820 +const JSON_ARRAY = 57821 +const JSON_OBJECT = 57822 +const JSON_QUOTE = 57823 +const JSON_DEPTH = 57824 +const JSON_TYPE = 57825 +const JSON_LENGTH = 57826 +const JSON_VALID = 57827 +const JSON_ARRAY_APPEND = 57828 +const JSON_ARRAY_INSERT = 57829 +const JSON_INSERT = 57830 +const JSON_MERGE = 57831 +const JSON_MERGE_PATCH = 57832 +const JSON_MERGE_PRESERVE = 57833 +const JSON_REMOVE = 57834 +const JSON_REPLACE = 57835 +const JSON_SET = 57836 +const JSON_UNQUOTE = 57837 +const COUNT = 57838 +const AVG = 57839 +const MAX = 57840 +const MIN = 57841 +const SUM = 57842 +const GROUP_CONCAT = 57843 +const BIT_AND = 57844 +const BIT_OR = 57845 +const BIT_XOR = 57846 +const STD = 57847 +const STDDEV = 57848 +const STDDEV_POP = 57849 +const STDDEV_SAMP = 57850 +const VAR_POP = 57851 +const VAR_SAMP = 57852 +const VARIANCE = 57853 +const ANY_VALUE = 57854 +const REGEXP_INSTR = 57855 +const REGEXP_LIKE = 57856 +const REGEXP_REPLACE = 57857 +const REGEXP_SUBSTR = 57858 +const ExtractValue = 57859 +const UpdateXML = 57860 +const GET_LOCK = 57861 +const RELEASE_LOCK = 57862 +const RELEASE_ALL_LOCKS = 57863 +const IS_FREE_LOCK = 57864 +const IS_USED_LOCK = 57865 +const LOCATE = 57866 +const POSITION = 57867 +const ST_GeometryCollectionFromText = 57868 +const ST_GeometryFromText = 57869 +const ST_LineStringFromText = 57870 +const ST_MultiLineStringFromText = 57871 +const ST_MultiPointFromText = 57872 +const ST_MultiPolygonFromText = 57873 +const ST_PointFromText = 57874 +const ST_PolygonFromText = 57875 +const ST_GeometryCollectionFromWKB = 57876 +const ST_GeometryFromWKB = 57877 +const ST_LineStringFromWKB = 57878 +const ST_MultiLineStringFromWKB = 57879 +const ST_MultiPointFromWKB = 57880 +const ST_MultiPolygonFromWKB = 57881 +const ST_PointFromWKB = 57882 +const ST_PolygonFromWKB = 57883 +const ST_AsBinary = 57884 +const ST_AsText = 57885 +const ST_Dimension = 57886 +const ST_Envelope = 57887 +const ST_IsSimple = 57888 +const ST_IsEmpty = 57889 +const ST_GeometryType = 57890 +const ST_X = 57891 +const ST_Y = 57892 +const ST_Latitude = 57893 +const ST_Longitude = 57894 +const ST_EndPoint = 57895 +const ST_IsClosed = 57896 +const ST_Length = 57897 +const ST_NumPoints = 57898 +const ST_StartPoint = 57899 +const ST_PointN = 57900 +const ST_Area = 57901 +const ST_Centroid = 57902 +const ST_ExteriorRing = 57903 +const ST_InteriorRingN = 57904 +const ST_NumInteriorRings = 57905 +const ST_NumGeometries = 57906 +const ST_GeometryN = 57907 +const ST_LongFromGeoHash = 57908 +const ST_PointFromGeoHash = 57909 +const ST_LatFromGeoHash = 57910 +const ST_GeoHash = 57911 +const ST_AsGeoJSON = 57912 +const ST_GeomFromGeoJSON = 57913 +const MATCH = 57914 +const AGAINST = 57915 +const BOOLEAN = 57916 +const LANGUAGE = 57917 +const WITH = 57918 +const QUERY = 57919 +const EXPANSION = 57920 +const WITHOUT = 57921 +const VALIDATION = 57922 +const ROLLUP = 57923 +const UNUSED = 57924 +const ARRAY = 57925 +const BYTE = 57926 +const CUME_DIST = 57927 +const DESCRIPTION = 57928 +const DENSE_RANK = 57929 +const EMPTY = 57930 +const EXCEPT = 57931 +const FIRST_VALUE = 57932 +const GROUPING = 57933 +const GROUPS = 57934 +const JSON_TABLE = 57935 +const LAG = 57936 +const LAST_VALUE = 57937 +const LATERAL = 57938 +const LEAD = 57939 +const NTH_VALUE = 57940 +const NTILE = 57941 +const OF = 57942 +const OVER = 57943 +const PERCENT_RANK = 57944 +const RANK = 57945 +const RECURSIVE = 57946 +const ROW_NUMBER = 57947 +const SYSTEM = 57948 +const WINDOW = 57949 +const ACTIVE = 57950 +const ADMIN = 57951 +const AUTOEXTEND_SIZE = 57952 +const BUCKETS = 57953 +const CLONE = 57954 +const COLUMN_FORMAT = 57955 +const COMPONENT = 57956 +const DEFINITION = 57957 +const ENFORCED = 57958 +const ENGINE_ATTRIBUTE = 57959 +const EXCLUDE = 57960 +const FOLLOWING = 57961 +const GET_MASTER_PUBLIC_KEY = 57962 +const HISTOGRAM = 57963 +const HISTORY = 57964 +const INACTIVE = 57965 +const INVISIBLE = 57966 +const LOCKED = 57967 +const MASTER_COMPRESSION_ALGORITHMS = 57968 +const MASTER_PUBLIC_KEY_PATH = 57969 +const MASTER_TLS_CIPHERSUITES = 57970 +const MASTER_ZSTD_COMPRESSION_LEVEL = 57971 +const NESTED = 57972 +const NETWORK_NAMESPACE = 57973 +const NOWAIT = 57974 +const NULLS = 57975 +const OJ = 57976 +const OLD = 57977 +const OPTIONAL = 57978 +const ORDINALITY = 57979 +const ORGANIZATION = 57980 +const OTHERS = 57981 +const PARTIAL = 57982 +const PATH = 57983 +const PERSIST = 57984 +const PERSIST_ONLY = 57985 +const PRECEDING = 57986 +const PRIVILEGE_CHECKS_USER = 57987 +const PROCESS = 57988 +const RANDOM = 57989 +const REFERENCE = 57990 +const REQUIRE_ROW_FORMAT = 57991 +const RESOURCE = 57992 +const RESPECT = 57993 +const RESTART = 57994 +const RETAIN = 57995 +const REUSE = 57996 +const ROLE = 57997 +const SECONDARY = 57998 +const SECONDARY_ENGINE = 57999 +const SECONDARY_ENGINE_ATTRIBUTE = 58000 +const SECONDARY_LOAD = 58001 +const SECONDARY_UNLOAD = 58002 +const SIMPLE = 58003 +const SKIP = 58004 +const SRID = 58005 +const THREAD_PRIORITY = 58006 +const TIES = 58007 +const UNBOUNDED = 58008 +const VCPU = 58009 +const VISIBLE = 58010 +const RETURNING = 58011 +const FORMAT_BYTES = 58012 +const FORMAT_PICO_TIME = 58013 +const PS_CURRENT_THREAD_ID = 58014 +const PS_THREAD_ID = 58015 +const GTID_SUBSET = 58016 +const GTID_SUBTRACT = 58017 +const WAIT_FOR_EXECUTED_GTID_SET = 58018 +const WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS = 58019 +const FORMAT = 58020 +const TREE = 58021 +const VITESS = 58022 +const TRADITIONAL = 58023 +const VTEXPLAIN = 58024 +const VEXPLAIN = 58025 +const PLAN = 58026 +const LOCAL = 58027 +const LOW_PRIORITY = 58028 +const NO_WRITE_TO_BINLOG = 58029 +const LOGS = 58030 +const ERROR = 58031 +const GENERAL = 58032 +const HOSTS = 58033 +const OPTIMIZER_COSTS = 58034 +const USER_RESOURCES = 58035 +const SLOW = 58036 +const CHANNEL = 58037 +const RELAY = 58038 +const EXPORT = 58039 +const CURRENT = 58040 +const ROW = 58041 +const ROWS = 58042 +const AVG_ROW_LENGTH = 58043 +const CONNECTION = 58044 +const CHECKSUM = 58045 +const DELAY_KEY_WRITE = 58046 +const ENCRYPTION = 58047 +const ENGINE = 58048 +const INSERT_METHOD = 58049 +const MAX_ROWS = 58050 +const MIN_ROWS = 58051 +const PACK_KEYS = 58052 +const PASSWORD = 58053 +const FIXED = 58054 +const DYNAMIC = 58055 +const COMPRESSED = 58056 +const REDUNDANT = 58057 +const COMPACT = 58058 +const ROW_FORMAT = 58059 +const STATS_AUTO_RECALC = 58060 +const STATS_PERSISTENT = 58061 +const STATS_SAMPLE_PAGES = 58062 +const STORAGE = 58063 +const MEMORY = 58064 +const DISK = 58065 +const PARTITIONS = 58066 +const LINEAR = 58067 +const RANGE = 58068 +const LIST = 58069 +const SUBPARTITION = 58070 +const SUBPARTITIONS = 58071 +const HASH = 58072 var yyToknames = [...]string{ "$end", @@ -764,6 +772,7 @@ var yyToknames = [...]string{ "FUNCTION_CALL_NON_KEYWORD", "STRING_TYPE_PREFIX_NON_KEYWORD", "ANY_SOME", + "SELECT_OPTIONS", "LEX_ERROR", "UNION", "SELECT", @@ -826,6 +835,9 @@ var yyToknames = [...]string{ "SQL_NO_CACHE", "SQL_CACHE", "SQL_CALC_FOUND_ROWS", + "SQL_SMALL_RESULT", + "SQL_BIG_RESULT", + "HIGH_PRIORITY", "JOIN", "STRAIGHT_JOIN", "LEFT", @@ -850,6 +862,7 @@ var yyToknames = [...]string{ "','", "')'", "STRING", + "SQL_BUFFER_RESULT", "ID", "AT_ID", "AT_AT_ID", @@ -877,6 +890,8 @@ var yyToknames = [...]string{ "JSON_OVERLAPS", "JSON_SEARCH", "JSON_VALUE", + "JSON_ARRAYAGG", + "JSON_OBJECTAGG", "EXTRACT", "NULL", "UNKNOWN", @@ -1134,6 +1149,7 @@ var yyToknames = [...]string{ "MULTIPOLYGON", "ASCII", "UNICODE", + "VECTOR", "NULLX", "AUTO_INCREMENT", "APPROXNUM", @@ -1510,4493 +1526,1168 @@ var yyExca = [...]int{ 1, -1, -2, 0, -1, 2, - 15, 49, 16, 49, + 17, 49, -2, 40, -1, 52, 1, 157, - 740, 157, + 748, 157, -2, 165, -1, 53, - 141, 165, - 183, 165, - 353, 165, - -2, 523, + 148, 165, + 190, 165, + 360, 165, + -2, 524, -1, 61, - 37, 777, - 246, 777, - 257, 777, - 292, 791, - 293, 791, - -2, 779, + 38, 782, + 253, 782, + 264, 782, + 299, 796, + 300, 796, + -2, 784, -1, 66, - 248, 815, - -2, 813, + 255, 820, + -2, 818, -1, 122, - 245, 1606, + 252, 1617, -2, 131, -1, 124, 1, 158, - 740, 158, + 748, 158, -2, 165, -1, 135, - 142, 408, - 251, 408, - -2, 512, + 149, 409, + 258, 409, + -2, 513, -1, 154, - 141, 165, - 183, 165, - 353, 165, - -2, 532, - -1, 739, - 169, 41, + 148, 165, + 190, 165, + 360, 165, + -2, 533, + -1, 744, + 176, 41, -2, 43, - -1, 946, - 91, 1623, - -2, 1467, - -1, 947, - 91, 1624, - 228, 1628, - -2, 1468, - -1, 948, - 228, 1627, + -1, 953, + 95, 1634, + -2, 1478, + -1, 954, + 95, 1635, + 235, 1639, + -2, 1479, + -1, 955, + 235, 1638, -2, 42, - -1, 1032, - 64, 887, - -2, 900, - -1, 1120, - 256, 1096, - 261, 1096, - -2, 419, - -1, 1205, - 1, 580, - 740, 580, - -2, 165, - -1, 1509, - 228, 1628, - -2, 1468, - -1, 1720, - 64, 888, - -2, 904, - -1, 1721, - 64, 889, + -1, 1039, + 65, 892, -2, 905, - -1, 1777, - 141, 165, - 183, 165, - 353, 165, - -2, 458, - -1, 1858, - 142, 408, - 251, 408, - -2, 512, - -1, 1867, - 256, 1097, - 261, 1097, + -1, 1127, + 263, 1105, + 268, 1105, -2, 420, - -1, 2310, - 228, 1632, - -2, 1626, - -1, 2311, - 228, 1628, - -2, 1624, - -1, 2414, - 141, 165, - 183, 165, - 353, 165, + -1, 1212, + 1, 581, + 748, 581, + -2, 165, + -1, 1520, + 235, 1639, + -2, 1479, + -1, 1733, + 65, 893, + -2, 909, + -1, 1734, + 65, 894, + -2, 910, + -1, 1794, + 148, 165, + 190, 165, + 360, 165, -2, 459, - -1, 2421, - 27, 186, + -1, 1876, + 149, 409, + 258, 409, + -2, 513, + -1, 1885, + 263, 1106, + 268, 1106, + -2, 421, + -1, 2333, + 235, 1643, + -2, 1637, + -1, 2334, + 235, 1639, + -2, 1635, + -1, 2437, + 148, 165, + 190, 165, + 360, 165, + -2, 460, + -1, 2444, + 28, 186, -2, 188, - -1, 2878, - 82, 96, - 92, 96, - -2, 963, - -1, 2947, - 715, 700, - -2, 674, - -1, 3169, - 54, 1571, - -2, 1565, - -1, 4003, - 715, 700, - -2, 688, - -1, 4095, - 94, 632, - 99, 632, - 109, 632, - 185, 632, - 186, 632, - 187, 632, - 188, 632, - 189, 632, - 190, 632, - 191, 632, - 192, 632, - 193, 632, - 194, 632, - 195, 632, - 196, 632, - 197, 632, - 198, 632, - 199, 632, - 200, 632, - 201, 632, - 202, 632, - 203, 632, - 204, 632, - 205, 632, - 206, 632, - 207, 632, - 208, 632, - 209, 632, - 210, 632, - 211, 632, - 212, 632, - 213, 632, - 214, 632, - 215, 632, - 216, 632, - 217, 632, - 218, 632, - 219, 632, - 220, 632, - 221, 632, - 222, 632, - 223, 632, - 224, 632, - 225, 632, - 226, 632, - -2, 1998, + -1, 2906, + 86, 96, + 96, 96, + -2, 972, + -1, 2975, + 723, 702, + -2, 676, + -1, 3199, + 55, 1582, + -2, 1576, + -1, 4037, + 723, 702, + -2, 690, + -1, 4129, + 98, 634, + 104, 634, + 114, 634, + 192, 634, + 193, 634, + 194, 634, + 195, 634, + 196, 634, + 197, 634, + 198, 634, + 199, 634, + 200, 634, + 201, 634, + 202, 634, + 203, 634, + 204, 634, + 205, 634, + 206, 634, + 207, 634, + 208, 634, + 209, 634, + 210, 634, + 211, 634, + 212, 634, + 213, 634, + 214, 634, + 215, 634, + 216, 634, + 217, 634, + 218, 634, + 219, 634, + 220, 634, + 221, 634, + 222, 634, + 223, 634, + 224, 634, + 225, 634, + 226, 634, + 227, 634, + 228, 634, + 229, 634, + 230, 634, + 231, 634, + 232, 634, + 233, 634, + -2, 2014, } const yyPrivate = 57344 -const yyLast = 56205 +const yyLast = 56304 var yyAct = [...]int{ - 962, 3656, 3657, 87, 3655, 950, 4074, 4183, 4093, 4170, - 3984, 3221, 3321, 3966, 2117, 4137, 1273, 957, 3606, 949, - 2105, 4062, 4138, 3228, 2339, 3270, 3456, 2411, 3889, 3279, - 3182, 3284, 3281, 3964, 3037, 3280, 3278, 1271, 3283, 1780, - 3593, 3282, 2341, 3299, 3120, 2485, 1987, 3236, 3298, 743, - 2043, 3186, 3183, 5, 3502, 1736, 3698, 3011, 3180, 3496, - 2838, 2366, 737, 3301, 3170, 3036, 2448, 738, 3486, 2912, - 3328, 1836, 911, 2993, 771, 2944, 4035, 910, 2473, 2453, - 2913, 915, 2914, 2399, 42, 2516, 1030, 2382, 87, 163, - 2387, 2385, 1050, 1082, 1027, 1883, 2386, 1057, 2863, 2814, - 2830, 41, 1128, 43, 2295, 1152, 2263, 1030, 3524, 2139, - 2101, 2985, 2494, 149, 2051, 2262, 2472, 2374, 1865, 2533, - 2455, 2905, 1092, 1115, 1110, 2851, 1769, 2880, 1749, 1522, - 100, 2844, 2389, 1701, 2145, 104, 2076, 105, 2065, 1447, - 1432, 1872, 1983, 1089, 1086, 1964, 2470, 753, 1121, 3185, - 1090, 2444, 2445, 1116, 1117, 1768, 748, 1039, 1067, 1069, - 1118, 1754, 1723, 2153, 3693, 2172, 2812, 1029, 99, 1033, - 1505, 1481, 1036, 107, 2042, 85, 1261, 1995, 167, 1049, - 127, 125, 3685, 126, 2367, 3457, 1857, 3513, 1052, 1034, - 912, 1035, 1025, 132, 133, 1201, 1062, 747, 1037, 741, - 1526, 740, 98, 4171, 93, 1247, 1269, 2487, 2488, 2489, - 1061, 3594, 84, 3267, 2487, 1531, 4019, 2967, 2966, 106, - 2935, 2531, 1024, 3586, 3549, 4120, 730, 3001, 3002, 4015, - 1042, 128, 2336, 2337, 4014, 2058, 2057, 2056, 2055, 1132, - 134, 2054, 4020, 1083, 1157, 2053, 675, 2026, 1217, 672, - 1218, 673, 4114, 2810, 2581, 3166, 4141, 1154, 2520, 3124, - 3660, 1165, 4193, 3660, 4136, 4161, 3460, 2363, 3459, 1043, - 1171, 1172, 1173, 1076, 1176, 1177, 1178, 1179, 2, 2362, - 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, - 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1131, 1028, 731, - 95, 1077, 2519, 128, 1026, 1106, 1105, 95, 1104, 3993, - 1464, 1051, 1740, 1107, 2960, 2937, 1158, 1161, 1162, 2840, - 1730, 3289, 3967, 111, 112, 113, 2079, 116, 1099, 1443, - 122, 3289, 1949, 191, 1738, 4015, 667, 1094, 3347, 2360, - 95, 2775, 1741, 709, 3286, 4176, 715, 1023, 728, 729, - 3659, 190, 1174, 3659, 2063, 4089, 4124, 4122, 1018, 1019, - 1020, 1021, 916, 715, 1739, 1032, 1075, 1079, 914, 2957, - 4175, 128, 190, 95, 129, 3885, 3884, 3287, 1075, 1079, - 914, 4123, 4121, 3599, 1156, 1108, 3600, 3287, 1155, 4151, - 172, 3895, 4118, 1064, 1065, 129, 1434, 965, 966, 967, - 965, 966, 967, 3618, 3293, 86, 3607, 1460, 2588, 709, - 4063, 172, 709, 86, 3293, 4071, 2513, 3894, 2110, 86, - 4098, 3373, 1846, 2889, 709, 1770, 2888, 1771, 2854, 2890, - 3218, 3219, 2811, 2894, 2406, 2407, 2035, 2036, 3217, 3000, - 2585, 2405, 1254, 2984, 1256, 1237, 169, 1016, 4075, 170, - 2518, 1461, 706, 1462, 1463, 1015, 2855, 1266, 4103, 1098, - 1242, 1243, 1100, 1225, 3712, 3617, 1225, 169, 1226, 2938, - 170, 1226, 3985, 189, 1238, 2586, 4101, 1231, 2901, 1224, - 1991, 1223, 1253, 1255, 709, 95, 4107, 4108, 3325, 3998, - 2424, 2423, 709, 95, 189, 3238, 3239, 3323, 709, 95, - 691, 3355, 4102, 2847, 2848, 2338, 1103, 3353, 1210, 1211, - 4142, 2579, 86, 689, 709, 88, 2034, 1482, 3290, 1766, - 1200, 723, 2181, 721, 4079, 2038, 1175, 4079, 3290, 3058, - 727, 4143, 1444, 3329, 1705, 2370, 2986, 2495, 1939, 3344, - 1213, 1483, 1484, 1485, 1486, 1487, 1488, 1489, 1491, 1490, - 1492, 1493, 3937, 686, 3938, 710, 2534, 2370, 2538, 1433, - 2945, 1103, 701, 1095, 1101, 1244, 3316, 1265, 2970, 1239, - 1097, 1096, 1232, 1264, 3317, 1245, 2540, 696, 2582, 1263, - 2583, 3326, 1940, 4173, 1941, 1258, 1965, 173, 699, 1251, - 3324, 3588, 95, 1252, 1068, 1246, 179, 1240, 1241, 2464, - 2537, 1206, 2988, 1257, 3237, 3587, 2536, 2560, 173, 1181, - 2974, 2975, 1180, 2539, 3869, 3584, 3240, 179, 1992, 1101, - 2173, 710, 2458, 1111, 710, 2175, 1708, 1112, 1250, 2180, - 2176, 2541, 3240, 2177, 2178, 2179, 710, 2498, 2174, 2182, - 2183, 2184, 2185, 2186, 2187, 2188, 2189, 2190, 2557, 3664, - 2558, 4115, 2559, 2383, 1496, 1112, 676, 1150, 678, 692, - 1149, 712, 1148, 711, 682, 1147, 680, 684, 693, 685, - 3123, 679, 1146, 690, 1145, 1850, 681, 694, 695, 698, - 702, 703, 704, 700, 697, 3499, 688, 713, 1078, 1072, - 1070, 1144, 1143, 1102, 1138, 3059, 710, 1151, 1087, 4194, - 1078, 1072, 1070, 1124, 710, 4148, 1270, 1087, 1270, 1270, - 710, 2547, 2543, 2545, 2546, 2544, 2548, 2549, 2550, 1087, - 1123, 164, 1984, 1085, 2471, 1160, 710, 1063, 2368, 2369, - 3583, 1123, 2989, 2524, 2523, 1159, 1980, 1435, 1168, 3260, - 3005, 2969, 164, 1844, 1843, 1842, 4116, 1767, 1102, 2955, - 2368, 2369, 1981, 1840, 1216, 666, 1030, 1506, 1511, 1512, - 3980, 1515, 1517, 1518, 1519, 1520, 1521, 2939, 1524, 1525, - 1527, 1527, 2457, 1527, 1527, 1532, 1532, 1532, 1535, 1536, - 1537, 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1546, - 1547, 1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556, - 1557, 1558, 1559, 1560, 1561, 1562, 1563, 1564, 1565, 1566, - 1567, 1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, - 1577, 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, - 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1596, - 1597, 1598, 1599, 1600, 1601, 1602, 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, - 4038, 1259, 1448, 1503, 1657, 3992, 1659, 1660, 1661, 1662, - 1663, 2936, 3547, 3548, 1426, 1427, 1109, 963, 1532, 1532, - 1532, 1532, 1532, 1532, 963, 3658, 2517, 1221, 3658, 1227, - 1228, 1229, 1230, 1670, 1671, 1672, 1673, 1674, 1675, 1676, - 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1507, 1425, 1499, - 1500, 1501, 1502, 1267, 1268, 1448, 3345, 963, 2972, 1513, - 165, 1141, 714, 1516, 1698, 1071, 2903, 177, 2587, 2959, - 3616, 1528, 4077, 1529, 1530, 4077, 89, 1071, 1139, 94, - 1496, 165, 1442, 707, 3444, 3500, 4106, 94, 177, 3291, - 3292, 1533, 1534, 94, 1130, 1204, 1212, 1222, 708, 3291, - 3292, 1970, 3295, 3012, 4076, 1209, 2586, 4076, 185, 2992, - 1458, 2515, 3295, 2958, 1871, 1969, 2983, 1130, 1704, 2982, - 1951, 1950, 1952, 1953, 1954, 3132, 1130, 1030, 3538, 185, - 4105, 1030, 1497, 1498, 1729, 3224, 3520, 1030, 2885, 2815, - 2817, 2850, 2787, 1235, 1695, 2113, 1758, 124, 1658, 1215, - 3131, 166, 171, 168, 174, 175, 176, 178, 180, 181, - 182, 183, 2845, 1458, 1696, 674, 2603, 184, 186, 187, - 188, 1167, 166, 171, 168, 174, 175, 176, 178, 180, - 181, 182, 183, 3225, 2412, 1496, 94, 3014, 184, 186, - 187, 188, 1493, 3216, 2614, 1476, 1046, 1129, 1262, 2081, - 1730, 4006, 2461, 4187, 1248, 3032, 1996, 3227, 1712, 1153, - 1142, 3579, 1716, 2082, 1494, 1495, 2080, 2146, 1029, 1454, - 1129, 119, 1714, 1870, 1715, 3222, 104, 1140, 105, 1129, - 2154, 1220, 1696, 1664, 1665, 1666, 1667, 1668, 1669, 3512, - 2535, 1464, 2047, 2462, 3238, 3239, 1977, 2155, 1702, 1772, - 2460, 3223, 2928, 1103, 1199, 1689, 4152, 1130, 3024, 3023, - 3022, 3151, 3707, 3016, 107, 3020, 1966, 3015, 1967, 3013, - 3149, 1968, 1454, 2995, 3018, 1446, 2995, 2146, 2994, 2623, - 2614, 2994, 1463, 3017, 2463, 3229, 1464, 1130, 1488, 1489, - 1491, 1490, 1492, 1493, 2459, 120, 1130, 1462, 1463, 3554, - 3553, 3019, 3021, 1732, 1464, 1710, 2502, 1880, 1130, 2816, - 1879, 2514, 1863, 1847, 1848, 1849, 1869, 1973, 1203, 1971, - 1972, 1713, 1974, 1975, 1976, 3362, 2512, 1934, 1856, 1873, - 1873, 1711, 1989, 1130, 1885, 2510, 1886, 1735, 1888, 1890, - 1205, 1699, 1894, 1896, 1898, 1900, 1902, 1875, 1026, 1028, - 1801, 1141, 1234, 3237, 2507, 1249, 1916, 1997, 1270, 2137, - 1129, 1763, 1764, 1236, 2140, 3240, 1123, 1126, 1127, 1874, - 1087, 1831, 2507, 1139, 1120, 1124, 4144, 4039, 1219, 2152, - 1924, 1925, 1461, 3539, 1462, 1463, 1930, 1931, 1041, 1839, - 1129, 3034, 1166, 1730, 2511, 1119, 1163, 1464, 4195, 1129, - 1853, 965, 966, 967, 1133, 1123, 1866, 1854, 1852, 1135, - 1717, 1129, 2509, 1136, 1134, 4189, 715, 1123, 1126, 1127, - 3877, 1087, 1877, 4040, 1202, 1120, 1124, 1461, 4185, 1462, - 1463, 4186, 3876, 4184, 1137, 3972, 1129, 3867, 3630, 733, - 1102, 1133, 1123, 1959, 1464, 1461, 1135, 1462, 1463, 1912, - 1136, 1134, 1915, 1920, 1917, 1985, 3629, 2129, 2118, 2119, - 2120, 2121, 2131, 2122, 2123, 2124, 2136, 2132, 2125, 2126, - 2133, 2134, 2135, 2127, 2128, 2130, 3561, 3613, 1845, 3614, - 3560, 3973, 3226, 2300, 128, 3899, 1106, 1105, 4196, 1104, - 1484, 1485, 1486, 1487, 1488, 1489, 1491, 1490, 1492, 1493, - 1789, 1486, 1487, 1488, 1489, 1491, 1490, 1492, 1493, 3550, - 1958, 2002, 1957, 1946, 3268, 1453, 1450, 1451, 1452, 1457, - 1459, 1456, 2612, 1455, 1730, 1270, 1270, 3256, 2910, 1998, - 1999, 2151, 2611, 1449, 2909, 2024, 2908, 2467, 1461, 87, - 1462, 1463, 87, 2003, 2069, 2070, 2593, 2594, 1960, 1944, - 2010, 2011, 2012, 1483, 1484, 1485, 1486, 1487, 1488, 1489, - 1491, 1490, 1492, 1493, 2023, 1464, 3544, 715, 1453, 1450, - 1451, 1452, 1457, 1459, 1456, 1482, 1455, 3004, 2658, 1956, - 1945, 1943, 2000, 1942, 1802, 1461, 1449, 1462, 1463, 2004, - 1932, 2006, 2007, 2008, 2009, 1926, 1923, 1922, 2013, 1483, - 1484, 1485, 1486, 1487, 1488, 1489, 1491, 1490, 1492, 1493, - 2025, 1921, 1482, 1892, 1709, 2108, 2108, 2106, 2106, 2109, - 42, 3320, 1429, 42, 1470, 1471, 1472, 1473, 1474, 1475, - 1469, 1466, 2892, 715, 2662, 2071, 1483, 1484, 1485, 1486, - 1487, 1488, 1489, 1491, 1490, 1492, 1493, 1815, 1818, 1819, - 1820, 1821, 1822, 1823, 1730, 1824, 1825, 1827, 1828, 1826, - 1829, 1830, 1803, 1804, 1805, 1806, 1787, 1788, 1816, 2192, - 1790, 1766, 1791, 1792, 1793, 1794, 1795, 1796, 1797, 1798, - 1799, 2836, 4172, 1800, 1807, 1808, 1809, 1810, 101, 1811, - 1812, 1813, 1814, 4145, 2069, 2070, 2067, 2068, 102, 1695, - 4001, 1464, 2483, 2482, 2481, 2480, 1461, 4000, 1462, 1463, - 1464, 85, 2479, 2478, 85, 1482, 2048, 2602, 1464, 1696, - 2066, 3976, 1743, 3975, 3230, 2078, 2375, 2376, 3234, 2141, - 3974, 2031, 2032, 1482, 3872, 3233, 1478, 1464, 1479, 1483, - 1484, 1485, 1486, 1487, 1488, 1489, 1491, 1490, 1492, 1493, - 2083, 1464, 1480, 1494, 1495, 1477, 1730, 1483, 1484, 1485, - 1486, 1487, 1488, 1489, 1491, 1490, 1492, 1493, 1744, 3235, - 4132, 1730, 2836, 1730, 3231, 2310, 3856, 2112, 3855, 3232, - 2085, 2084, 2214, 2086, 2087, 2088, 2089, 2090, 2091, 2093, - 2095, 2096, 2097, 2098, 2099, 2100, 2308, 1507, 4157, 1730, - 2156, 2157, 2158, 2159, 1482, 2309, 4155, 1730, 1460, 1730, - 2660, 2836, 4070, 2298, 2170, 2147, 2836, 4049, 1730, 2191, - 1460, 1730, 3994, 2296, 3706, 4085, 1730, 1464, 1483, 1484, - 1485, 1486, 1487, 1488, 1489, 1491, 1490, 1492, 1493, 4083, - 1730, 3904, 1461, 1464, 1462, 1463, 2836, 4045, 3903, 3957, - 1730, 1461, 2300, 1462, 1463, 1464, 2297, 3597, 3991, 1461, - 1464, 1462, 1463, 110, 2391, 2299, 2206, 2307, 3880, 1730, - 2313, 2314, 2836, 3868, 109, 2310, 108, 1464, 1461, 961, - 1462, 1463, 3704, 3626, 103, 1464, 1694, 1693, 104, 1692, - 105, 3558, 1461, 1464, 1462, 1463, 2308, 3597, 1730, 1817, - 1464, 2836, 3595, 3511, 3543, 2380, 2507, 1730, 2421, 104, - 3330, 105, 3518, 1730, 2343, 4081, 1730, 2355, 1464, 2742, - 1730, 3860, 1464, 101, 3327, 3259, 1464, 3258, 2919, 103, - 2906, 3950, 1730, 102, 3249, 3248, 1092, 3246, 3247, 3859, - 2077, 3244, 3245, 3948, 1730, 2393, 1730, 3515, 3945, 1730, - 3244, 3243, 3605, 2430, 2431, 2432, 2433, 2425, 1464, 2426, - 2427, 2428, 2429, 1042, 1464, 2331, 1730, 2415, 1461, 1092, - 1462, 1463, 2416, 3927, 1730, 2436, 2437, 2438, 2439, 2397, - 1691, 3485, 1730, 1464, 1461, 2356, 1462, 1463, 3478, 1730, - 2946, 1730, 2358, 2349, 1684, 2350, 1461, 2450, 1462, 1463, - 2570, 1461, 2419, 1462, 1463, 2569, 3475, 1730, 2496, 1464, - 3473, 1730, 3514, 2456, 3436, 1730, 2924, 2378, 1461, 2529, - 1462, 1463, 1076, 2403, 2402, 2401, 1461, 110, 1462, 1463, - 2860, 1730, 2418, 2417, 1461, 2528, 1462, 1463, 109, 2881, - 108, 1461, 2365, 1462, 1463, 1464, 3434, 1730, 2586, 2968, - 1077, 2344, 3430, 1730, 2466, 1464, 2493, 1835, 2949, 1461, - 1464, 1462, 1463, 1461, 1132, 1462, 1463, 1461, 103, 1462, - 1463, 3427, 1730, 1464, 1873, 2027, 2451, 2440, 2442, 2443, - 2447, 2942, 2943, 2836, 2835, 2469, 2465, 1993, 2501, 1955, - 1464, 2504, 2477, 2505, 1464, 2111, 1730, 3425, 1730, 1461, - 1947, 1462, 1463, 1464, 2882, 1461, 2881, 1462, 1463, 2521, - 1730, 2451, 2500, 2503, 2884, 2499, 2852, 1937, 1464, 1933, - 1929, 1928, 1131, 1927, 1461, 1464, 1462, 1463, 1745, 2522, - 1730, 2525, 1464, 3423, 1730, 2526, 2527, 1464, 2619, 1260, - 2833, 1835, 1834, 3421, 1730, 1778, 1777, 3181, 3419, 1730, - 1461, 1464, 1462, 1463, 103, 2852, 1464, 3211, 3511, 1460, - 1464, 3417, 1730, 2420, 2591, 1464, 4033, 2586, 4005, 1731, - 1733, 2882, 2836, 1030, 1030, 1030, 2860, 2532, 3415, 1730, - 2508, 2586, 3413, 1730, 109, 3464, 1461, 3246, 1462, 1463, - 2860, 3411, 1730, 1517, 1464, 1517, 1461, 3154, 1462, 1463, - 2859, 1461, 1464, 1462, 1463, 2404, 3409, 1730, 2742, 2647, - 2646, 2606, 2507, 2618, 1461, 2831, 1462, 1463, 2490, 2373, - 3407, 1730, 1734, 1464, 2563, 3405, 1730, 1464, 2334, 3511, - 2310, 1461, 3562, 1462, 1463, 1461, 2111, 1462, 1463, 3403, - 1730, 2507, 2049, 1464, 1461, 4146, 1462, 1463, 3401, 1730, - 2033, 2609, 1979, 3399, 1730, 1460, 1765, 1114, 2860, 1461, - 2309, 1462, 1463, 1464, 1031, 1113, 1461, 1464, 1462, 1463, - 1908, 1464, 95, 1461, 2578, 1462, 1463, 4111, 1461, 1464, - 1462, 1463, 3397, 1730, 4052, 3891, 3563, 3564, 3565, 2584, - 3383, 1730, 1461, 1737, 1462, 1463, 3857, 1461, 3719, 1462, - 1463, 1461, 2650, 1462, 1463, 2592, 1461, 3578, 1462, 1463, - 1464, 3360, 1730, 3575, 1464, 2807, 1730, 2598, 3556, 3378, - 2595, 2596, 2597, 3377, 1909, 1910, 1911, 1697, 2078, 1837, - 2915, 2805, 1730, 2449, 3318, 1461, 3273, 1462, 1463, 3269, - 2950, 2446, 2441, 1461, 95, 1462, 1463, 1464, 2435, 2572, - 2573, 2780, 1730, 2434, 2575, 2757, 1730, 1464, 3271, 2749, - 1730, 1464, 1962, 2576, 1461, 1868, 1462, 1463, 1461, 1864, - 1462, 1463, 1833, 1464, 121, 3566, 2916, 1204, 3322, 2622, - 3892, 2916, 2600, 2599, 1461, 2601, 1462, 1463, 1904, 3525, - 3526, 1464, 3531, 2464, 2604, 2347, 2605, 1464, 2740, 1730, - 2029, 4167, 2607, 3989, 1461, 1464, 1462, 1463, 1461, 2786, - 1462, 1463, 1461, 4165, 1462, 1463, 4139, 4013, 1464, 3932, - 1461, 3528, 1462, 1463, 1742, 3567, 3568, 3569, 2774, 2656, - 3265, 1464, 3264, 3263, 4009, 2738, 1730, 1464, 1905, 1906, - 1907, 2818, 3181, 1482, 2929, 2725, 1730, 2564, 671, 2723, - 1730, 1461, 3530, 1462, 1463, 1461, 1464, 1462, 1463, 3200, - 1030, 2721, 1730, 2108, 2030, 2106, 2821, 1483, 1484, 1485, - 1486, 1487, 1488, 1489, 1491, 1490, 1492, 1493, 3199, 2719, - 1730, 1464, 3203, 2857, 2858, 2819, 3864, 3204, 1461, 3893, - 1462, 1463, 2391, 2717, 1730, 1030, 2877, 2364, 1461, 1044, - 1462, 1463, 1461, 2353, 1462, 1463, 2715, 1730, 2822, 3205, - 2824, 2869, 2870, 3201, 1461, 3519, 1462, 1463, 3202, 2713, - 1730, 3159, 732, 3158, 3971, 2711, 1730, 2837, 3504, 1464, - 3697, 3699, 1461, 2856, 1462, 1463, 3503, 3507, 1461, 1464, - 1462, 1463, 3168, 2077, 2709, 1730, 1461, 1047, 1462, 1463, - 1045, 3171, 3173, 1464, 1978, 1048, 3684, 1014, 3683, 1461, - 3174, 1462, 1463, 3242, 42, 2899, 1464, 1702, 2809, 2707, - 1730, 1464, 1461, 2874, 1462, 1463, 2876, 1724, 1461, 2556, - 1462, 1463, 2920, 2875, 1056, 2829, 1464, 2555, 2902, 2904, - 2554, 1728, 2553, 1696, 1725, 2154, 1464, 1461, 1055, 1462, - 1463, 2846, 2849, 2552, 2895, 2551, 1747, 2834, 3682, 2954, - 3338, 2879, 2155, 2074, 2072, 2073, 1170, 2705, 1730, 2351, - 2352, 1727, 1461, 1726, 1462, 1463, 2883, 2703, 1730, 101, - 1169, 2886, 2915, 2456, 2998, 1724, 1464, 1428, 2893, 102, - 2896, 2701, 1730, 1464, 2956, 110, 2137, 1464, 129, 1728, - 3509, 103, 1725, 2965, 2699, 1730, 109, 2907, 108, 2697, - 1730, 4181, 2149, 2918, 3261, 2567, 103, 2150, 2921, 2922, - 1461, 4088, 1462, 1463, 1746, 2917, 1464, 1720, 1721, 1727, - 1461, 1726, 1462, 1463, 2695, 1730, 2925, 2375, 2376, 2926, - 3990, 2930, 2931, 2932, 1461, 1464, 1462, 1463, 2962, 108, - 1464, 3887, 3241, 2210, 1856, 1464, 2873, 1461, 2359, 1462, - 1463, 3487, 1461, 2590, 1462, 1463, 3956, 3955, 2610, 3008, - 3009, 2951, 2952, 109, 2693, 1730, 3935, 1461, 3705, 1462, - 1463, 2691, 1730, 3157, 2961, 2686, 1730, 1461, 3694, 1462, - 1463, 3156, 1464, 3703, 2129, 2118, 2119, 2120, 2121, 2131, - 2122, 2123, 2124, 2136, 2132, 2125, 2126, 2133, 2134, 2135, - 2127, 2128, 2130, 1464, 2682, 1730, 2987, 3702, 3695, 3025, - 3006, 3576, 3508, 3506, 1464, 3274, 2491, 1461, 2990, 1462, - 1463, 110, 1851, 2293, 1461, 1464, 1462, 1463, 1461, 3580, - 1462, 1463, 109, 2680, 1730, 1054, 3497, 2852, 4169, 4168, - 3043, 3044, 3045, 3046, 3047, 3048, 3049, 3050, 3051, 3052, - 3668, 1464, 101, 2325, 2963, 110, 1464, 1461, 103, 1462, - 1463, 2833, 102, 3026, 4168, 1464, 109, 3060, 108, 4169, - 3533, 1731, 2332, 2648, 2345, 1759, 1461, 1751, 1462, 1463, - 3977, 1461, 3542, 1462, 1463, 3, 1461, 97, 1462, 1463, - 1464, 2673, 1730, 1, 1464, 114, 115, 2046, 2044, 1022, - 10, 9, 2671, 1730, 1431, 2045, 1430, 2357, 8, 3546, - 4100, 3062, 687, 3480, 2335, 1700, 3118, 2996, 4140, 4096, - 2997, 4097, 1697, 1461, 1948, 1462, 1463, 1938, 3608, 2261, - 3888, 1464, 3277, 2497, 2865, 2868, 2869, 2870, 2866, 3476, - 2867, 2871, 3574, 3007, 1461, 2911, 1462, 1463, 3010, 2454, - 1122, 154, 3125, 3442, 2413, 1461, 3027, 1462, 1463, 2414, - 4065, 118, 1080, 117, 3127, 3136, 1461, 2204, 1462, 1463, - 1125, 2941, 1233, 2492, 2391, 1464, 3598, 3053, 3438, 2900, - 2422, 2298, 3375, 2298, 1784, 1464, 1782, 1783, 1781, 3098, - 1464, 2296, 1461, 2296, 1462, 1463, 3188, 1461, 87, 1462, - 1463, 2391, 2391, 2391, 2391, 2391, 1461, 1786, 1462, 1463, - 1785, 4037, 3346, 2468, 3108, 3109, 3110, 3111, 3112, 3374, - 2649, 2391, 3443, 3126, 2391, 3128, 2037, 722, 3136, 2872, - 3193, 1461, 716, 1462, 1463, 1461, 3135, 1462, 1463, 1464, - 192, 1773, 1989, 3210, 1752, 1164, 677, 2287, 2288, 2289, - 2290, 2291, 1464, 3147, 3153, 2393, 1464, 3250, 3148, 3150, - 3152, 2530, 1464, 3366, 2312, 3163, 1464, 2315, 2316, 3162, - 3160, 683, 1461, 3364, 1462, 1463, 1464, 1514, 2803, 1033, - 2028, 3155, 2393, 2393, 2393, 2393, 2393, 2887, 3294, 1074, - 1066, 2346, 3195, 3196, 3192, 3198, 3161, 3194, 3302, 1034, - 3197, 1035, 2393, 2333, 2823, 2393, 1073, 104, 3214, 105, - 3206, 3865, 3212, 3175, 3176, 3213, 1461, 3189, 1462, 1463, - 1464, 3501, 3167, 3169, 3220, 1464, 1461, 2802, 1462, 1463, - 2839, 1461, 3172, 1462, 1463, 3253, 3252, 3251, 1464, 3165, - 2798, 3970, 3696, 4050, 2797, 1464, 2897, 1748, 3463, 2621, - 2796, 2144, 1504, 1464, 2795, 2390, 3663, 2064, 745, 744, - 742, 3254, 3255, 1464, 2794, 2825, 2853, 1464, 2456, 3296, - 3306, 3178, 3303, 1468, 1464, 3307, 3275, 3313, 1467, 951, - 1461, 2813, 1462, 1463, 1760, 3184, 2864, 1464, 2862, 2861, - 3184, 2565, 2398, 1461, 3527, 1462, 1463, 1461, 3331, 1462, - 1463, 3334, 3523, 1461, 3333, 1462, 1463, 1461, 2793, 1462, - 1463, 4092, 3341, 2784, 2392, 2388, 2832, 1461, 902, 1462, - 1463, 901, 754, 3351, 3348, 3349, 2783, 3350, 746, 736, - 3352, 964, 3354, 2782, 3356, 900, 899, 3304, 3305, 2971, - 3319, 2781, 2973, 2898, 3367, 3368, 3369, 3370, 3371, 3315, - 1445, 2778, 1719, 1722, 2354, 2773, 1093, 3343, 3996, 2589, - 3372, 1461, 2766, 1462, 1463, 1718, 1461, 4003, 1462, 1463, - 1517, 3285, 3592, 3266, 1517, 2765, 3276, 2947, 2484, 1461, - 69, 1462, 1463, 46, 3965, 4034, 1461, 2608, 1462, 1463, - 3488, 2613, 3490, 894, 1461, 3458, 1462, 1463, 891, 3665, - 3666, 3667, 3462, 3121, 1461, 3122, 1462, 1463, 1461, 4016, - 1462, 1463, 4017, 890, 2616, 1461, 2617, 1462, 1463, 4018, - 2199, 1441, 2625, 1438, 4113, 2039, 2627, 2628, 1461, 96, - 1462, 1463, 36, 35, 34, 2634, 2635, 2636, 2637, 2638, - 2639, 2640, 2641, 2642, 2643, 3342, 2645, 33, 32, 26, - 25, 24, 2391, 23, 22, 29, 19, 3493, 3187, 3489, - 21, 3491, 20, 18, 3288, 3540, 3498, 4135, 1464, 2651, - 2652, 2653, 2654, 2655, 3505, 2657, 4180, 123, 55, 2659, - 1464, 3510, 52, 2664, 2665, 50, 2666, 3336, 3337, 2669, - 2670, 2672, 2674, 2675, 2676, 2677, 2678, 2679, 2681, 2683, - 2684, 2685, 2687, 3532, 2689, 2690, 2692, 2694, 2696, 2698, - 2700, 2702, 2704, 2706, 2708, 2710, 2712, 2714, 2716, 2718, - 2720, 2722, 2724, 2726, 2727, 2728, 3495, 2730, 3541, 2732, - 3297, 2734, 2735, 2393, 2737, 2739, 2741, 3306, 3534, 3303, - 2744, 734, 3307, 3535, 2748, 3557, 3529, 3559, 2753, 2754, - 2755, 2756, 1464, 131, 3602, 3603, 2764, 1464, 130, 3522, - 53, 2767, 2768, 2769, 2770, 2771, 2772, 1464, 2763, 2776, - 2777, 3465, 1464, 3467, 3468, 3469, 49, 2779, 3536, 3537, - 3551, 3552, 2785, 1207, 47, 1464, 31, 2788, 2789, 2790, - 2791, 2792, 1464, 30, 17, 16, 1464, 15, 2799, 2800, - 1464, 2801, 14, 13, 2804, 2806, 2357, 12, 2808, 1461, - 3604, 1462, 1463, 11, 7, 6, 39, 38, 2820, 37, - 28, 1461, 27, 1462, 1463, 40, 1464, 4, 2934, 2486, - 1464, 0, 0, 3585, 0, 0, 0, 3589, 3590, 3591, - 2762, 0, 0, 1464, 0, 2761, 0, 0, 0, 0, - 1053, 3620, 0, 1059, 1059, 2760, 0, 0, 2629, 1464, - 2759, 0, 0, 0, 0, 0, 1464, 0, 0, 0, - 0, 1464, 0, 2758, 0, 2644, 1464, 0, 0, 0, - 2752, 0, 0, 0, 2751, 0, 0, 1464, 2750, 0, - 0, 0, 1464, 1461, 0, 1462, 1463, 1464, 1461, 0, - 1462, 1463, 1464, 0, 0, 0, 0, 0, 1461, 0, - 1462, 1463, 0, 1461, 2747, 1462, 1463, 1464, 2746, 0, - 3671, 0, 3672, 3673, 3674, 0, 1461, 3681, 1462, 1463, - 3688, 2745, 3690, 1461, 1464, 1462, 1463, 1461, 0, 1462, - 1463, 1461, 3661, 1462, 1463, 0, 1464, 2743, 0, 0, - 0, 0, 0, 0, 2736, 3188, 0, 3691, 87, 2733, - 3188, 0, 0, 0, 2731, 0, 0, 1461, 0, 1462, - 1463, 1461, 0, 1462, 1463, 2729, 0, 0, 0, 0, - 2688, 0, 1464, 0, 1461, 2668, 1462, 1463, 0, 0, - 2667, 2108, 3625, 2106, 3721, 3692, 3701, 3700, 3711, 0, - 1461, 0, 1462, 1463, 3708, 2663, 3710, 1461, 3713, 1462, - 1463, 0, 1461, 0, 1462, 1463, 0, 1461, 0, 1462, - 1463, 0, 2661, 0, 0, 3871, 0, 0, 1461, 0, - 1462, 1463, 3725, 1461, 2626, 1462, 1463, 0, 1461, 42, - 1462, 1463, 0, 1461, 0, 1462, 1463, 0, 0, 0, - 0, 0, 0, 3581, 3582, 0, 0, 0, 1461, 0, - 1462, 1463, 3863, 0, 3862, 0, 3861, 0, 0, 0, - 2620, 0, 0, 0, 3878, 1461, 0, 1462, 1463, 0, - 0, 3883, 0, 3882, 0, 3890, 0, 1461, 0, 1462, - 1463, 0, 0, 0, 0, 0, 0, 3929, 3930, 0, - 3722, 3723, 0, 0, 3038, 3039, 3040, 3041, 3042, 3715, - 0, 0, 0, 3689, 0, 0, 0, 0, 2108, 0, - 2106, 3933, 0, 1461, 3057, 1462, 1463, 0, 0, 0, - 0, 0, 3873, 3874, 3875, 0, 0, 2865, 2868, 2869, - 2870, 2866, 3184, 2867, 2871, 0, 0, 3525, 3526, 0, - 3936, 0, 3978, 3188, 3939, 3717, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1535, 1536, 1537, - 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, - 1548, 1549, 1550, 1551, 1552, 1553, 1555, 1556, 1557, 1558, - 1559, 1560, 1561, 1562, 1563, 1564, 1565, 1566, 1567, 1568, - 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, - 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, - 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1596, 1597, 1598, - 1599, 1600, 1601, 1602, 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, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, - 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1653, 1654, - 1655, 1656, 1670, 1671, 1672, 1673, 1674, 1675, 1676, 1677, - 1678, 1679, 1680, 1681, 1682, 1683, 3934, 3963, 3962, 0, - 1464, 0, 3979, 0, 3953, 0, 0, 0, 0, 0, - 3997, 3959, 0, 3961, 0, 0, 0, 3187, 0, 0, - 3028, 0, 3187, 0, 0, 0, 0, 0, 87, 0, - 0, 0, 3190, 0, 0, 0, 0, 3982, 0, 0, - 0, 0, 0, 3981, 0, 0, 0, 0, 0, 0, - 3208, 0, 0, 0, 0, 3986, 3999, 0, 3866, 0, - 0, 4002, 0, 0, 0, 0, 0, 0, 4133, 0, - 0, 0, 0, 0, 0, 0, 0, 1801, 4004, 0, - 0, 0, 0, 0, 0, 0, 0, 3870, 2615, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, - 0, 4022, 0, 0, 4023, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4047, 0, 0, 0, - 0, 87, 0, 0, 0, 0, 0, 4032, 0, 0, - 0, 1461, 0, 1462, 1463, 0, 0, 0, 4041, 0, - 3100, 0, 3102, 0, 0, 0, 0, 0, 0, 4053, - 0, 0, 0, 0, 4078, 0, 0, 0, 3113, 3114, - 3115, 3116, 0, 4056, 4064, 4061, 4058, 1465, 3340, 4057, - 4055, 4051, 4060, 3890, 4067, 4059, 0, 4086, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 3983, - 3357, 3358, 4099, 3359, 3361, 3363, 0, 0, 1523, 0, - 0, 4091, 42, 4109, 4104, 3187, 0, 0, 0, 0, - 0, 4078, 4119, 4117, 0, 0, 0, 1789, 0, 4130, - 0, 3376, 0, 0, 0, 0, 3380, 3381, 3382, 3384, - 3385, 3386, 3387, 3388, 3389, 3390, 3391, 3392, 3393, 3394, - 3395, 3396, 3398, 3400, 3402, 3404, 3406, 3408, 3410, 3412, - 3414, 3416, 3418, 3420, 3422, 3424, 3426, 3428, 3429, 3431, - 3432, 3433, 3435, 1989, 4134, 3437, 4150, 3439, 3440, 3441, - 4153, 4160, 3445, 3446, 3447, 3448, 3449, 3450, 3451, 3452, - 3453, 3454, 3455, 2108, 4166, 2106, 4163, 4159, 4078, 4174, - 4164, 3461, 4162, 4149, 4129, 3466, 4048, 4043, 3184, 3470, - 3471, 1802, 3472, 3474, 4182, 3477, 3479, 4188, 3481, 3482, - 3483, 3484, 4190, 0, 0, 0, 0, 0, 3492, 0, - 0, 0, 0, 0, 0, 0, 0, 3988, 0, 4199, - 4200, 3930, 4198, 0, 0, 0, 0, 0, 0, 0, - 0, 2108, 0, 2106, 4197, 0, 0, 0, 0, 0, - 0, 0, 0, 3516, 3517, 0, 0, 3521, 0, 0, - 0, 4007, 3995, 0, 1815, 1818, 1819, 1820, 1821, 1822, - 1823, 0, 1824, 1825, 1827, 1828, 1826, 1829, 1830, 1803, - 1804, 1805, 1806, 1787, 1788, 1816, 0, 1790, 0, 1791, - 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 0, 0, - 1800, 1807, 1808, 1809, 1810, 0, 1811, 1812, 1813, 1814, - 0, 4125, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 4042, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 3596, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1750, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3615, 0, - 0, 3619, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1838, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3631, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 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, 4147, 0, 1697, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3654, 0, - 0, 0, 1012, 0, 2300, 0, 1817, 1013, 0, 0, - 0, 3662, 0, 0, 0, 0, 0, 2107, 3669, 0, - 0, 0, 0, 0, 0, 195, 0, 0, 195, 0, - 0, 0, 720, 0, 0, 0, 0, 726, 0, 0, - 0, 0, 1994, 0, 0, 0, 0, 0, 195, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 195, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 726, - 195, 726, 0, 970, 971, 972, 973, 974, 975, 976, - 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, - 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, - 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, - 1007, 1008, 1009, 1010, 1011, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 3879, 0, 0, - 0, 0, 0, 0, 0, 0, 3886, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3896, 3897, 3898, 0, - 3900, 0, 3901, 3902, 0, 0, 0, 3905, 3906, 3907, - 3908, 3909, 3910, 3911, 3912, 3913, 3914, 3915, 3916, 3917, - 3918, 3919, 3920, 3921, 3922, 3923, 3924, 3925, 3926, 0, - 3928, 3931, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 3652, 0, 0, 3940, 3941, 3942, 3943, - 3944, 3946, 3947, 3949, 3951, 3952, 3954, 0, 0, 0, - 3958, 0, 0, 0, 3960, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 3987, - 0, 0, 2059, 2060, 2061, 2062, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2075, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2114, 2115, 0, 0, 0, 0, 2138, - 0, 0, 2142, 2143, 0, 0, 0, 2148, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2160, 2161, 2162, 2163, 2164, 2165, 2166, 2167, - 2168, 2169, 0, 2171, 0, 0, 0, 2193, 2194, 2195, - 2196, 2197, 2198, 2200, 0, 2205, 0, 2207, 2208, 2209, - 0, 2211, 2212, 2213, 0, 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, 2264, 2265, 2266, 2267, 2268, 2269, 2270, 2271, 2272, - 2273, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2282, - 2283, 2284, 2285, 2286, 0, 0, 0, 0, 0, 2292, - 0, 2294, 0, 2301, 2302, 2303, 2304, 2305, 2306, 0, - 3969, 0, 0, 0, 4012, 0, 0, 0, 0, 0, - 0, 0, 2317, 2318, 2319, 2320, 2321, 2322, 2323, 2324, - 0, 2326, 2327, 2328, 2329, 2330, 0, 0, 4027, 0, - 0, 0, 0, 0, 4030, 0, 4031, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 86, 44, 45, 88, 4046, - 0, 1059, 0, 0, 0, 0, 0, 190, 0, 0, - 0, 0, 0, 0, 92, 0, 0, 0, 48, 76, - 77, 0, 74, 78, 0, 4072, 4073, 0, 2371, 2372, - 129, 0, 151, 0, 75, 0, 0, 0, 0, 4080, - 4082, 4084, 0, 0, 0, 0, 172, 0, 0, 0, - 0, 0, 0, 0, 2410, 0, 0, 4090, 0, 0, - 0, 0, 0, 62, 0, 0, 0, 0, 0, 4112, - 0, 0, 0, 0, 0, 95, 0, 162, 0, 0, - 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 195, 0, 195, 0, - 0, 0, 169, 0, 0, 170, 0, 4131, 0, 0, - 0, 0, 0, 0, 0, 2452, 1697, 0, 0, 0, - 0, 0, 83, 0, 0, 138, 139, 161, 160, 189, - 0, 0, 0, 0, 0, 726, 0, 726, 726, 0, - 0, 4154, 4156, 4158, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 726, 195, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 4011, 0, 4179, 0, 0, 0, 0, 0, - 4021, 0, 0, 0, 0, 0, 1509, 0, 0, 0, - 0, 0, 4191, 4192, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 51, 54, 57, 56, - 59, 0, 73, 1012, 0, 82, 79, 0, 1013, 0, - 155, 136, 158, 143, 135, 0, 156, 157, 2107, 0, - 0, 0, 1697, 173, 0, 0, 0, 0, 0, 61, - 91, 90, 179, 144, 71, 72, 58, 0, 0, 0, - 0, 0, 80, 81, 0, 0, 0, 147, 145, 140, - 141, 142, 146, 0, 0, 0, 0, 0, 0, 137, - 0, 0, 0, 0, 0, 0, 0, 0, 148, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 63, 64, 0, 65, 66, - 67, 68, 0, 0, 970, 971, 972, 973, 974, 975, - 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, - 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, - 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, - 1006, 1007, 1008, 1009, 1010, 1011, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, - 0, 0, 0, 0, 0, 0, 0, 164, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1509, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2624, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2630, 2631, - 2632, 2633, 0, 0, 0, 195, 0, 0, 0, 726, - 726, 0, 0, 0, 0, 0, 0, 0, 0, 89, - 0, 0, 0, 0, 0, 0, 0, 0, 195, 0, - 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, - 0, 1523, 0, 0, 0, 0, 0, 0, 0, 726, - 0, 0, 195, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 726, 0, 0, 0, 0, 0, - 0, 195, 0, 0, 0, 726, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 726, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 726, 0, - 726, 0, 0, 0, 0, 0, 0, 0, 726, 0, - 0, 1509, 726, 0, 0, 726, 726, 726, 726, 94, - 726, 0, 726, 726, 0, 726, 726, 726, 726, 726, - 726, 0, 152, 0, 0, 153, 0, 0, 1509, 726, - 726, 1509, 726, 1509, 195, 726, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 195, 0, 165, 0, 0, 0, - 0, 0, 0, 177, 0, 0, 0, 726, 0, 195, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 726, 0, 0, 726, 0, 195, 195, 0, 0, 0, - 0, 0, 0, 0, 0, 1750, 0, 0, 0, 0, - 0, 0, 195, 0, 185, 0, 0, 0, 0, 195, - 0, 0, 0, 0, 0, 0, 70, 0, 195, 195, - 195, 195, 195, 195, 195, 195, 195, 726, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 166, 171, 168, - 174, 175, 176, 178, 180, 181, 182, 183, 0, 0, - 0, 0, 0, 184, 186, 187, 188, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 726, 726, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 726, 0, 0, - 0, 0, 0, 3003, 0, 0, 195, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 3029, 3030, 3031, 0, 0, 3033, 0, 0, 3035, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 726, 0, 3054, 3055, - 3056, 0, 0, 0, 0, 0, 1509, 0, 0, 0, - 3061, 0, 0, 3063, 3064, 3065, 0, 0, 0, 3066, - 3067, 0, 0, 3068, 1509, 3069, 0, 0, 0, 0, - 0, 0, 3070, 0, 3071, 0, 0, 0, 3072, 0, - 3073, 0, 0, 3074, 0, 3075, 0, 3076, 0, 3077, - 0, 3078, 0, 3079, 0, 3080, 0, 3081, 0, 3082, - 0, 3083, 0, 3084, 0, 3085, 0, 3086, 0, 3087, - 0, 3088, 0, 3089, 0, 3090, 0, 3091, 0, 0, - 0, 3092, 0, 3093, 0, 3094, 0, 0, 3095, 0, - 3096, 0, 3097, 0, 2264, 3099, 0, 0, 3101, 0, - 0, 3103, 3104, 3105, 3106, 0, 0, 0, 0, 3107, - 2264, 2264, 2264, 2264, 2264, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3117, 0, 0, 0, 0, - 0, 0, 0, 3130, 0, 0, 3134, 0, 0, 0, - 0, 0, 0, 0, 0, 3137, 3138, 3139, 3140, 3141, - 3142, 0, 0, 0, 3143, 3144, 0, 3145, 2311, 3146, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1059, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 195, 3179, 0, 0, 0, 726, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 190, 0, 3209, - 0, 0, 0, 0, 195, 0, 0, 726, 2940, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 129, 195, 151, 0, 0, 726, 0, 0, 2311, 195, - 0, 195, 0, 195, 195, 0, 172, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 726, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 3272, 0, 0, 0, 0, 0, 0, 162, 0, 0, - 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 169, 0, 0, 170, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 726, 0, 0, 0, 0, - 0, 0, 726, 726, 726, 1859, 1860, 161, 160, 189, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 726, 0, 0, 0, 0, 0, 726, 726, - 0, 0, 726, 0, 726, 0, 0, 0, 0, 0, - 726, 946, 0, 0, 0, 0, 3365, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3379, 0, 0, 726, 0, 0, 0, 0, - 726, 0, 0, 0, 726, 726, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 705, 0, 0, 0, 0, 0, 725, - 155, 1861, 158, 0, 1858, 0, 156, 157, 0, 0, - 0, 0, 195, 173, 0, 0, 0, 0, 0, 195, - 0, 0, 179, 0, 0, 0, 0, 0, 0, 195, - 195, 0, 0, 195, 0, 195, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 195, 0, 0, 0, 0, - 0, 725, 195, 725, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 195, 0, - 0, 0, 0, 0, 0, 0, 0, 726, 0, 0, - 903, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 164, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 724, 0, - 0, 1509, 0, 2311, 0, 0, 0, 0, 0, 0, - 0, 3577, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3601, 0, 0, 0, 0, 0, - 1084, 0, 1091, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3621, 0, 3622, 0, 3623, 0, 3624, 0, - 0, 0, 0, 0, 0, 0, 3627, 3628, 0, 0, - 0, 0, 0, 0, 0, 3632, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 3633, - 0, 3634, 0, 3635, 0, 3636, 0, 3637, 0, 3638, - 0, 3639, 0, 3640, 0, 3641, 0, 3642, 0, 3643, - 0, 3644, 0, 3645, 0, 3646, 0, 3647, 0, 3648, - 0, 0, 3649, 0, 0, 0, 3650, 0, 3651, 0, - 0, 0, 0, 0, 3653, 0, 0, 0, 0, 0, - 0, 0, 152, 0, 0, 153, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3670, 0, 0, 0, - 0, 0, 0, 0, 0, 3675, 0, 3676, 3677, 0, - 3678, 0, 3679, 0, 195, 0, 165, 3680, 0, 0, - 0, 0, 195, 177, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 726, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3709, 0, 0, 726, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 3718, 0, 0, - 3720, 0, 0, 0, 185, 0, 0, 0, 0, 0, - 0, 195, 3724, 0, 0, 0, 195, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3858, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 166, 171, 168, - 174, 175, 176, 178, 180, 181, 182, 183, 0, 0, - 0, 0, 0, 184, 186, 187, 188, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 726, 0, 0, 0, 0, 0, - 195, 0, 0, 0, 0, 0, 0, 195, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 726, 0, 0, 0, 0, 0, 0, 726, 0, - 0, 0, 726, 726, 0, 0, 0, 726, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1509, 726, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 195, 195, 195, 195, - 195, 195, 0, 0, 0, 0, 3968, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 195, 195, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 195, 725, 1424, 725, - 725, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 725, - 1703, 0, 726, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1508, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 726, 0, 0, 0, 0, 0, 0, 0, 0, 669, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1017, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1088, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1272, 0, 1272, 1272, - 0, 4010, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1436, 0, - 0, 0, 0, 0, 0, 726, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 726, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4024, 0, 0, - 4025, 0, 4026, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 726, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 195, 0, 0, 726, 0, 0, 1508, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 726, 0, 0, 0, 1509, 0, 0, 726, 726, 1509, - 195, 195, 195, 195, 195, 0, 0, 0, 0, 0, - 0, 0, 195, 0, 0, 0, 0, 0, 195, 0, - 195, 0, 0, 195, 195, 195, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 725, 725, 0, 4110, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, - 0, 0, 0, 4126, 0, 4127, 0, 4128, 0, 0, - 0, 725, 726, 0, 0, 1509, 0, 0, 0, 0, - 726, 0, 0, 0, 0, 195, 725, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 725, 0, 195, - 0, 0, 0, 0, 0, 0, 0, 725, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, - 0, 0, 195, 0, 0, 0, 0, 0, 0, 0, - 725, 0, 725, 0, 0, 0, 0, 4177, 0, 4178, - 725, 0, 0, 1508, 725, 0, 0, 725, 725, 725, - 725, 0, 725, 0, 725, 725, 0, 725, 725, 725, - 725, 725, 725, 0, 0, 0, 0, 0, 0, 0, - 1508, 725, 725, 1508, 725, 1508, 0, 725, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1706, 1707, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 725, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 725, 0, 0, 725, 0, 0, 0, 0, - 1756, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1774, 0, 0, 726, 0, - 0, 0, 0, 0, 0, 0, 1832, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1841, 0, 0, 725, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 195, 0, 0, 0, 1084, - 0, 1867, 0, 0, 0, 0, 0, 0, 0, 1876, - 0, 0, 0, 1878, 0, 0, 1881, 1882, 1884, 1884, - 0, 1884, 0, 1884, 1884, 0, 1893, 1884, 1884, 1884, - 1884, 1884, 0, 0, 0, 0, 0, 0, 0, 0, - 1913, 1914, 0, 1084, 0, 0, 1919, 0, 0, 0, - 0, 195, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1961, 0, - 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1982, 0, 0, 1986, 0, 0, 0, 0, 904, - 195, 0, 0, 195, 195, 195, 0, 0, 0, 0, - 0, 0, 0, 726, 726, 0, 0, 1208, 0, 1214, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1272, 0, - 0, 0, 0, 0, 0, 0, 725, 725, 0, 0, - 0, 0, 0, 0, 0, 193, 0, 0, 670, 725, - 0, 0, 726, 726, 726, 726, 190, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1855, 670, 1437, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, - 0, 151, 0, 0, 1040, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, - 0, 1060, 1060, 0, 0, 0, 0, 0, 725, 0, - 670, 0, 0, 0, 0, 0, 0, 0, 1508, 0, - 0, 0, 0, 0, 0, 0, 162, 2116, 0, 0, - 0, 0, 150, 0, 0, 0, 1508, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 169, 0, 0, 170, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1859, 1860, 161, 160, 189, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1272, 1272, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2040, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 726, 0, - 726, 0, 195, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1509, 0, 0, 0, 195, 0, 0, 726, 0, - 726, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2102, 0, 0, - 725, 0, 0, 0, 0, 0, 0, 0, 0, 155, - 1861, 158, 0, 1858, 0, 156, 157, 0, 0, 0, - 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, - 0, 179, 0, 0, 0, 0, 0, 0, 726, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 725, 195, 0, 0, 726, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 726, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 725, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 725, 0, 0, - 725, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 725, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1762, 0, 0, 0, 0, 0, 0, - 0, 726, 0, 0, 0, 0, 0, 0, 726, 0, - 726, 0, 1779, 0, 0, 0, 164, 0, 0, 1272, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 725, 0, 726, - 0, 0, 0, 0, 725, 725, 725, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 725, 0, 0, 0, 0, 2348, - 725, 725, 0, 0, 725, 0, 725, 0, 0, 0, - 0, 0, 725, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1918, 0, 0, 2361, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 159, 0, 0, 0, 1756, 725, 0, 1272, - 0, 0, 725, 0, 0, 0, 725, 725, 0, 0, - 1963, 0, 0, 0, 0, 0, 0, 0, 0, 1084, - 0, 0, 0, 0, 0, 0, 0, 1990, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2001, 0, 0, 0, 0, 0, 0, - 2005, 0, 0, 0, 0, 0, 0, 726, 0, 0, - 0, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 0, 0, - 0, 0, 0, 195, 0, 0, 1091, 0, 0, 0, - 0, 0, 0, 2474, 2475, 2476, 0, 0, 0, 0, - 0, 726, 195, 0, 0, 0, 0, 0, 0, 0, - 0, 152, 0, 1084, 153, 0, 0, 0, 0, 1091, - 1876, 0, 0, 1876, 0, 1876, 0, 0, 0, 725, - 0, 2506, 0, 0, 0, 0, 670, 0, 670, 0, - 0, 0, 0, 0, 0, 165, 0, 0, 0, 0, - 0, 0, 177, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1084, 726, 0, 0, - 0, 2102, 0, 0, 0, 2102, 2102, 726, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1509, 726, 0, - 726, 0, 0, 185, 0, 0, 0, 0, 670, 0, - 0, 0, 0, 1508, 0, 725, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 726, 2311, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1510, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 166, 171, 168, 174, - 175, 176, 178, 180, 181, 182, 183, 0, 0, 0, - 0, 0, 184, 186, 187, 188, 195, 726, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2052, 0, 0, - 0, 0, 0, 0, 0, 95, 0, 0, 1012, 0, - 0, 0, 952, 1013, 965, 966, 967, 953, 2580, 0, - 954, 955, 0, 956, 0, 0, 0, 726, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 961, 0, 968, - 969, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 726, 0, 0, 0, 0, 195, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 726, 0, 726, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 3308, 3309, 0, - 0, 0, 0, 0, 1272, 0, 0, 0, 0, 970, - 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, - 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, - 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, - 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, - 1011, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1510, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 725, 0, 0, 0, 0, - 0, 0, 3310, 0, 0, 0, 0, 0, 0, 725, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 670, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2891, 0, 0, 0, 1040, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 3311, 3312, 670, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 670, 0, 0, 0, 0, 725, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2377, 0, 0, 0, 0, 0, 0, 0, - 2381, 0, 2384, 725, 0, 2052, 0, 0, 0, 0, - 725, 0, 0, 0, 725, 725, 0, 0, 0, 725, - 0, 1510, 0, 0, 2826, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 917, 1508, 725, 0, 2841, 0, - 921, 0, 0, 0, 918, 919, 0, 0, 1510, 920, - 922, 1510, 0, 1510, 670, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1935, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 670, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1988, 670, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 670, 0, 725, 0, 0, 0, 0, 670, - 0, 0, 0, 0, 0, 2923, 0, 0, 2014, 2015, - 670, 670, 670, 670, 670, 670, 670, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2361, 0, 0, 0, 0, 0, 0, 2948, - 0, 0, 725, 1876, 1876, 0, 0, 0, 2953, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2964, 0, 0, 0, 0, - 0, 0, 0, 2052, 0, 0, 0, 0, 0, 0, - 2542, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2561, 2562, 0, 0, 2566, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 2571, 0, 0, 0, - 0, 0, 0, 2574, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 2577, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2102, 0, 0, 0, 725, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 725, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 725, 2102, 0, 0, 0, 0, 670, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 725, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 725, 0, 0, 0, 1508, 0, 0, 725, - 725, 1508, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1510, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1510, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3257, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3119, 0, 0, 0, - 0, 0, 0, 0, 725, 0, 0, 1508, 1272, 0, - 0, 0, 725, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1884, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 3164, 0, 0, - 0, 0, 0, 0, 3339, 0, 0, 0, 0, 0, - 0, 1272, 0, 0, 0, 0, 0, 0, 3191, 1884, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1988, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1935, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1060, - 0, 0, 0, 1084, 0, 0, 0, 0, 0, 0, - 0, 2361, 0, 0, 1040, 0, 0, 0, 0, 0, - 725, 0, 0, 0, 0, 0, 0, 2878, 0, 0, - 0, 670, 0, 0, 0, 0, 0, 0, 1988, 670, - 0, 670, 0, 670, 2400, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2927, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3545, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2976, 2977, 2978, - 2979, 2980, 2981, 0, 0, 725, 725, 0, 0, 1832, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2052, 2991, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2999, 0, 0, - 0, 0, 0, 0, 725, 725, 725, 725, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 670, 0, 0, 0, 0, 0, 0, 670, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 670, - 670, 0, 0, 670, 0, 2568, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 670, 0, 0, 0, 0, - 0, 0, 670, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 670, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2361, 2361, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 3609, 3610, 3611, 3612, 0, 0, 0, - 725, 1510, 725, 1988, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1508, 0, 0, 0, 0, 0, 0, - 725, 0, 725, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 725, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 725, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 725, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 3686, - 0, 3686, 0, 0, 0, 0, 0, 0, 0, 0, - 3262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 3714, - 0, 3716, 0, 725, 0, 0, 3300, 0, 0, 0, - 725, 0, 725, 0, 0, 0, 0, 0, 0, 0, - 3314, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 670, 0, 0, 0, 0, 0, - 3332, 725, 1935, 3335, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 2361, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3881, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1272, 0, - 0, 670, 0, 0, 0, 0, 670, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3686, 0, 0, 0, 0, 0, 0, 3686, - 670, 3686, 0, 0, 0, 0, 0, 2933, 0, 725, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2361, 0, 0, 0, 0, 0, 3494, 0, 0, 0, - 0, 0, 0, 725, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1510, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 670, 670, 670, 670, - 670, 670, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 670, 670, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 725, - 0, 0, 0, 0, 0, 0, 670, 0, 0, 725, - 0, 3555, 0, 0, 0, 0, 0, 0, 0, 1508, - 725, 0, 725, 0, 0, 0, 0, 0, 0, 0, - 0, 3570, 0, 0, 3571, 3572, 3573, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 725, 725, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2361, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 725, - 0, 0, 2361, 0, 0, 0, 0, 3746, 3748, 3747, - 3811, 3812, 3813, 3814, 3815, 3816, 3817, 796, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 725, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 725, 0, 0, 0, 0, 4028, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 4036, 0, - 0, 0, 725, 0, 725, 0, 0, 0, 0, 2361, - 0, 4044, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1272, 1272, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 4094, 0, - 0, 1060, 0, 670, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1510, 0, 0, 0, 0, 1510, - 670, 670, 670, 670, 670, 0, 0, 0, 4036, 0, - 0, 0, 3207, 0, 0, 0, 0, 0, 1935, 0, - 670, 0, 0, 670, 3215, 1988, 0, 0, 0, 0, - 0, 0, 2361, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1832, 0, 4094, 0, 3752, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 670, - 3760, 3761, 0, 0, 3836, 3835, 3834, 0, 0, 3832, - 3833, 3831, 0, 0, 0, 1510, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 670, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 670, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 670, - 0, 0, 670, 0, 3837, 917, 0, 772, 773, 3838, - 3839, 921, 3840, 775, 776, 918, 919, 0, 770, 774, - 920, 922, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 3743, 3744, 3745, - 3749, 3750, 3751, 3762, 3809, 3810, 3818, 3820, 873, 3819, - 3821, 3822, 3823, 3826, 3827, 3828, 3829, 3824, 3825, 3830, - 3726, 3730, 3727, 3728, 3729, 3741, 3731, 3732, 3733, 3734, - 3735, 3736, 3737, 3738, 3739, 3740, 3742, 3841, 3842, 3843, - 3844, 3845, 3846, 3755, 3759, 3758, 3756, 3757, 3753, 3754, - 3781, 3780, 3782, 3783, 3784, 3785, 3786, 3787, 3789, 3788, - 3790, 3791, 3792, 3793, 3794, 3795, 3763, 3764, 3767, 3768, - 3766, 3765, 3769, 3778, 3779, 3770, 3771, 3772, 3773, 3774, - 3775, 3777, 3776, 3796, 3797, 3798, 3799, 3800, 3802, 3801, - 3805, 3806, 3804, 3803, 3808, 3807, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 670, 0, 0, 0, 923, - 0, 924, 0, 0, 928, 0, 0, 0, 930, 929, - 0, 931, 893, 892, 0, 0, 925, 926, 0, 927, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 670, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 670, 0, 0, 4008, 3847, 3848, 3849, 3850, 3851, 3852, - 3853, 3854, 0, 0, 0, 0, 0, 0, 0, 0, - 670, 0, 0, 670, 670, 670, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1935, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1510, 0, 0, 0, 1935, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1935, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1935, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 670, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 394, 0, 0, 0, 0, 0, 1407, 1393, 525, - 0, 1335, 1410, 1304, 1323, 1420, 1326, 1329, 1372, 1282, - 1350, 414, 1320, 1308, 1277, 1315, 1278, 1306, 1337, 270, - 1303, 1395, 1354, 1409, 364, 267, 1284, 1275, 204, 503, - 1309, 428, 1325, 203, 1374, 485, 252, 375, 372, 580, - 282, 273, 269, 250, 317, 383, 426, 515, 420, 1416, - 368, 1360, 0, 495, 399, 0, 0, 1510, 1339, 1399, - 1348, 1386, 1334, 1373, 1292, 1359, 1411, 1321, 1369, 1412, - 323, 248, 325, 202, 411, 496, 286, 0, 0, 0, - 0, 4068, 948, 0, 0, 0, 4066, 4069, 0, 0, - 0, 0, 238, 0, 0, 245, 0, 0, 0, 349, - 358, 357, 338, 339, 341, 343, 348, 355, 361, 1317, - 1366, 604, 1406, 1318, 1368, 265, 321, 272, 264, 577, - 1417, 1398, 1281, 1347, 1405, 1342, 1935, 0, 229, 1408, - 1341, 0, 1371, 0, 1423, 1276, 1362, 0, 1279, 1283, - 1419, 1403, 1312, 275, 0, 0, 0, 0, 0, 0, - 0, 1338, 1349, 1383, 1387, 1332, 0, 0, 0, 0, - 0, 0, 0, 0, 1310, 0, 1358, 0, 0, 0, - 1288, 1280, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1988, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1336, 0, 0, 0, 0, 1291, - 0, 1311, 1384, 0, 1274, 297, 1285, 400, 257, 0, - 451, 1391, 1402, 1333, 622, 1404, 1331, 1330, 1378, 1289, - 1397, 1324, 363, 1287, 330, 197, 225, 0, 1322, 410, - 459, 471, 1396, 1307, 1316, 253, 1314, 469, 424, 599, - 233, 284, 456, 430, 467, 438, 287, 1357, 1376, 468, - 370, 582, 448, 596, 623, 624, 263, 404, 609, 519, - 617, 641, 226, 260, 418, 504, 602, 492, 395, 578, - 579, 329, 491, 295, 201, 367, 629, 224, 477, 369, - 242, 231, 584, 606, 299, 289, 454, 636, 213, 514, - 594, 239, 481, 0, 0, 644, 247, 502, 215, 591, - 501, 391, 326, 327, 214, 0, 455, 268, 293, 0, - 0, 258, 413, 586, 587, 256, 645, 228, 616, 220, - 1286, 615, 406, 581, 592, 392, 381, 219, 590, 390, - 380, 334, 353, 354, 280, 307, 445, 373, 446, 306, - 308, 402, 401, 403, 207, 603, 0, 208, 0, 497, - 605, 646, 450, 212, 234, 235, 237, 1302, 279, 283, - 291, 294, 303, 304, 313, 365, 417, 444, 440, 449, - 1392, 576, 597, 610, 621, 627, 628, 630, 631, 632, - 633, 634, 637, 635, 405, 311, 493, 333, 371, 1381, - 1422, 423, 470, 240, 601, 494, 199, 1296, 1301, 1294, - 0, 254, 255, 1363, 572, 1297, 1295, 1352, 1353, 1298, - 1413, 1414, 1415, 1400, 647, 648, 649, 650, 651, 652, - 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, - 663, 664, 642, 505, 511, 506, 507, 508, 509, 510, - 0, 512, 1385, 1290, 0, 1299, 1300, 396, 1394, 588, - 589, 665, 382, 484, 598, 335, 347, 350, 340, 359, - 0, 360, 336, 337, 342, 344, 345, 346, 351, 352, - 356, 362, 249, 210, 388, 397, 575, 312, 216, 217, - 218, 521, 522, 523, 524, 613, 614, 618, 205, 460, - 461, 462, 463, 292, 608, 309, 466, 465, 331, 332, - 377, 447, 537, 539, 550, 554, 556, 558, 564, 567, - 538, 540, 551, 555, 557, 559, 565, 568, 527, 529, - 531, 533, 546, 545, 542, 570, 571, 548, 553, 532, - 544, 549, 562, 569, 566, 526, 530, 534, 543, 561, - 560, 541, 552, 563, 547, 535, 528, 536, 1356, 196, - 221, 366, 1418, 452, 288, 643, 612, 482, 607, 206, - 223, 1293, 262, 1305, 1313, 0, 1319, 1327, 1328, 1340, - 1343, 1344, 1345, 1346, 1364, 1365, 1367, 1375, 1377, 1380, - 1382, 1389, 1401, 1421, 198, 200, 209, 222, 232, 236, - 243, 261, 276, 278, 285, 298, 310, 318, 319, 322, - 328, 378, 384, 385, 386, 387, 407, 408, 409, 412, - 415, 416, 419, 421, 422, 425, 429, 433, 434, 435, - 437, 439, 441, 453, 458, 472, 473, 474, 475, 476, - 479, 480, 486, 487, 488, 489, 490, 498, 499, 513, - 583, 585, 600, 619, 625, 478, 301, 302, 442, 443, - 314, 315, 639, 640, 300, 595, 626, 593, 638, 620, - 436, 376, 1355, 1361, 379, 281, 305, 320, 1370, 611, - 500, 227, 464, 290, 251, 1388, 1390, 211, 246, 230, - 259, 274, 277, 324, 389, 398, 427, 432, 296, 271, - 244, 457, 241, 483, 516, 517, 518, 520, 393, 266, - 431, 1351, 1379, 374, 573, 574, 316, 394, 0, 0, - 0, 0, 0, 1407, 1393, 525, 0, 1335, 1410, 1304, - 1323, 1420, 1326, 1329, 1372, 1282, 1350, 414, 1320, 1308, - 1277, 1315, 1278, 1306, 1337, 270, 1303, 1395, 1354, 1409, - 364, 267, 1284, 1275, 204, 503, 1309, 428, 1325, 203, - 1374, 485, 252, 375, 372, 580, 282, 273, 269, 250, - 317, 383, 426, 515, 420, 1416, 368, 1360, 0, 495, - 399, 0, 0, 0, 1339, 1399, 1348, 1386, 1334, 1373, - 1292, 1359, 1411, 1321, 1369, 1412, 323, 248, 325, 202, - 411, 496, 286, 0, 0, 0, 0, 0, 194, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 238, 0, - 0, 245, 0, 0, 0, 349, 358, 357, 338, 339, - 341, 343, 348, 355, 361, 1317, 1366, 604, 1406, 1318, - 1368, 265, 321, 272, 264, 577, 1417, 1398, 1281, 1347, - 1405, 1342, 0, 0, 229, 1408, 1341, 0, 1371, 0, - 1423, 1276, 1362, 0, 1279, 1283, 1419, 1403, 1312, 275, - 0, 0, 0, 0, 0, 0, 0, 1338, 1349, 1383, - 1387, 1332, 0, 0, 0, 0, 0, 0, 3216, 0, - 1310, 0, 1358, 0, 0, 0, 1288, 1280, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1336, 0, 0, 0, 0, 1291, 0, 1311, 1384, 0, - 1274, 297, 1285, 400, 257, 0, 451, 1391, 1402, 1333, - 622, 1404, 1331, 1330, 1378, 1289, 1397, 1324, 363, 1287, - 330, 197, 225, 0, 1322, 410, 459, 471, 1396, 1307, - 1316, 253, 1314, 469, 424, 599, 233, 284, 456, 430, - 467, 438, 287, 1357, 1376, 468, 370, 582, 448, 596, - 623, 624, 263, 404, 609, 519, 617, 641, 226, 260, - 418, 504, 602, 492, 395, 578, 579, 329, 491, 295, - 201, 367, 629, 224, 477, 369, 242, 231, 584, 606, - 299, 289, 454, 636, 213, 514, 594, 239, 481, 0, - 0, 644, 247, 502, 215, 591, 501, 391, 326, 327, - 214, 0, 455, 268, 293, 0, 0, 258, 413, 586, - 587, 256, 645, 228, 616, 220, 1286, 615, 406, 581, - 592, 392, 381, 219, 590, 390, 380, 334, 353, 354, - 280, 307, 445, 373, 446, 306, 308, 402, 401, 403, - 207, 603, 0, 208, 0, 497, 605, 646, 450, 212, - 234, 235, 237, 1302, 279, 283, 291, 294, 303, 304, - 313, 365, 417, 444, 440, 449, 1392, 576, 597, 610, - 621, 627, 628, 630, 631, 632, 633, 634, 637, 635, - 405, 311, 493, 333, 371, 1381, 1422, 423, 470, 240, - 601, 494, 199, 1296, 1301, 1294, 0, 254, 255, 1363, - 572, 1297, 1295, 1352, 1353, 1298, 1413, 1414, 1415, 1400, - 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, - 657, 658, 659, 660, 661, 662, 663, 664, 642, 505, - 511, 506, 507, 508, 509, 510, 0, 512, 1385, 1290, - 0, 1299, 1300, 396, 1394, 588, 589, 665, 382, 484, - 598, 335, 347, 350, 340, 359, 0, 360, 336, 337, - 342, 344, 345, 346, 351, 352, 356, 362, 249, 210, - 388, 397, 575, 312, 216, 217, 218, 521, 522, 523, - 524, 613, 614, 618, 205, 460, 461, 462, 463, 292, - 608, 309, 466, 465, 331, 332, 377, 447, 537, 539, - 550, 554, 556, 558, 564, 567, 538, 540, 551, 555, - 557, 559, 565, 568, 527, 529, 531, 533, 546, 545, - 542, 570, 571, 548, 553, 532, 544, 549, 562, 569, - 566, 526, 530, 534, 543, 561, 560, 541, 552, 563, - 547, 535, 528, 536, 1356, 196, 221, 366, 1418, 452, - 288, 643, 612, 482, 607, 206, 223, 1293, 262, 1305, - 1313, 0, 1319, 1327, 1328, 1340, 1343, 1344, 1345, 1346, - 1364, 1365, 1367, 1375, 1377, 1380, 1382, 1389, 1401, 1421, - 198, 200, 209, 222, 232, 236, 243, 261, 276, 278, - 285, 298, 310, 318, 319, 322, 328, 378, 384, 385, - 386, 387, 407, 408, 409, 412, 415, 416, 419, 421, - 422, 425, 429, 433, 434, 435, 437, 439, 441, 453, - 458, 472, 473, 474, 475, 476, 479, 480, 486, 487, - 488, 489, 490, 498, 499, 513, 583, 585, 600, 619, - 625, 478, 301, 302, 442, 443, 314, 315, 639, 640, - 300, 595, 626, 593, 638, 620, 436, 376, 1355, 1361, - 379, 281, 305, 320, 1370, 611, 500, 227, 464, 290, - 251, 1388, 1390, 211, 246, 230, 259, 274, 277, 324, - 389, 398, 427, 432, 296, 271, 244, 457, 241, 483, - 516, 517, 518, 520, 393, 266, 431, 1351, 1379, 374, - 573, 574, 316, 394, 0, 0, 0, 0, 0, 1407, - 1393, 525, 0, 1335, 1410, 1304, 1323, 1420, 1326, 1329, - 1372, 1282, 1350, 414, 1320, 1308, 1277, 1315, 1278, 1306, - 1337, 270, 1303, 1395, 1354, 1409, 364, 267, 1284, 1275, - 204, 503, 1309, 428, 1325, 203, 1374, 485, 252, 375, - 372, 580, 282, 273, 269, 250, 317, 383, 426, 515, - 420, 1416, 368, 1360, 0, 495, 399, 0, 0, 0, - 1339, 1399, 1348, 1386, 1334, 1373, 1292, 1359, 1411, 1321, - 1369, 1412, 323, 248, 325, 202, 411, 496, 286, 0, - 0, 0, 0, 0, 715, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 238, 0, 0, 245, 0, 0, - 0, 349, 358, 357, 338, 339, 341, 343, 348, 355, - 361, 1317, 1366, 604, 1406, 1318, 1368, 265, 321, 272, - 264, 577, 1417, 1398, 1281, 1347, 1405, 1342, 0, 0, - 229, 1408, 1341, 0, 1371, 0, 1423, 1276, 1362, 0, - 1279, 1283, 1419, 1403, 1312, 275, 0, 0, 0, 0, - 0, 0, 0, 1338, 1349, 1383, 1387, 1332, 0, 0, - 0, 0, 0, 0, 3177, 0, 1310, 0, 1358, 0, - 0, 0, 1288, 1280, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1336, 0, 0, 0, - 0, 1291, 0, 1311, 1384, 0, 1274, 297, 1285, 400, - 257, 0, 451, 1391, 1402, 1333, 622, 1404, 1331, 1330, - 1378, 1289, 1397, 1324, 363, 1287, 330, 197, 225, 0, - 1322, 410, 459, 471, 1396, 1307, 1316, 253, 1314, 469, - 424, 599, 233, 284, 456, 430, 467, 438, 287, 1357, - 1376, 468, 370, 582, 448, 596, 623, 624, 263, 404, - 609, 519, 617, 641, 226, 260, 418, 504, 602, 492, - 395, 578, 579, 329, 491, 295, 201, 367, 629, 224, - 477, 369, 242, 231, 584, 606, 299, 289, 454, 636, - 213, 514, 594, 239, 481, 0, 0, 644, 247, 502, - 215, 591, 501, 391, 326, 327, 214, 0, 455, 268, - 293, 0, 0, 258, 413, 586, 587, 256, 645, 228, - 616, 220, 1286, 615, 406, 581, 592, 392, 381, 219, - 590, 390, 380, 334, 353, 354, 280, 307, 445, 373, - 446, 306, 308, 402, 401, 403, 207, 603, 0, 208, - 0, 497, 605, 646, 450, 212, 234, 235, 237, 1302, - 279, 283, 291, 294, 303, 304, 313, 365, 417, 444, - 440, 449, 1392, 576, 597, 610, 621, 627, 628, 630, - 631, 632, 633, 634, 637, 635, 405, 311, 493, 333, - 371, 1381, 1422, 423, 470, 240, 601, 494, 199, 1296, - 1301, 1294, 0, 254, 255, 1363, 572, 1297, 1295, 1352, - 1353, 1298, 1413, 1414, 1415, 1400, 647, 648, 649, 650, - 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, - 661, 662, 663, 664, 642, 505, 511, 506, 507, 508, - 509, 510, 0, 512, 1385, 1290, 0, 1299, 1300, 396, - 1394, 588, 589, 665, 382, 484, 598, 335, 347, 350, - 340, 359, 0, 360, 336, 337, 342, 344, 345, 346, - 351, 352, 356, 362, 249, 210, 388, 397, 575, 312, - 216, 217, 218, 521, 522, 523, 524, 613, 614, 618, - 205, 460, 461, 462, 463, 292, 608, 309, 466, 465, - 331, 332, 377, 447, 537, 539, 550, 554, 556, 558, - 564, 567, 538, 540, 551, 555, 557, 559, 565, 568, - 527, 529, 531, 533, 546, 545, 542, 570, 571, 548, - 553, 532, 544, 549, 562, 569, 566, 526, 530, 534, - 543, 561, 560, 541, 552, 563, 547, 535, 528, 536, - 1356, 196, 221, 366, 1418, 452, 288, 643, 612, 482, - 607, 206, 223, 1293, 262, 1305, 1313, 0, 1319, 1327, - 1328, 1340, 1343, 1344, 1345, 1346, 1364, 1365, 1367, 1375, - 1377, 1380, 1382, 1389, 1401, 1421, 198, 200, 209, 222, - 232, 236, 243, 261, 276, 278, 285, 298, 310, 318, - 319, 322, 328, 378, 384, 385, 386, 387, 407, 408, - 409, 412, 415, 416, 419, 421, 422, 425, 429, 433, - 434, 435, 437, 439, 441, 453, 458, 472, 473, 474, - 475, 476, 479, 480, 486, 487, 488, 489, 490, 498, - 499, 513, 583, 585, 600, 619, 625, 478, 301, 302, - 442, 443, 314, 315, 639, 640, 300, 595, 626, 593, - 638, 620, 436, 376, 1355, 1361, 379, 281, 305, 320, - 1370, 611, 500, 227, 464, 290, 251, 1388, 1390, 211, - 246, 230, 259, 274, 277, 324, 389, 398, 427, 432, - 296, 271, 244, 457, 241, 483, 516, 517, 518, 520, - 393, 266, 431, 1351, 1379, 374, 573, 574, 316, 394, - 0, 0, 0, 0, 0, 1407, 1393, 525, 0, 1335, - 1410, 1304, 1323, 1420, 1326, 1329, 1372, 1282, 1350, 414, - 1320, 1308, 1277, 1315, 1278, 1306, 1337, 270, 1303, 1395, - 1354, 1409, 364, 267, 1284, 1275, 204, 503, 1309, 428, - 1325, 203, 1374, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 1416, 368, 1360, - 0, 495, 399, 0, 0, 0, 1339, 1399, 1348, 1386, - 1334, 1373, 1292, 1359, 1411, 1321, 1369, 1412, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 948, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 1317, 1366, 604, - 1406, 1318, 1368, 265, 321, 272, 264, 577, 1417, 1398, - 1281, 1347, 1405, 1342, 0, 0, 229, 1408, 1341, 0, - 1371, 0, 1423, 1276, 1362, 0, 1279, 1283, 1419, 1403, - 1312, 275, 0, 0, 0, 0, 0, 0, 0, 1338, - 1349, 1383, 1387, 1332, 0, 0, 0, 0, 0, 0, - 2379, 0, 1310, 0, 1358, 0, 0, 0, 1288, 1280, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1336, 0, 0, 0, 0, 1291, 0, 1311, - 1384, 0, 1274, 297, 1285, 400, 257, 0, 451, 1391, - 1402, 1333, 622, 1404, 1331, 1330, 1378, 1289, 1397, 1324, - 363, 1287, 330, 197, 225, 0, 1322, 410, 459, 471, - 1396, 1307, 1316, 253, 1314, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 1357, 1376, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 1286, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 1302, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 1392, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 1381, 1422, 423, - 470, 240, 601, 494, 199, 1296, 1301, 1294, 0, 254, - 255, 1363, 572, 1297, 1295, 1352, 1353, 1298, 1413, 1414, - 1415, 1400, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 1385, 1290, 0, 1299, 1300, 396, 1394, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 1356, 196, 221, 366, - 1418, 452, 288, 643, 612, 482, 607, 206, 223, 1293, - 262, 1305, 1313, 0, 1319, 1327, 1328, 1340, 1343, 1344, - 1345, 1346, 1364, 1365, 1367, 1375, 1377, 1380, 1382, 1389, - 1401, 1421, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 1355, 1361, 379, 281, 305, 320, 1370, 611, 500, 227, - 464, 290, 251, 1388, 1390, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 1351, - 1379, 374, 573, 574, 316, 394, 0, 0, 0, 0, - 0, 1407, 1393, 525, 0, 1335, 1410, 1304, 1323, 1420, - 1326, 1329, 1372, 1282, 1350, 414, 1320, 1308, 1277, 1315, - 1278, 1306, 1337, 270, 1303, 1395, 1354, 1409, 364, 267, - 1284, 1275, 204, 503, 1309, 428, 1325, 203, 1374, 485, - 252, 375, 372, 580, 282, 273, 269, 250, 317, 383, - 426, 515, 420, 1416, 368, 1360, 0, 495, 399, 0, - 0, 0, 1339, 1399, 1348, 1386, 1334, 1373, 1292, 1359, - 1411, 1321, 1369, 1412, 323, 248, 325, 202, 411, 496, - 286, 0, 95, 0, 0, 0, 715, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 238, 0, 0, 245, - 0, 0, 0, 349, 358, 357, 338, 339, 341, 343, - 348, 355, 361, 1317, 1366, 604, 1406, 1318, 1368, 265, - 321, 272, 264, 577, 1417, 1398, 1281, 1347, 1405, 1342, - 0, 0, 229, 1408, 1341, 0, 1371, 0, 1423, 1276, - 1362, 0, 1279, 1283, 1419, 1403, 1312, 275, 0, 0, - 0, 0, 0, 0, 0, 1338, 1349, 1383, 1387, 1332, - 0, 0, 0, 0, 0, 0, 0, 0, 1310, 0, - 1358, 0, 0, 0, 1288, 1280, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1336, 0, - 0, 0, 0, 1291, 0, 1311, 1384, 0, 1274, 297, - 1285, 400, 257, 0, 451, 1391, 1402, 1333, 622, 1404, - 1331, 1330, 1378, 1289, 1397, 1324, 363, 1287, 330, 197, - 225, 0, 1322, 410, 459, 471, 1396, 1307, 1316, 253, - 1314, 469, 424, 599, 233, 284, 456, 430, 467, 438, - 287, 1357, 1376, 468, 370, 582, 448, 596, 623, 624, - 263, 404, 609, 519, 617, 641, 226, 260, 418, 504, - 602, 492, 395, 578, 579, 329, 491, 295, 201, 367, - 629, 224, 477, 369, 242, 231, 584, 606, 299, 289, - 454, 636, 213, 514, 594, 239, 481, 0, 0, 644, - 247, 502, 215, 591, 501, 391, 326, 327, 214, 0, - 455, 268, 293, 0, 0, 258, 413, 586, 587, 256, - 645, 228, 616, 220, 1286, 615, 406, 581, 592, 392, - 381, 219, 590, 390, 380, 334, 353, 354, 280, 307, - 445, 373, 446, 306, 308, 402, 401, 403, 207, 603, - 0, 208, 0, 497, 605, 646, 450, 212, 234, 235, - 237, 1302, 279, 283, 291, 294, 303, 304, 313, 365, - 417, 444, 440, 449, 1392, 576, 597, 610, 621, 627, - 628, 630, 631, 632, 633, 634, 637, 635, 405, 311, - 493, 333, 371, 1381, 1422, 423, 470, 240, 601, 494, - 199, 1296, 1301, 1294, 0, 254, 255, 1363, 572, 1297, - 1295, 1352, 1353, 1298, 1413, 1414, 1415, 1400, 647, 648, - 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, - 659, 660, 661, 662, 663, 664, 642, 505, 511, 506, - 507, 508, 509, 510, 0, 512, 1385, 1290, 0, 1299, - 1300, 396, 1394, 588, 589, 665, 382, 484, 598, 335, - 347, 350, 340, 359, 0, 360, 336, 337, 342, 344, - 345, 346, 351, 352, 356, 362, 249, 210, 388, 397, - 575, 312, 216, 217, 218, 521, 522, 523, 524, 613, - 614, 618, 205, 460, 461, 462, 463, 292, 608, 309, - 466, 465, 331, 332, 377, 447, 537, 539, 550, 554, - 556, 558, 564, 567, 538, 540, 551, 555, 557, 559, - 565, 568, 527, 529, 531, 533, 546, 545, 542, 570, - 571, 548, 553, 532, 544, 549, 562, 569, 566, 526, - 530, 534, 543, 561, 560, 541, 552, 563, 547, 535, - 528, 536, 1356, 196, 221, 366, 1418, 452, 288, 643, - 612, 482, 607, 206, 223, 1293, 262, 1305, 1313, 0, - 1319, 1327, 1328, 1340, 1343, 1344, 1345, 1346, 1364, 1365, - 1367, 1375, 1377, 1380, 1382, 1389, 1401, 1421, 198, 200, - 209, 222, 232, 236, 243, 261, 276, 278, 285, 298, - 310, 318, 319, 322, 328, 378, 384, 385, 386, 387, - 407, 408, 409, 412, 415, 416, 419, 421, 422, 425, - 429, 433, 434, 435, 437, 439, 441, 453, 458, 472, - 473, 474, 475, 476, 479, 480, 486, 487, 488, 489, - 490, 498, 499, 513, 583, 585, 600, 619, 625, 478, - 301, 302, 442, 443, 314, 315, 639, 640, 300, 595, - 626, 593, 638, 620, 436, 376, 1355, 1361, 379, 281, - 305, 320, 1370, 611, 500, 227, 464, 290, 251, 1388, - 1390, 211, 246, 230, 259, 274, 277, 324, 389, 398, - 427, 432, 296, 271, 244, 457, 241, 483, 516, 517, - 518, 520, 393, 266, 431, 1351, 1379, 374, 573, 574, - 316, 394, 0, 0, 0, 0, 0, 1407, 1393, 525, - 0, 1335, 1410, 1304, 1323, 1420, 1326, 1329, 1372, 1282, - 1350, 414, 1320, 1308, 1277, 1315, 1278, 1306, 1337, 270, - 1303, 1395, 1354, 1409, 364, 267, 1284, 1275, 204, 503, - 1309, 428, 1325, 203, 1374, 485, 252, 375, 372, 580, - 282, 273, 269, 250, 317, 383, 426, 515, 420, 1416, - 368, 1360, 0, 495, 399, 0, 0, 0, 1339, 1399, - 1348, 1386, 1334, 1373, 1292, 1359, 1411, 1321, 1369, 1412, - 323, 248, 325, 202, 411, 496, 286, 0, 0, 0, - 0, 0, 194, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 238, 0, 0, 245, 0, 0, 0, 349, - 358, 357, 338, 339, 341, 343, 348, 355, 361, 1317, - 1366, 604, 1406, 1318, 1368, 265, 321, 272, 264, 577, - 1417, 1398, 1281, 1347, 1405, 1342, 0, 0, 229, 1408, - 1341, 0, 1371, 0, 1423, 1276, 1362, 0, 1279, 1283, - 1419, 1403, 1312, 275, 0, 0, 0, 0, 0, 0, - 0, 1338, 1349, 1383, 1387, 1332, 0, 0, 0, 0, - 0, 0, 0, 0, 1310, 0, 1358, 0, 0, 0, - 1288, 1280, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1336, 0, 0, 0, 0, 1291, - 0, 1311, 1384, 0, 1274, 297, 1285, 400, 257, 0, - 451, 1391, 1402, 1333, 622, 1404, 1331, 1330, 1378, 1289, - 1397, 1324, 363, 1287, 330, 197, 225, 0, 1322, 410, - 459, 471, 1396, 1307, 1316, 253, 1314, 469, 424, 599, - 233, 284, 456, 430, 467, 438, 287, 1357, 1376, 468, - 370, 582, 448, 596, 623, 624, 263, 404, 609, 519, - 617, 641, 226, 260, 418, 504, 602, 492, 395, 578, - 579, 329, 491, 295, 201, 367, 629, 224, 477, 369, - 242, 231, 584, 606, 299, 289, 454, 636, 213, 514, - 594, 239, 481, 0, 0, 644, 247, 502, 215, 591, - 501, 391, 326, 327, 214, 0, 455, 268, 293, 0, - 0, 258, 413, 586, 587, 256, 645, 228, 616, 220, - 1286, 615, 406, 581, 592, 392, 381, 219, 590, 390, - 380, 334, 353, 354, 280, 307, 445, 373, 446, 306, - 308, 402, 401, 403, 207, 603, 0, 208, 0, 497, - 605, 646, 450, 212, 234, 235, 237, 1302, 279, 283, - 291, 294, 303, 304, 313, 365, 417, 444, 440, 449, - 1392, 576, 597, 610, 621, 627, 628, 630, 631, 632, - 633, 634, 637, 635, 405, 311, 493, 333, 371, 1381, - 1422, 423, 470, 240, 601, 494, 199, 1296, 1301, 1294, - 0, 254, 255, 1363, 572, 1297, 1295, 1352, 1353, 1298, - 1413, 1414, 1415, 1400, 647, 648, 649, 650, 651, 652, - 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, - 663, 664, 642, 505, 511, 506, 507, 508, 509, 510, - 0, 512, 1385, 1290, 0, 1299, 1300, 396, 1394, 588, - 589, 665, 382, 484, 598, 335, 347, 350, 340, 359, - 0, 360, 336, 337, 342, 344, 345, 346, 351, 352, - 356, 362, 249, 210, 388, 397, 575, 312, 216, 217, - 218, 521, 522, 523, 524, 613, 614, 618, 205, 460, - 461, 462, 463, 292, 608, 309, 466, 465, 331, 332, - 377, 447, 537, 539, 550, 554, 556, 558, 564, 567, - 538, 540, 551, 555, 557, 559, 565, 568, 527, 529, - 531, 533, 546, 545, 542, 570, 571, 548, 553, 532, - 544, 549, 562, 569, 566, 526, 530, 534, 543, 561, - 560, 541, 552, 563, 547, 535, 528, 536, 1356, 196, - 221, 366, 1418, 452, 288, 643, 612, 482, 607, 206, - 223, 1293, 262, 1305, 1313, 0, 1319, 1327, 1328, 1340, - 1343, 1344, 1345, 1346, 1364, 1365, 1367, 1375, 1377, 1380, - 1382, 1389, 1401, 1421, 198, 200, 209, 222, 232, 236, - 243, 261, 276, 278, 285, 298, 310, 318, 319, 322, - 328, 378, 384, 385, 386, 387, 407, 408, 409, 412, - 415, 416, 419, 421, 422, 425, 429, 433, 434, 435, - 437, 439, 441, 453, 458, 472, 473, 474, 475, 476, - 479, 480, 486, 487, 488, 489, 490, 498, 499, 513, - 583, 585, 600, 619, 625, 478, 301, 302, 442, 443, - 314, 315, 639, 640, 300, 595, 626, 593, 638, 620, - 436, 376, 1355, 1361, 379, 281, 305, 320, 1370, 611, - 500, 227, 464, 290, 251, 1388, 1390, 211, 246, 230, - 259, 274, 277, 324, 389, 398, 427, 432, 296, 271, - 244, 457, 241, 483, 516, 517, 518, 520, 393, 266, - 431, 1351, 1379, 374, 573, 574, 316, 394, 0, 0, - 0, 0, 0, 1407, 1393, 525, 0, 1335, 1410, 1304, - 1323, 1420, 1326, 1329, 1372, 1282, 1350, 414, 1320, 1308, - 1277, 1315, 1278, 1306, 1337, 270, 1303, 1395, 1354, 1409, - 364, 267, 1284, 1275, 204, 503, 1309, 428, 1325, 203, - 1374, 485, 252, 375, 372, 580, 282, 273, 269, 250, - 317, 383, 426, 515, 420, 1416, 368, 1360, 0, 495, - 399, 0, 0, 0, 1339, 1399, 1348, 1386, 1334, 1373, - 1292, 1359, 1411, 1321, 1369, 1412, 323, 248, 325, 202, - 411, 496, 286, 0, 0, 0, 0, 0, 715, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 238, 0, - 0, 245, 0, 0, 0, 349, 358, 357, 338, 339, - 341, 343, 348, 355, 361, 1317, 1366, 604, 1406, 1318, - 1368, 265, 321, 272, 264, 577, 1417, 1398, 1281, 1347, - 1405, 1342, 0, 0, 229, 1408, 1341, 0, 1371, 0, - 1423, 1276, 1362, 0, 1279, 1283, 1419, 1403, 1312, 275, - 0, 0, 0, 0, 0, 0, 0, 1338, 1349, 1383, - 1387, 1332, 0, 0, 0, 0, 0, 0, 0, 0, - 1310, 0, 1358, 0, 0, 0, 1288, 1280, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1336, 0, 0, 0, 0, 1291, 0, 1311, 1384, 0, - 1274, 297, 1285, 400, 257, 0, 451, 1391, 1402, 1333, - 622, 1404, 1331, 1330, 1378, 1289, 1397, 1324, 363, 1287, - 330, 197, 225, 0, 1322, 410, 459, 471, 1396, 1307, - 1316, 253, 1314, 469, 424, 599, 233, 284, 456, 430, - 467, 438, 287, 1357, 1376, 468, 370, 582, 448, 596, - 623, 624, 263, 404, 609, 519, 617, 641, 226, 260, - 418, 504, 602, 492, 395, 578, 579, 329, 491, 295, - 201, 367, 629, 224, 477, 369, 242, 231, 584, 606, - 299, 289, 454, 636, 213, 514, 594, 239, 481, 0, - 0, 644, 247, 502, 215, 591, 501, 391, 326, 327, - 214, 0, 455, 268, 293, 0, 0, 258, 413, 586, - 587, 256, 645, 228, 616, 220, 1286, 615, 406, 581, - 592, 392, 381, 219, 590, 390, 380, 334, 353, 354, - 280, 307, 445, 373, 446, 306, 308, 402, 401, 403, - 207, 603, 0, 208, 0, 497, 605, 646, 450, 212, - 234, 235, 237, 1302, 279, 283, 291, 294, 303, 304, - 313, 365, 417, 444, 440, 449, 1392, 576, 597, 610, - 621, 627, 628, 630, 631, 632, 633, 634, 637, 635, - 405, 311, 493, 333, 371, 1381, 1422, 423, 470, 240, - 601, 494, 199, 1296, 1301, 1294, 0, 254, 255, 1363, - 572, 1297, 1295, 1352, 1353, 1298, 1413, 1414, 1415, 1400, - 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, - 657, 658, 659, 660, 661, 662, 663, 664, 642, 505, - 511, 506, 507, 508, 509, 510, 0, 512, 1385, 1290, - 0, 1299, 1300, 396, 1394, 588, 589, 665, 382, 484, - 598, 335, 347, 350, 340, 359, 0, 360, 336, 337, - 342, 344, 345, 346, 351, 352, 356, 362, 249, 210, - 388, 397, 575, 312, 216, 217, 218, 521, 522, 523, - 524, 613, 614, 618, 205, 460, 461, 462, 463, 292, - 608, 309, 466, 465, 331, 332, 377, 447, 537, 539, - 550, 554, 556, 558, 564, 567, 538, 540, 551, 555, - 557, 559, 565, 568, 527, 529, 531, 533, 546, 545, - 542, 570, 571, 548, 553, 532, 544, 549, 562, 569, - 566, 526, 530, 534, 543, 561, 560, 541, 552, 563, - 547, 535, 528, 536, 1356, 196, 221, 366, 1418, 452, - 288, 643, 612, 482, 607, 206, 223, 1293, 262, 1305, - 1313, 0, 1319, 1327, 1328, 1340, 1343, 1344, 1345, 1346, - 1364, 1365, 1367, 1375, 1377, 1380, 1382, 1389, 1401, 1421, - 198, 200, 209, 222, 232, 236, 243, 261, 276, 278, - 285, 298, 310, 318, 319, 322, 328, 378, 384, 385, - 386, 387, 407, 408, 409, 412, 415, 416, 419, 421, - 422, 425, 429, 433, 434, 435, 437, 439, 441, 453, - 458, 472, 473, 474, 475, 476, 479, 480, 486, 487, - 488, 489, 490, 498, 499, 513, 583, 585, 600, 619, - 625, 478, 301, 302, 442, 443, 314, 315, 639, 640, - 300, 595, 626, 593, 638, 620, 436, 376, 1355, 1361, - 379, 281, 305, 320, 1370, 611, 500, 227, 464, 290, - 251, 1388, 1390, 211, 246, 230, 259, 274, 277, 324, - 389, 398, 427, 432, 296, 271, 244, 457, 241, 483, - 516, 517, 518, 520, 393, 266, 431, 1351, 1379, 374, - 573, 574, 316, 394, 0, 0, 0, 0, 0, 1407, - 1393, 525, 0, 1335, 1410, 1304, 1323, 1420, 1326, 1329, - 1372, 1282, 1350, 414, 1320, 1308, 1277, 1315, 1278, 1306, - 1337, 270, 1303, 1395, 1354, 1409, 364, 267, 1284, 1275, - 204, 503, 1309, 428, 1325, 203, 1374, 485, 252, 375, - 372, 580, 282, 273, 269, 250, 317, 383, 426, 515, - 420, 1416, 368, 1360, 0, 495, 399, 0, 0, 0, - 1339, 1399, 1348, 1386, 1334, 1373, 1292, 1359, 1411, 1321, - 1369, 1412, 323, 248, 325, 202, 411, 496, 286, 0, - 0, 0, 0, 0, 948, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 238, 0, 0, 245, 0, 0, - 0, 349, 358, 357, 338, 339, 341, 343, 348, 355, - 361, 1317, 1366, 604, 1406, 1318, 1368, 265, 321, 272, - 264, 577, 1417, 1398, 1281, 1347, 1405, 1342, 0, 0, - 229, 1408, 1341, 0, 1371, 0, 1423, 1276, 1362, 0, - 1279, 1283, 1419, 1403, 1312, 275, 0, 0, 0, 0, - 0, 0, 0, 1338, 1349, 1383, 1387, 1332, 0, 0, - 0, 0, 0, 0, 0, 0, 1310, 0, 1358, 0, - 0, 0, 1288, 1280, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1336, 0, 0, 0, - 0, 1291, 0, 1311, 1384, 0, 1274, 297, 1285, 400, - 257, 0, 451, 1391, 1402, 1333, 622, 1404, 1331, 1330, - 1378, 1289, 1397, 1324, 363, 1287, 330, 197, 225, 0, - 1322, 410, 459, 471, 1396, 1307, 1316, 253, 1314, 469, - 424, 599, 233, 284, 456, 430, 467, 438, 287, 1357, - 1376, 468, 370, 582, 448, 596, 623, 624, 263, 404, - 609, 519, 617, 641, 226, 260, 418, 504, 602, 492, - 395, 578, 579, 329, 491, 295, 201, 367, 629, 224, - 477, 369, 242, 231, 584, 606, 299, 289, 454, 636, - 213, 514, 594, 239, 481, 0, 0, 644, 247, 502, - 215, 591, 501, 391, 326, 327, 214, 0, 455, 268, - 293, 0, 0, 258, 413, 586, 587, 256, 645, 228, - 616, 220, 1286, 615, 406, 581, 592, 392, 381, 219, - 590, 390, 380, 334, 353, 354, 280, 307, 445, 373, - 446, 306, 308, 402, 401, 403, 207, 603, 0, 208, - 0, 497, 605, 646, 450, 212, 234, 235, 237, 1302, - 279, 283, 291, 294, 303, 304, 313, 365, 417, 444, - 440, 449, 1392, 576, 597, 610, 621, 627, 628, 630, - 631, 632, 633, 634, 637, 635, 405, 311, 493, 333, - 371, 1381, 1422, 423, 470, 240, 601, 494, 199, 1296, - 1301, 1294, 0, 254, 255, 1363, 572, 1297, 1295, 1352, - 1353, 1298, 1413, 1414, 1415, 1400, 647, 648, 649, 650, - 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, - 661, 662, 663, 664, 642, 505, 511, 506, 507, 508, - 509, 510, 0, 512, 1385, 1290, 0, 1299, 1300, 396, - 1394, 588, 589, 665, 382, 484, 598, 335, 347, 350, - 340, 359, 0, 360, 336, 337, 342, 344, 345, 346, - 351, 352, 356, 362, 249, 210, 388, 397, 575, 312, - 216, 217, 218, 521, 522, 523, 524, 613, 614, 618, - 205, 460, 461, 462, 463, 292, 608, 309, 466, 465, - 331, 332, 377, 447, 537, 539, 550, 554, 556, 558, - 564, 567, 538, 540, 551, 555, 557, 559, 565, 568, - 527, 529, 531, 533, 546, 545, 542, 570, 571, 548, - 553, 532, 544, 549, 562, 569, 566, 526, 530, 534, - 543, 561, 560, 541, 552, 563, 547, 535, 528, 536, - 1356, 196, 221, 366, 1418, 452, 288, 643, 612, 482, - 607, 206, 223, 1293, 262, 1305, 1313, 0, 1319, 1327, - 1328, 1340, 1343, 1344, 1345, 1346, 1364, 1365, 1367, 1375, - 1377, 1380, 1382, 1389, 1401, 1421, 198, 200, 209, 222, - 232, 236, 243, 261, 276, 278, 285, 298, 310, 318, - 319, 322, 328, 378, 384, 385, 386, 387, 407, 408, - 409, 412, 415, 416, 419, 421, 422, 425, 429, 433, - 434, 435, 437, 439, 441, 453, 458, 472, 473, 474, - 475, 476, 479, 480, 486, 487, 488, 489, 490, 498, - 499, 513, 583, 585, 600, 619, 625, 478, 301, 302, - 442, 443, 314, 315, 639, 640, 300, 595, 626, 593, - 638, 620, 436, 376, 1355, 1361, 379, 281, 305, 320, - 1370, 611, 500, 227, 464, 290, 251, 1388, 1390, 211, - 246, 230, 259, 274, 277, 324, 389, 398, 427, 432, - 296, 271, 244, 457, 241, 483, 516, 517, 518, 520, - 393, 266, 431, 1351, 1379, 374, 573, 574, 316, 394, - 0, 0, 0, 0, 0, 0, 0, 525, 0, 768, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 755, 0, 0, 0, 270, 760, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 767, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 762, 763, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 95, 0, 0, 1012, - 948, 739, 914, 952, 1013, 965, 966, 967, 953, 0, - 238, 954, 955, 245, 956, 0, 913, 798, 800, 799, - 863, 864, 865, 866, 867, 868, 869, 796, 961, 604, - 968, 969, 0, 265, 321, 272, 264, 577, 0, 0, - 2201, 2202, 2203, 0, 0, 0, 229, 0, 0, 0, - 0, 0, 0, 0, 735, 752, 0, 766, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 749, 750, - 0, 0, 0, 0, 908, 0, 751, 0, 0, 759, - 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, - 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, - 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, - 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, - 1010, 1011, 761, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 907, - 0, 0, 622, 0, 0, 905, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 958, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 959, 960, 256, 645, 804, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 812, 813, 280, 307, 889, 888, 887, 306, 308, 885, - 886, 884, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 895, 917, 906, 772, 773, 896, - 897, 921, 898, 775, 776, 918, 919, 769, 770, 774, - 920, 922, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 909, 758, 757, 0, 764, 765, 0, 794, 795, 797, - 801, 802, 803, 814, 861, 862, 870, 872, 873, 871, - 874, 875, 876, 879, 880, 881, 882, 877, 878, 883, - 777, 781, 778, 779, 780, 792, 782, 783, 784, 785, - 786, 787, 788, 789, 790, 791, 793, 932, 933, 934, - 935, 936, 937, 807, 811, 810, 808, 809, 805, 806, - 833, 832, 834, 835, 836, 837, 838, 839, 841, 840, - 842, 843, 844, 845, 846, 847, 815, 816, 819, 820, - 818, 817, 821, 830, 831, 822, 823, 824, 825, 826, - 827, 829, 828, 848, 849, 850, 851, 852, 854, 853, - 857, 858, 856, 855, 860, 859, 756, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 923, - 262, 924, 0, 0, 928, 0, 0, 0, 930, 929, - 0, 931, 893, 892, 0, 0, 925, 926, 0, 927, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 938, 939, 940, 941, 942, 943, - 944, 945, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 963, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 768, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 755, 0, 0, 0, 270, 760, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 767, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 762, 763, - 0, 0, 0, 0, 0, 0, 2408, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 95, 0, 0, 1012, - 948, 739, 914, 952, 1013, 965, 966, 967, 953, 0, - 238, 954, 955, 245, 956, 0, 913, 798, 800, 799, - 863, 864, 865, 866, 867, 868, 869, 796, 961, 604, - 968, 969, 2409, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, - 0, 0, 0, 0, 735, 752, 0, 766, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 749, 750, - 0, 0, 0, 0, 908, 0, 751, 0, 0, 759, - 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, - 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, - 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, - 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, - 1010, 1011, 761, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 907, - 0, 0, 622, 0, 0, 905, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 958, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 959, 960, 256, 645, 804, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 812, 813, 280, 307, 889, 888, 887, 306, 308, 885, - 886, 884, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 895, 917, 906, 772, 773, 896, - 897, 921, 898, 775, 776, 918, 919, 769, 770, 774, - 920, 922, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 909, 758, 757, 0, 764, 765, 0, 794, 795, 797, - 801, 802, 803, 814, 861, 862, 870, 872, 873, 871, - 874, 875, 876, 879, 880, 881, 882, 877, 878, 883, - 777, 781, 778, 779, 780, 792, 782, 783, 784, 785, - 786, 787, 788, 789, 790, 791, 793, 932, 933, 934, - 935, 936, 937, 807, 811, 810, 808, 809, 805, 806, - 833, 832, 834, 835, 836, 837, 838, 839, 841, 840, - 842, 843, 844, 845, 846, 847, 815, 816, 819, 820, - 818, 817, 821, 830, 831, 822, 823, 824, 825, 826, - 827, 829, 828, 848, 849, 850, 851, 852, 854, 853, - 857, 858, 856, 855, 860, 859, 756, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 923, - 262, 924, 0, 0, 928, 0, 0, 0, 930, 929, - 0, 931, 893, 892, 0, 0, 925, 926, 0, 927, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 938, 939, 940, 941, 942, 943, - 944, 945, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 963, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 86, 525, 0, 768, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 755, 0, 0, 0, 270, 760, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 767, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 762, 763, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 95, 0, 0, 1012, - 948, 739, 914, 952, 1013, 965, 966, 967, 953, 0, - 238, 954, 955, 245, 956, 0, 913, 798, 800, 799, - 863, 864, 865, 866, 867, 868, 869, 796, 961, 604, - 968, 969, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, - 0, 0, 0, 0, 735, 752, 0, 766, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 749, 750, - 0, 0, 0, 0, 908, 0, 751, 0, 0, 759, - 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, - 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, - 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, - 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, - 1010, 1011, 761, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 907, - 0, 0, 622, 0, 0, 905, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 958, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 959, 960, 256, 645, 804, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 812, 813, 280, 307, 889, 888, 887, 306, 308, 885, - 886, 884, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 895, 917, 906, 772, 773, 896, - 897, 921, 898, 775, 776, 918, 919, 769, 770, 774, - 920, 922, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 909, 758, 757, 0, 764, 765, 0, 794, 795, 797, - 801, 802, 803, 814, 861, 862, 870, 872, 873, 871, - 874, 875, 876, 879, 880, 881, 882, 877, 878, 883, - 777, 781, 778, 779, 780, 792, 782, 783, 784, 785, - 786, 787, 788, 789, 790, 791, 793, 932, 933, 934, - 935, 936, 937, 807, 811, 810, 808, 809, 805, 806, - 833, 832, 834, 835, 836, 837, 838, 839, 841, 840, - 842, 843, 844, 845, 846, 847, 815, 816, 819, 820, - 818, 817, 821, 830, 831, 822, 823, 824, 825, 826, - 827, 829, 828, 848, 849, 850, 851, 852, 854, 853, - 857, 858, 856, 855, 860, 859, 756, 196, 221, 366, - 94, 452, 288, 643, 612, 482, 607, 206, 223, 923, - 262, 924, 0, 0, 928, 0, 0, 0, 930, 929, - 0, 931, 893, 892, 0, 0, 925, 926, 0, 927, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 938, 939, 940, 941, 942, 943, - 944, 945, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 963, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 768, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 755, 0, 0, 0, 270, 760, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 767, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 762, 763, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 95, 0, 0, 1012, - 948, 739, 914, 952, 1013, 965, 966, 967, 953, 0, - 238, 954, 955, 245, 956, 0, 913, 798, 800, 799, - 863, 864, 865, 866, 867, 868, 869, 796, 961, 604, - 968, 969, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, - 0, 0, 0, 0, 735, 752, 0, 766, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 749, 750, - 0, 0, 0, 0, 908, 0, 751, 0, 0, 759, - 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, - 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, - 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, - 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, - 1010, 1011, 761, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 907, - 0, 0, 622, 0, 0, 905, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 958, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 4054, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 959, 960, 256, 645, 804, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 812, 813, 280, 307, 889, 888, 887, 306, 308, 885, - 886, 884, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 895, 917, 906, 772, 773, 896, - 897, 921, 898, 775, 776, 918, 919, 769, 770, 774, - 920, 922, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 909, 758, 757, 0, 764, 765, 0, 794, 795, 797, - 801, 802, 803, 814, 861, 862, 870, 872, 873, 871, - 874, 875, 876, 879, 880, 881, 882, 877, 878, 883, - 777, 781, 778, 779, 780, 792, 782, 783, 784, 785, - 786, 787, 788, 789, 790, 791, 793, 932, 933, 934, - 935, 936, 937, 807, 811, 810, 808, 809, 805, 806, - 833, 832, 834, 835, 836, 837, 838, 839, 841, 840, - 842, 843, 844, 845, 846, 847, 815, 816, 819, 820, - 818, 817, 821, 830, 831, 822, 823, 824, 825, 826, - 827, 829, 828, 848, 849, 850, 851, 852, 854, 853, - 857, 858, 856, 855, 860, 859, 756, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 923, - 262, 924, 0, 0, 928, 0, 0, 0, 930, 929, - 0, 931, 893, 892, 0, 0, 925, 926, 0, 927, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 938, 939, 940, 941, 942, 943, - 944, 945, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 963, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 768, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 755, 0, 0, 0, 270, 760, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 767, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 762, 763, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 95, 0, 1730, 1012, - 948, 739, 914, 952, 1013, 965, 966, 967, 953, 0, - 238, 954, 955, 245, 956, 0, 913, 798, 800, 799, - 863, 864, 865, 866, 867, 868, 869, 796, 961, 604, - 968, 969, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, - 0, 0, 0, 0, 735, 752, 0, 766, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 749, 750, - 0, 0, 0, 0, 908, 0, 751, 0, 0, 759, - 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, - 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, - 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, - 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, - 1010, 1011, 761, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 907, - 0, 0, 622, 0, 0, 905, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 958, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 959, 960, 256, 645, 804, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 812, 813, 280, 307, 889, 888, 887, 306, 308, 885, - 886, 884, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 895, 917, 906, 772, 773, 896, - 897, 921, 898, 775, 776, 918, 919, 769, 770, 774, - 920, 922, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 909, 758, 757, 0, 764, 765, 0, 794, 795, 797, - 801, 802, 803, 814, 861, 862, 870, 872, 873, 871, - 874, 875, 876, 879, 880, 881, 882, 877, 878, 883, - 777, 781, 778, 779, 780, 792, 782, 783, 784, 785, - 786, 787, 788, 789, 790, 791, 793, 932, 933, 934, - 935, 936, 937, 807, 811, 810, 808, 809, 805, 806, - 833, 832, 834, 835, 836, 837, 838, 839, 841, 840, - 842, 843, 844, 845, 846, 847, 815, 816, 819, 820, - 818, 817, 821, 830, 831, 822, 823, 824, 825, 826, - 827, 829, 828, 848, 849, 850, 851, 852, 854, 853, - 857, 858, 856, 855, 860, 859, 756, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 923, - 262, 924, 0, 0, 928, 0, 0, 0, 930, 929, - 0, 931, 893, 892, 0, 0, 925, 926, 0, 927, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 938, 939, 940, 941, 942, 943, - 944, 945, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 963, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 768, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 755, 0, 0, 0, 270, 760, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 767, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 762, 763, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 95, 0, 0, 1012, - 948, 739, 914, 952, 1013, 965, 966, 967, 953, 0, - 238, 954, 955, 245, 956, 0, 913, 798, 800, 799, - 863, 864, 865, 866, 867, 868, 869, 796, 961, 604, - 968, 969, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, - 0, 0, 0, 0, 735, 752, 0, 766, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 749, 750, - 1058, 0, 0, 0, 908, 0, 751, 0, 0, 759, - 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, - 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, - 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, - 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, - 1010, 1011, 761, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 907, - 0, 0, 622, 0, 0, 905, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 958, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 959, 960, 256, 645, 804, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 812, 813, 280, 307, 889, 888, 887, 306, 308, 885, - 886, 884, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 895, 917, 906, 772, 773, 896, - 897, 921, 898, 775, 776, 918, 919, 769, 770, 774, - 920, 922, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 909, 758, 757, 0, 764, 765, 0, 794, 795, 797, - 801, 802, 803, 814, 861, 862, 870, 872, 873, 871, - 874, 875, 876, 879, 880, 881, 882, 877, 878, 883, - 777, 781, 778, 779, 780, 792, 782, 783, 784, 785, - 786, 787, 788, 789, 790, 791, 793, 932, 933, 934, - 935, 936, 937, 807, 811, 810, 808, 809, 805, 806, - 833, 832, 834, 835, 836, 837, 838, 839, 841, 840, - 842, 843, 844, 845, 846, 847, 815, 816, 819, 820, - 818, 817, 821, 830, 831, 822, 823, 824, 825, 826, - 827, 829, 828, 848, 849, 850, 851, 852, 854, 853, - 857, 858, 856, 855, 860, 859, 756, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 923, - 262, 924, 0, 0, 928, 0, 0, 0, 930, 929, - 0, 931, 893, 892, 0, 0, 925, 926, 0, 927, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 938, 939, 940, 941, 942, 943, - 944, 945, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 963, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 768, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 755, 0, 0, 0, 270, 760, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 767, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 762, 763, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 95, 0, 0, 1012, - 948, 739, 914, 952, 1013, 965, 966, 967, 953, 0, - 238, 954, 955, 245, 956, 0, 913, 798, 800, 799, - 863, 864, 865, 866, 867, 868, 869, 796, 961, 604, - 968, 969, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, - 0, 0, 0, 0, 735, 752, 0, 766, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 749, 750, - 0, 0, 0, 0, 908, 0, 751, 0, 0, 759, - 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, - 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, - 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, - 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, - 1010, 1011, 761, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 907, - 0, 0, 622, 0, 0, 905, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 958, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 959, 960, 256, 645, 804, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 812, 813, 280, 307, 889, 888, 887, 306, 308, 885, - 886, 884, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 895, 917, 906, 772, 773, 896, - 897, 921, 898, 775, 776, 918, 919, 769, 770, 774, - 920, 922, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 909, 758, 757, 0, 764, 765, 0, 794, 795, 797, - 801, 802, 803, 814, 861, 862, 870, 872, 873, 871, - 874, 875, 876, 879, 880, 881, 882, 877, 878, 883, - 777, 781, 778, 779, 780, 792, 782, 783, 784, 785, - 786, 787, 788, 789, 790, 791, 793, 932, 933, 934, - 935, 936, 937, 807, 811, 810, 808, 809, 805, 806, - 833, 832, 834, 835, 836, 837, 838, 839, 841, 840, - 842, 843, 844, 845, 846, 847, 815, 816, 819, 820, - 818, 817, 821, 830, 831, 822, 823, 824, 825, 826, - 827, 829, 828, 848, 849, 850, 851, 852, 854, 853, - 857, 858, 856, 855, 860, 859, 756, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 923, - 262, 924, 0, 0, 928, 0, 0, 0, 930, 929, - 0, 931, 893, 892, 0, 0, 925, 926, 0, 927, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 938, 939, 940, 941, 942, 943, - 944, 945, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 963, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 768, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 755, 0, 0, 0, 270, 760, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 767, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 762, 763, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 95, 0, 0, 1012, - 948, 739, 914, 952, 1013, 965, 966, 967, 953, 0, - 238, 954, 955, 245, 956, 0, 913, 798, 800, 799, - 863, 864, 865, 866, 867, 868, 869, 796, 961, 604, - 968, 969, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, - 0, 0, 0, 0, 735, 752, 0, 766, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 749, 750, - 0, 0, 0, 0, 908, 0, 751, 0, 0, 759, - 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, - 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, - 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, - 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, - 1010, 1011, 3133, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 907, - 0, 0, 622, 0, 0, 905, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 958, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 959, 960, 256, 645, 804, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 812, 813, 280, 307, 889, 888, 887, 306, 308, 885, - 886, 884, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 895, 917, 906, 772, 773, 896, - 897, 921, 898, 775, 776, 918, 919, 769, 770, 774, - 920, 922, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 909, 758, 757, 0, 764, 765, 0, 794, 795, 797, - 801, 802, 803, 814, 861, 862, 870, 872, 873, 871, - 874, 875, 876, 879, 880, 881, 882, 877, 878, 883, - 777, 781, 778, 779, 780, 792, 782, 783, 784, 785, - 786, 787, 788, 789, 790, 791, 793, 932, 933, 934, - 935, 936, 937, 807, 811, 810, 808, 809, 805, 806, - 833, 832, 834, 835, 836, 837, 838, 839, 841, 840, - 842, 843, 844, 845, 846, 847, 815, 816, 819, 820, - 818, 817, 821, 830, 831, 822, 823, 824, 825, 826, - 827, 829, 828, 848, 849, 850, 851, 852, 854, 853, - 857, 858, 856, 855, 860, 859, 756, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 923, - 262, 924, 0, 0, 928, 0, 0, 0, 930, 929, - 0, 931, 893, 892, 0, 0, 925, 926, 0, 927, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 938, 939, 940, 941, 942, 943, - 944, 945, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 963, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 768, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 755, 0, 0, 0, 270, 760, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 767, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 762, 763, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 95, 0, 0, 1012, - 948, 739, 914, 952, 1013, 965, 966, 967, 953, 0, - 238, 954, 955, 245, 956, 0, 913, 798, 800, 799, - 863, 864, 865, 866, 867, 868, 869, 796, 961, 604, - 968, 969, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, - 0, 0, 0, 0, 735, 752, 0, 766, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 749, 750, - 0, 0, 0, 0, 908, 0, 751, 0, 0, 759, - 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, - 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, - 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, - 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, - 1010, 1011, 3129, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 907, - 0, 0, 622, 0, 0, 905, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 958, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 959, 960, 256, 645, 804, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 812, 813, 280, 307, 889, 888, 887, 306, 308, 885, - 886, 884, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 895, 917, 906, 772, 773, 896, - 897, 921, 898, 775, 776, 918, 919, 769, 770, 774, - 920, 922, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 909, 758, 757, 0, 764, 765, 0, 794, 795, 797, - 801, 802, 803, 814, 861, 862, 870, 872, 873, 871, - 874, 875, 876, 879, 880, 881, 882, 877, 878, 883, - 777, 781, 778, 779, 780, 792, 782, 783, 784, 785, - 786, 787, 788, 789, 790, 791, 793, 932, 933, 934, - 935, 936, 937, 807, 811, 810, 808, 809, 805, 806, - 833, 832, 834, 835, 836, 837, 838, 839, 841, 840, - 842, 843, 844, 845, 846, 847, 815, 816, 819, 820, - 818, 817, 821, 830, 831, 822, 823, 824, 825, 826, - 827, 829, 828, 848, 849, 850, 851, 852, 854, 853, - 857, 858, 856, 855, 860, 859, 756, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 923, - 262, 924, 0, 0, 928, 0, 0, 0, 930, 929, - 0, 931, 893, 892, 0, 0, 925, 926, 0, 927, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 938, 939, 940, 941, 942, 943, - 944, 945, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 963, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 768, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 755, 0, 0, 0, 270, 760, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 767, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 762, 763, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 95, 0, 0, 1012, - 948, 1079, 914, 952, 1013, 965, 966, 967, 953, 0, - 238, 954, 955, 245, 956, 0, 913, 798, 800, 799, - 863, 864, 865, 866, 867, 868, 869, 796, 961, 604, - 968, 969, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, - 0, 0, 0, 0, 0, 752, 0, 766, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 749, 750, - 0, 0, 0, 0, 908, 0, 751, 0, 0, 759, - 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, - 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, - 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, - 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, - 1010, 1011, 761, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 907, - 0, 0, 622, 0, 0, 905, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 958, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 959, 960, 256, 645, 804, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 812, 813, 280, 307, 889, 888, 887, 306, 308, 885, - 886, 884, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 895, 917, 906, 772, 773, 896, - 897, 921, 898, 775, 776, 918, 919, 769, 770, 774, - 920, 922, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 909, 758, 757, 0, 764, 765, 0, 794, 795, 797, - 801, 802, 803, 814, 861, 862, 870, 872, 873, 871, - 874, 875, 876, 879, 880, 881, 882, 877, 878, 883, - 777, 781, 778, 779, 780, 792, 782, 783, 784, 785, - 786, 787, 788, 789, 790, 791, 793, 932, 933, 934, - 935, 936, 937, 807, 811, 810, 808, 809, 805, 806, - 833, 832, 834, 835, 836, 837, 838, 839, 841, 840, - 842, 843, 844, 845, 846, 847, 815, 816, 819, 820, - 818, 817, 821, 830, 831, 822, 823, 824, 825, 826, - 827, 829, 828, 848, 849, 850, 851, 852, 854, 853, - 857, 858, 856, 855, 860, 859, 756, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 923, - 262, 924, 0, 0, 928, 0, 0, 0, 930, 929, - 0, 931, 893, 892, 0, 0, 925, 926, 0, 927, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 938, 939, 940, 941, 942, 943, - 944, 945, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 963, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 768, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 755, 0, 0, 0, 270, 760, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 767, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 762, 763, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 95, 0, 0, 1012, - 948, 1079, 914, 952, 1013, 965, 966, 967, 953, 0, - 238, 954, 955, 245, 956, 0, 913, 798, 800, 799, - 863, 864, 865, 866, 867, 868, 869, 796, 961, 604, - 968, 969, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, - 0, 0, 0, 0, 0, 752, 0, 766, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 749, 750, - 0, 0, 0, 0, 908, 0, 751, 0, 0, 759, - 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, - 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, - 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, - 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, - 1010, 1011, 2094, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 907, - 0, 0, 622, 0, 0, 905, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 958, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 959, 960, 256, 645, 804, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 812, 813, 280, 307, 889, 888, 887, 306, 308, 885, - 886, 884, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 895, 917, 906, 772, 773, 896, - 897, 921, 898, 775, 776, 918, 919, 769, 770, 774, - 920, 922, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 909, 758, 757, 0, 764, 765, 0, 794, 795, 797, - 801, 802, 803, 814, 861, 862, 870, 872, 873, 871, - 874, 875, 876, 879, 880, 881, 882, 877, 878, 883, - 777, 781, 778, 779, 780, 792, 782, 783, 784, 785, - 786, 787, 788, 789, 790, 791, 793, 932, 933, 934, - 935, 936, 937, 807, 811, 810, 808, 809, 805, 806, - 833, 832, 834, 835, 836, 837, 838, 839, 841, 840, - 842, 843, 844, 845, 846, 847, 815, 816, 819, 820, - 818, 817, 821, 830, 831, 822, 823, 824, 825, 826, - 827, 829, 828, 848, 849, 850, 851, 852, 854, 853, - 857, 858, 856, 855, 860, 859, 756, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 923, - 262, 924, 0, 0, 928, 0, 0, 0, 930, 929, - 0, 931, 893, 892, 0, 0, 925, 926, 0, 927, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 938, 939, 940, 941, 942, 943, - 944, 945, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 963, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 768, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 755, 0, 0, 0, 270, 760, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 767, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 762, 763, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 95, 0, 0, 1012, - 948, 1079, 914, 952, 1013, 965, 966, 967, 953, 0, - 238, 954, 955, 245, 956, 0, 913, 798, 800, 799, - 863, 864, 865, 866, 867, 868, 869, 796, 961, 604, - 968, 969, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, - 0, 0, 0, 0, 0, 752, 0, 766, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 749, 750, - 0, 0, 0, 0, 908, 0, 751, 0, 0, 759, - 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, - 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, - 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, - 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, - 1010, 1011, 2092, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 907, - 0, 0, 622, 0, 0, 905, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 958, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 959, 960, 256, 645, 804, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 812, 813, 280, 307, 889, 888, 887, 306, 308, 885, - 886, 884, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 895, 917, 906, 772, 773, 896, - 897, 921, 898, 775, 776, 918, 919, 769, 770, 774, - 920, 922, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 909, 758, 757, 0, 764, 765, 0, 794, 795, 797, - 801, 802, 803, 814, 861, 862, 870, 872, 873, 871, - 874, 875, 876, 879, 880, 881, 882, 877, 878, 883, - 777, 781, 778, 779, 780, 792, 782, 783, 784, 785, - 786, 787, 788, 789, 790, 791, 793, 932, 933, 934, - 935, 936, 937, 807, 811, 810, 808, 809, 805, 806, - 833, 832, 834, 835, 836, 837, 838, 839, 841, 840, - 842, 843, 844, 845, 846, 847, 815, 816, 819, 820, - 818, 817, 821, 830, 831, 822, 823, 824, 825, 826, - 827, 829, 828, 848, 849, 850, 851, 852, 854, 853, - 857, 858, 856, 855, 860, 859, 756, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 923, - 262, 924, 0, 0, 928, 0, 0, 0, 930, 929, - 0, 931, 893, 892, 0, 0, 925, 926, 0, 927, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 938, 939, 940, 941, 942, 943, - 944, 945, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 963, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 1130, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 1129, 622, 0, 0, 0, 0, 0, 1126, 1127, - 363, 1087, 330, 197, 225, 1120, 1124, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 1691, - 948, 0, 0, 1688, 0, 0, 0, 0, 1686, 0, - 238, 1687, 1685, 245, 1690, 0, 913, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 86, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 95, 0, 0, 0, - 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 94, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 2395, 0, 0, - 2394, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 1753, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 1755, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 1757, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, - 1461, 0, 1462, 1463, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 86, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 95, 0, 1730, 0, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 94, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 95, 0, 0, 0, - 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 2395, 0, 0, - 2394, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 2342, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 1936, - 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 2340, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, - 1081, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 1087, 330, 197, 225, 1085, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 2342, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 1936, - 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 969, 3688, 3689, 87, 3687, 4018, 4204, 957, 4108, 4127, + 2138, 3351, 3487, 4000, 4217, 4096, 3923, 4171, 1280, 964, + 3637, 956, 2126, 3251, 4172, 3258, 2362, 1278, 3309, 3300, + 2434, 3314, 3311, 3310, 3212, 3308, 3313, 3312, 3998, 3065, + 2064, 3150, 2006, 5, 3624, 3266, 3329, 748, 2509, 3216, + 3213, 3328, 3533, 3527, 3039, 3064, 2364, 3210, 3730, 742, + 2389, 743, 3517, 3200, 918, 2472, 3021, 3331, 2940, 1797, + 2866, 776, 1089, 2972, 2477, 2941, 2540, 2497, 4069, 1753, + 917, 2942, 3358, 163, 2891, 2408, 1037, 2422, 87, 1057, + 2410, 43, 1034, 2409, 2872, 2858, 1064, 1135, 2842, 2160, + 2405, 1901, 1854, 41, 2318, 2286, 2122, 1037, 2072, 3013, + 1883, 2285, 2518, 149, 3555, 2397, 2557, 2479, 2933, 1122, + 1117, 1786, 1099, 2908, 2496, 1766, 2412, 100, 1714, 1533, + 2166, 2097, 104, 2086, 1458, 105, 1443, 2002, 1890, 1096, + 1093, 1125, 1128, 2494, 1982, 1097, 758, 2468, 2469, 1123, + 3215, 1124, 1785, 2390, 1046, 753, 1074, 1076, 1771, 1736, + 2174, 2193, 1516, 99, 1492, 2879, 3725, 2063, 745, 2840, + 107, 1043, 1268, 2014, 85, 167, 127, 125, 126, 1042, + 132, 3488, 3717, 1875, 133, 1208, 93, 1044, 3544, 1056, + 1069, 1041, 106, 84, 1032, 735, 752, 98, 4205, 1537, + 922, 3625, 746, 42, 3297, 4053, 1276, 2511, 2963, 1068, + 1254, 2511, 2512, 2513, 919, 679, 2995, 2994, 2555, 1459, + 3617, 4154, 1031, 3029, 3030, 1542, 3580, 1049, 128, 4049, + 4048, 4054, 2359, 2360, 1139, 2079, 2078, 134, 1164, 1090, + 2077, 2076, 2075, 2074, 2045, 1224, 4148, 676, 3692, 677, + 2838, 2607, 3196, 4175, 1757, 1755, 1172, 3154, 4210, 2, + 1106, 3692, 1101, 4195, 1050, 4158, 4227, 1967, 736, 4156, + 1084, 4170, 1083, 3491, 2868, 2542, 2544, 1033, 1138, 1035, + 3490, 2386, 1114, 4209, 1758, 1756, 1036, 2385, 1040, 2988, + 4157, 1475, 4001, 1058, 4155, 2803, 1159, 1165, 1168, 1169, + 128, 1113, 1112, 1111, 111, 112, 113, 1059, 116, 1454, + 3319, 122, 4027, 3319, 191, 2965, 95, 671, 95, 1225, + 2543, 1181, 2084, 3316, 1747, 3377, 720, 1469, 4123, 733, + 734, 4049, 3919, 95, 714, 3918, 2383, 1163, 2100, 1025, + 1026, 1027, 1028, 86, 3691, 3630, 1039, 1030, 3631, 4185, + 1162, 923, 3929, 4152, 3649, 95, 3638, 3691, 1445, 720, + 972, 973, 974, 4097, 4105, 2537, 2882, 3928, 128, 2131, + 3317, 4132, 2985, 3317, 1071, 1072, 1115, 972, 973, 974, + 3403, 1082, 1086, 921, 1864, 3248, 3249, 1261, 2839, 1263, + 1082, 1086, 921, 3247, 2883, 3002, 3028, 3003, 2917, 3323, + 2611, 2916, 3323, 2428, 2918, 4137, 1787, 714, 1788, 86, + 86, 1211, 3012, 4109, 3648, 2429, 2430, 2056, 2057, 1244, + 1023, 1249, 1250, 1273, 1022, 4135, 95, 1260, 1262, 714, + 2966, 4019, 2614, 1245, 2929, 4141, 4142, 1465, 714, 1472, + 1457, 1473, 1474, 2010, 3268, 3269, 1238, 3355, 1161, 1232, + 710, 4136, 1207, 3353, 1233, 1105, 2447, 2446, 1107, 3530, + 3744, 1178, 1179, 1180, 3385, 1183, 1184, 1185, 1186, 2875, + 2876, 1189, 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197, + 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 714, 4113, + 714, 2605, 95, 95, 3383, 3086, 1459, 86, 695, 1471, + 88, 728, 2612, 2055, 2202, 2361, 4113, 4176, 4032, 1232, + 714, 693, 2488, 3320, 1233, 2059, 3320, 732, 1455, 714, + 1783, 1444, 1231, 726, 1230, 3359, 3014, 1251, 4177, 1246, + 1110, 2393, 1217, 1218, 1272, 1258, 2482, 1252, 1718, 1259, + 1271, 3356, 1239, 3971, 2519, 3972, 715, 3354, 2973, 1264, + 3346, 690, 1182, 3267, 2998, 2564, 2558, 1110, 3347, 1102, + 705, 1957, 2393, 1438, 1220, 3270, 1104, 1103, 1493, 4207, + 1983, 1213, 1110, 1206, 1257, 700, 2608, 2582, 2609, 2583, + 95, 2584, 2011, 1247, 1248, 1265, 703, 1270, 1108, 713, + 3374, 3016, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1502, + 1501, 1503, 1504, 2194, 1469, 1958, 1253, 1959, 2196, 2562, + 2565, 1075, 2201, 2197, 3619, 1108, 2198, 2199, 2200, 715, + 3618, 2195, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, + 2211, 3615, 2585, 1188, 3903, 1187, 1118, 1210, 2560, 2522, + 1119, 715, 3696, 2406, 1119, 3270, 4149, 1157, 1156, 1155, + 715, 2561, 1154, 1153, 1152, 680, 1151, 682, 696, 1721, + 717, 3087, 716, 686, 2563, 684, 688, 697, 689, 3153, + 683, 1150, 694, 1145, 1868, 685, 698, 699, 702, 706, + 707, 708, 704, 701, 1158, 692, 718, 4228, 2481, 2571, + 2567, 2569, 2570, 2568, 2572, 2573, 2574, 1094, 1094, 1167, + 715, 1092, 715, 1131, 4182, 1130, 1085, 1079, 1077, 1166, + 1277, 1094, 1277, 1277, 1465, 1085, 1079, 1077, 1109, 1130, + 2003, 2495, 715, 1070, 2391, 2392, 3017, 2548, 2547, 1999, + 1446, 715, 2967, 1464, 1461, 1462, 1463, 1468, 1470, 1467, + 3290, 1466, 1175, 2997, 1209, 1109, 3614, 3000, 1862, 1861, + 1784, 1460, 2541, 1860, 2983, 2391, 2392, 2000, 1858, 1223, + 1109, 1037, 1517, 1522, 1523, 3531, 1526, 1528, 1529, 1530, + 1531, 1532, 670, 1535, 1536, 1538, 1538, 4150, 1538, 1538, + 1543, 1543, 1543, 1546, 1547, 1548, 1549, 1550, 1551, 1552, + 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562, + 1563, 1564, 1565, 1566, 1567, 1568, 1569, 1570, 1571, 1572, + 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1581, 1582, + 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, + 1593, 1594, 1595, 1596, 1597, 1598, 1599, 1600, 1601, 1602, + 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, 1514, 1116, 4026, + 1266, 1670, 2964, 1672, 1673, 1674, 1675, 1676, 1436, 1437, + 3690, 3578, 3579, 3647, 94, 1543, 1543, 1543, 1543, 1543, + 1543, 1435, 1219, 3690, 1216, 1527, 4140, 970, 4111, 970, + 1683, 1684, 1685, 1686, 1687, 1688, 1689, 1690, 1691, 1692, + 1693, 1694, 1695, 1696, 970, 4111, 1229, 1510, 1511, 1512, + 1513, 719, 1969, 1968, 1970, 1971, 1972, 1524, 89, 1453, + 4110, 1711, 2931, 3475, 1889, 1539, 1518, 1540, 1541, 2987, + 4139, 1137, 711, 1078, 1137, 3321, 3322, 4110, 3321, 3322, + 94, 94, 1078, 1148, 1146, 1507, 4072, 712, 3325, 2613, + 1228, 3325, 1234, 1235, 1236, 1237, 1544, 1545, 3375, 1507, + 1464, 1461, 1462, 1463, 1468, 1470, 1467, 2612, 1466, 2485, + 2843, 2845, 4014, 2986, 1242, 1717, 1274, 1275, 1460, 1137, + 3011, 3020, 3569, 3010, 1037, 1508, 1509, 2539, 1037, 3551, + 1746, 2913, 2878, 2815, 1037, 1988, 2134, 1775, 1671, 1222, + 3162, 3254, 86, 44, 45, 88, 1987, 3161, 2873, 4221, + 2486, 124, 678, 2435, 1507, 911, 1137, 2484, 1504, 1174, + 3246, 92, 2175, 1709, 1747, 48, 76, 77, 94, 74, + 78, 3033, 2640, 1888, 1136, 1487, 1137, 1136, 1255, 2176, + 1053, 75, 1269, 4040, 119, 2629, 2015, 1160, 3610, 2167, + 2956, 2487, 3255, 1497, 1498, 1499, 1500, 1502, 1501, 1503, + 1504, 2483, 1499, 1500, 1502, 1501, 1503, 1504, 3543, 1227, + 2559, 193, 2102, 62, 674, 3181, 1727, 3257, 3179, 1728, + 104, 2068, 1136, 105, 1996, 95, 2103, 1505, 1506, 2101, + 1789, 1709, 1149, 1147, 674, 3060, 4186, 3252, 1474, 1715, + 1677, 1678, 1679, 1680, 1681, 1682, 2167, 2640, 2649, 3739, + 1047, 1702, 2090, 2091, 2088, 2089, 3268, 3269, 107, 1136, + 1708, 120, 1475, 3253, 1140, 1130, 3040, 1067, 1067, 1142, + 1473, 1474, 2531, 1143, 1141, 83, 674, 3023, 2087, 1136, + 2536, 1137, 3022, 2844, 3585, 1130, 1133, 1134, 1881, 1094, + 1475, 3023, 3584, 1127, 1131, 1749, 3022, 3259, 2526, 1898, + 1984, 1897, 1985, 1887, 2645, 1986, 2534, 1712, 2531, 1148, + 1724, 1146, 1723, 4178, 1126, 2535, 3570, 2173, 1033, 4073, + 1726, 1891, 1891, 1752, 1725, 1874, 1048, 1035, 1729, 1241, + 1977, 2008, 1934, 2538, 1036, 1256, 1893, 1903, 1952, 1904, + 1243, 1906, 1908, 2016, 1212, 1912, 1914, 1916, 1918, 1920, + 3042, 2533, 1780, 1781, 1992, 1277, 1990, 1991, 1989, 1993, + 1994, 1995, 1226, 1892, 1849, 3267, 4223, 1475, 4074, 51, + 54, 57, 56, 59, 1137, 73, 1857, 3270, 82, 79, + 4219, 3911, 2644, 4220, 1136, 4218, 1173, 1475, 1730, 4229, + 1170, 1872, 3910, 4006, 1871, 1870, 1137, 1747, 3901, 1884, + 1475, 1976, 61, 91, 90, 2172, 3661, 71, 72, 58, + 1472, 2676, 1473, 1474, 2686, 80, 81, 3660, 3644, 1938, + 3645, 3052, 3051, 3050, 3592, 1975, 3044, 1964, 3048, 3591, + 3043, 3581, 3041, 2090, 2091, 2619, 2620, 3046, 1472, 3298, + 1473, 1474, 4007, 1895, 3286, 2938, 3045, 2004, 1481, 1482, + 1483, 1484, 1485, 1486, 1480, 1477, 1863, 2937, 63, 64, + 2323, 65, 66, 67, 68, 3047, 3049, 972, 973, 974, + 1930, 2936, 2491, 1933, 1978, 1935, 1475, 1136, 128, 1113, + 1112, 1111, 1140, 1130, 1962, 4230, 1961, 1142, 3350, 1960, + 1950, 1143, 1141, 1747, 1944, 3256, 1974, 1941, 1963, 1136, + 2636, 1865, 1866, 1867, 2021, 1130, 1133, 1134, 1940, 1094, + 1939, 1910, 1144, 1127, 1131, 1472, 1722, 1473, 1474, 1475, + 3575, 1440, 720, 60, 3062, 1277, 1277, 720, 2043, 2323, + 1783, 2017, 2018, 2320, 2920, 1472, 720, 1473, 1474, 2507, + 87, 2506, 2322, 87, 2505, 2022, 2504, 2503, 1472, 2502, + 1473, 1474, 2029, 2030, 2031, 2688, 4179, 1493, 968, 1760, + 1489, 2042, 1490, 2864, 4206, 1471, 1747, 1747, 1942, 1943, + 4028, 1493, 2161, 3032, 1948, 1949, 1491, 1505, 1506, 1488, + 4035, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1502, 1501, + 1503, 1504, 4034, 190, 4010, 1494, 1495, 1496, 1497, 1498, + 1499, 1500, 1502, 1501, 1503, 1504, 4009, 4008, 1761, 1493, + 3906, 4191, 1747, 89, 4166, 1747, 129, 3938, 2129, 2129, + 2127, 2127, 2130, 1475, 1472, 3890, 1473, 1474, 2864, 1747, + 2092, 2690, 172, 1494, 1495, 1496, 1497, 1498, 1499, 1500, + 1502, 1501, 1503, 1504, 1471, 1747, 1475, 738, 2019, 3889, + 110, 2864, 4104, 2864, 4083, 2023, 1493, 2025, 2026, 2027, + 2028, 109, 3738, 108, 2032, 3736, 2213, 1472, 3657, 1473, + 1474, 103, 1493, 1475, 2628, 1707, 2044, 1706, 2922, 1705, + 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1502, 1501, 1503, + 1504, 3589, 169, 2864, 4079, 170, 1494, 1495, 1496, 1497, + 1498, 1499, 1500, 1502, 1501, 1503, 1504, 3574, 101, 3360, + 2069, 85, 3991, 1747, 85, 4189, 1747, 1475, 102, 3357, + 2162, 189, 1709, 94, 3289, 2099, 3628, 4025, 3914, 1747, + 3937, 2050, 2051, 3288, 110, 2947, 1747, 3260, 4119, 1747, + 42, 3264, 2934, 42, 2104, 109, 1475, 108, 3263, 2105, + 1704, 2107, 2108, 2109, 2110, 2111, 2112, 2114, 2116, 2117, + 2118, 2119, 2120, 2121, 2861, 4117, 1747, 2864, 3902, 103, + 2133, 1472, 1697, 1473, 1474, 2237, 2603, 1475, 103, 1747, + 2333, 1475, 3265, 2595, 2106, 101, 2594, 3261, 2553, 2331, + 2552, 103, 3262, 2388, 1472, 102, 1473, 1474, 2177, 2178, + 2179, 2180, 3628, 1747, 2332, 2367, 1475, 2398, 2399, 4115, + 1747, 3894, 2191, 2321, 2864, 3626, 2212, 2046, 2319, 1708, + 1747, 1472, 1518, 1473, 1474, 2012, 674, 1973, 674, 1965, + 70, 1475, 2531, 1747, 1747, 173, 2229, 1955, 3984, 1747, + 2168, 1475, 2859, 190, 179, 1494, 1495, 1496, 1497, 1498, + 1499, 1500, 1502, 1501, 1503, 1504, 1747, 3549, 1747, 1475, + 2330, 2770, 1747, 2336, 2337, 1472, 129, 1473, 1474, 3982, + 1747, 2414, 1495, 1496, 1497, 1498, 1499, 1500, 1502, 1501, + 1503, 1504, 172, 1475, 2333, 3279, 3278, 2909, 104, 674, + 1951, 105, 1947, 2331, 1472, 1946, 1473, 1474, 3979, 1747, + 3893, 1475, 3276, 3277, 3274, 3275, 2909, 2366, 2403, 104, + 1945, 1475, 105, 3274, 3273, 2888, 1747, 1521, 2444, 2378, + 2612, 2996, 3546, 3961, 1747, 1472, 1762, 1473, 1474, 1472, + 2098, 1473, 1474, 3516, 1747, 1853, 2977, 2970, 2971, 2864, + 2863, 2880, 169, 1267, 1099, 170, 2132, 1747, 1853, 1852, + 3636, 3509, 1747, 1475, 1472, 2910, 1473, 1474, 2439, 2453, + 2454, 2455, 2456, 2354, 2880, 2912, 109, 1049, 2438, 2974, + 164, 189, 2952, 1475, 2910, 3506, 1747, 1099, 3241, 1472, + 2420, 1473, 1474, 1475, 2612, 2379, 1795, 1794, 2612, 1472, + 3545, 1473, 1474, 3504, 1747, 2448, 2381, 2449, 2450, 2451, + 2452, 3211, 2887, 3933, 2474, 2442, 2372, 1472, 2373, 1473, + 1474, 2458, 3542, 1475, 2460, 2461, 2462, 2463, 2888, 2520, + 2480, 2401, 2532, 2443, 3542, 1471, 1084, 2426, 1083, 2425, + 2424, 1472, 4067, 1473, 1474, 2441, 4039, 2440, 2864, 2888, + 1471, 3542, 2158, 2517, 3495, 3467, 1747, 3276, 3184, 1472, + 3593, 1473, 1474, 2427, 2770, 2673, 2672, 2531, 2514, 1472, + 2490, 1473, 1474, 2888, 2396, 3465, 1747, 1139, 1751, 2357, + 2132, 2416, 2070, 1475, 2054, 3461, 1747, 1891, 1998, 1782, + 2475, 2464, 2466, 2467, 2471, 173, 2531, 1121, 2525, 2489, + 1475, 2528, 2493, 2529, 179, 1120, 2545, 2501, 1475, 95, + 4145, 1472, 4086, 1473, 1474, 3458, 1747, 3594, 3595, 3596, + 1475, 1138, 1926, 1038, 1475, 2475, 2524, 2523, 2527, 3925, + 1521, 1472, 1475, 1473, 1474, 1754, 1475, 3891, 3751, 3609, + 3606, 1472, 3587, 1473, 1474, 2549, 3392, 2546, 1475, 2550, + 2551, 2150, 2139, 2140, 2141, 2142, 2152, 2143, 2144, 2145, + 2157, 2153, 2146, 2147, 2154, 2155, 2156, 2148, 2149, 2151, + 3408, 1472, 3407, 1473, 1474, 3456, 1747, 1855, 2473, 1927, + 1928, 1929, 1748, 1750, 3348, 2617, 3303, 3299, 674, 2556, + 2978, 3597, 3454, 1747, 1037, 1037, 1037, 2470, 2465, 3352, + 3452, 1747, 1475, 2459, 2457, 1980, 95, 1886, 1475, 1882, + 1851, 1047, 3450, 1747, 1528, 1475, 1528, 1747, 121, 165, + 3301, 2944, 2943, 1211, 3448, 1747, 177, 3926, 3446, 1747, + 164, 1472, 2632, 1473, 1474, 674, 3556, 3557, 2588, 2488, + 3444, 1747, 2370, 1475, 3598, 3599, 3600, 1475, 1472, 4201, + 1473, 1474, 1475, 2333, 674, 4199, 1472, 4173, 1473, 1474, + 4047, 3966, 2635, 3559, 3295, 2048, 3294, 185, 1472, 1475, + 1473, 1474, 1472, 3293, 1473, 1474, 2944, 2332, 3211, 2957, + 1472, 2589, 1473, 1474, 1472, 1475, 1473, 1474, 3562, 3561, + 3230, 2604, 3233, 1475, 3442, 1747, 1472, 3234, 1473, 1474, + 3440, 1747, 3229, 4043, 1521, 2610, 675, 3438, 1747, 1475, + 166, 171, 168, 174, 175, 176, 178, 180, 181, 182, + 183, 2618, 1475, 3927, 2387, 2638, 184, 186, 187, 188, + 1764, 1521, 2049, 2624, 1521, 2637, 1521, 674, 3231, 3564, + 2621, 2622, 2623, 3232, 3436, 1747, 1759, 2376, 2099, 3716, + 1472, 3715, 1473, 1474, 1922, 4005, 1472, 1953, 1473, 1474, + 1051, 3434, 1747, 1472, 3550, 1473, 1474, 3235, 3729, 2897, + 2898, 2625, 674, 2627, 3189, 1475, 3188, 3432, 1747, 3731, + 737, 3538, 2630, 3198, 2631, 3430, 1747, 1475, 2007, 674, + 1997, 1472, 1475, 1473, 1474, 1472, 2648, 1473, 1474, 1021, + 1472, 1763, 1473, 1474, 3714, 674, 2626, 1923, 1924, 1925, + 3535, 1052, 674, 3272, 3428, 1747, 2927, 1472, 3534, 1473, + 1474, 2033, 2034, 674, 674, 674, 674, 674, 674, 674, + 3201, 3203, 2814, 1472, 2948, 1473, 1474, 2597, 2598, 3204, + 1475, 1472, 2600, 1473, 1474, 1054, 2175, 2633, 2095, 2093, + 2094, 2601, 2684, 1055, 2581, 2580, 2802, 1472, 1475, 1473, + 1474, 1063, 2579, 2176, 2846, 1475, 2578, 3511, 1493, 165, + 1472, 2577, 1473, 1474, 2576, 1062, 177, 1177, 2575, 3414, + 1747, 1176, 3368, 1037, 3390, 1747, 2943, 3026, 2129, 1475, + 2127, 2849, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1502, + 1501, 1503, 1504, 1475, 1439, 2984, 2885, 2886, 129, 3540, + 1475, 2398, 2399, 3518, 101, 2414, 103, 185, 1037, 2905, + 103, 101, 2847, 1472, 102, 1473, 1474, 4215, 2850, 3291, + 2852, 102, 2835, 1747, 110, 1472, 2592, 1473, 1474, 1475, + 1472, 4122, 1473, 1474, 4024, 109, 2884, 108, 3921, 2865, + 2833, 1747, 1710, 2098, 1475, 103, 3271, 2808, 1747, 2901, + 166, 171, 168, 174, 175, 176, 178, 180, 181, 182, + 183, 2382, 3187, 2616, 2053, 108, 184, 186, 187, 188, + 3186, 2785, 1747, 1475, 1715, 3990, 2837, 2874, 1472, 3989, + 1473, 1474, 3969, 3737, 3735, 2777, 1747, 3734, 3727, 1475, + 2903, 110, 2768, 1747, 3607, 2857, 1472, 3539, 1473, 1474, + 2930, 2932, 109, 1472, 108, 1473, 1474, 1475, 1709, 3537, + 3304, 2923, 2877, 674, 2515, 1869, 1061, 110, 2907, 2862, + 109, 2766, 1747, 2982, 2880, 3726, 3700, 1472, 109, 1473, + 1474, 3528, 2861, 1475, 3090, 2911, 2753, 1747, 2674, 2914, + 2368, 1472, 1776, 1473, 1474, 1768, 2480, 2921, 1472, 2924, + 1473, 1474, 1475, 2893, 2896, 2897, 2898, 2894, 4202, 2895, + 2899, 2158, 4203, 3556, 3557, 2751, 1747, 4011, 2935, 2170, + 2993, 4203, 4202, 1521, 2171, 114, 115, 1472, 3573, 1473, + 1474, 2749, 1747, 3, 2067, 2065, 2945, 10, 9, 97, + 2066, 1521, 1472, 8, 1473, 1474, 42, 1475, 2953, 3507, + 2954, 1, 1029, 1475, 1442, 2902, 1441, 3577, 2904, 4134, + 2990, 1475, 2233, 2958, 2959, 2960, 691, 2358, 1874, 1713, + 4174, 1472, 4130, 1473, 1474, 2747, 1747, 2979, 2980, 4131, + 1966, 3036, 3037, 1956, 3639, 2284, 1475, 1472, 3922, 1473, + 1474, 3307, 2521, 3605, 2745, 1747, 2478, 1129, 2989, 154, + 2436, 2437, 4099, 118, 1475, 1472, 1087, 1473, 1474, 117, + 2150, 2139, 2140, 2141, 2142, 2152, 2143, 2144, 2145, 2157, + 2153, 2146, 2147, 2154, 2155, 2156, 2148, 2149, 2151, 3015, + 3034, 1472, 3053, 1473, 1474, 1132, 1240, 3018, 2516, 2743, + 1747, 3629, 2316, 2928, 2445, 2741, 1747, 1475, 1801, 1799, + 1472, 1800, 1473, 1474, 1747, 1798, 3071, 3072, 3073, 3074, + 3075, 3076, 3077, 3078, 3079, 3080, 1803, 1475, 1802, 4071, + 3376, 1475, 2348, 2675, 3474, 2058, 3088, 2007, 2739, 1747, + 2893, 2896, 2897, 2898, 2894, 3054, 2895, 2899, 727, 2900, + 1748, 2355, 721, 192, 1790, 1472, 3473, 1473, 1474, 1769, + 2052, 1472, 2991, 1473, 1474, 1171, 681, 1475, 3280, 1472, + 2554, 1473, 1474, 687, 1525, 2047, 3185, 1475, 2946, 2915, + 1081, 1073, 1953, 2949, 2950, 2369, 2851, 1080, 3899, 3219, + 2380, 3532, 3197, 3199, 1472, 3092, 1473, 1474, 1067, 2737, + 1747, 3038, 2867, 3202, 3148, 3195, 4004, 3024, 3728, 3055, + 3025, 1475, 1472, 4084, 1473, 1474, 2925, 1047, 1475, 2735, + 1747, 1765, 3494, 2733, 1747, 2647, 2165, 1515, 2413, 3695, + 2085, 750, 3035, 749, 674, 747, 2853, 2881, 1479, 1478, + 958, 2007, 674, 3166, 674, 3155, 674, 2423, 2841, 3157, + 1777, 2892, 2969, 1475, 2890, 1472, 2889, 1473, 1474, 2731, + 1747, 2590, 2414, 2421, 3558, 3081, 2321, 3554, 2321, 2729, + 1747, 2319, 4126, 2319, 2415, 1472, 3128, 1473, 1474, 1472, + 1475, 1473, 1474, 2411, 3218, 1475, 87, 2860, 909, 2414, + 2414, 2414, 2414, 2414, 1475, 908, 759, 2492, 3138, 3139, + 3140, 3141, 3142, 2727, 1747, 751, 3166, 741, 971, 2414, + 3469, 3156, 2414, 3158, 3165, 1472, 907, 1473, 1474, 906, + 3334, 3335, 3223, 2999, 3349, 1472, 1475, 1473, 1474, 3001, + 2926, 3345, 2008, 3240, 1456, 1732, 1735, 2377, 1100, 3373, + 3177, 3178, 3180, 3182, 4030, 2725, 1747, 3193, 3183, 2615, + 3402, 1731, 4037, 3190, 3315, 1475, 3192, 3623, 3296, 1472, + 2975, 1473, 1474, 2508, 3205, 3206, 1472, 1475, 1473, 1474, + 69, 46, 2723, 1747, 3999, 4068, 3324, 1042, 4180, 1475, + 3225, 3226, 3224, 3228, 3236, 3227, 3332, 4023, 3222, 1041, + 901, 898, 104, 3697, 3242, 105, 3698, 3243, 3699, 3151, + 3244, 1472, 3152, 1473, 1474, 4050, 3250, 4051, 897, 4052, + 2222, 1710, 1452, 1449, 4147, 1475, 3281, 2060, 3283, 3898, + 96, 1475, 36, 3282, 3191, 35, 34, 33, 1472, 32, + 1473, 1474, 26, 1472, 25, 1473, 1474, 24, 23, 22, + 29, 1475, 1472, 3305, 1473, 1474, 674, 2721, 1747, 19, + 3336, 21, 3326, 674, 20, 2480, 1475, 3333, 2227, 2719, + 1747, 18, 2416, 3343, 674, 674, 3337, 3318, 674, 3208, + 2593, 2714, 1747, 4169, 1472, 4214, 1473, 1474, 123, 55, + 674, 52, 50, 131, 130, 3363, 1040, 674, 3364, 2416, + 2416, 2416, 2416, 2416, 3371, 53, 49, 3214, 3361, 1214, + 47, 1475, 3214, 1472, 31, 1473, 1474, 2710, 1747, 2416, + 3381, 30, 2416, 674, 3611, 1472, 17, 1473, 1474, 16, + 15, 14, 3397, 3398, 3399, 3400, 3401, 1472, 13, 1473, + 1474, 12, 11, 2708, 1747, 7, 6, 39, 2310, 2311, + 2312, 2313, 2314, 3378, 3379, 38, 3380, 37, 3405, 3382, + 28, 3384, 27, 3386, 40, 2335, 4, 2962, 2338, 2339, + 1528, 2510, 0, 1472, 1528, 1473, 1474, 0, 0, 1472, + 0, 1473, 1474, 0, 2634, 0, 0, 0, 2639, 0, + 3519, 0, 3521, 0, 0, 0, 0, 0, 3306, 1472, + 3489, 1473, 1474, 3404, 2356, 0, 0, 3493, 1521, 0, + 2007, 2642, 0, 2643, 1472, 0, 1473, 1474, 0, 2651, + 0, 0, 0, 2653, 2654, 0, 0, 0, 0, 0, + 0, 0, 2660, 2661, 2662, 2663, 2664, 2665, 2666, 2667, + 2668, 2669, 0, 2671, 0, 3217, 3372, 0, 0, 0, + 3284, 3285, 2414, 3520, 3524, 3522, 0, 0, 0, 1472, + 0, 1473, 1474, 0, 0, 3571, 2677, 2678, 2679, 2680, + 0, 2682, 2683, 3536, 2685, 1475, 3529, 0, 2687, 1475, + 3541, 0, 2692, 2693, 0, 2694, 0, 1475, 2697, 2698, + 2700, 2702, 2703, 2704, 2705, 2706, 2707, 2709, 2711, 2712, + 2713, 2715, 739, 2717, 2718, 2720, 2722, 2724, 2726, 2728, + 2730, 2732, 2734, 2736, 2738, 2740, 2742, 2744, 2746, 2748, + 2750, 2752, 2754, 2755, 2756, 3327, 2758, 3563, 2760, 3336, + 2762, 2763, 3572, 2765, 2767, 2769, 3333, 3566, 3496, 2772, + 3498, 3499, 3500, 2776, 3588, 3337, 3590, 2781, 2782, 2783, + 2784, 3565, 3560, 1475, 3366, 3367, 3633, 3634, 1475, 0, + 2795, 2796, 2797, 2798, 2799, 2800, 3526, 3396, 2804, 2805, + 0, 2701, 1747, 0, 1475, 0, 2807, 0, 0, 2699, + 1747, 2813, 0, 0, 1475, 0, 2816, 2817, 2818, 2819, + 2820, 1475, 0, 0, 0, 1475, 0, 2827, 2828, 3553, + 2829, 1475, 0, 2832, 2834, 2380, 0, 2836, 0, 0, + 0, 1060, 0, 0, 1066, 1066, 0, 2848, 3567, 3568, + 0, 0, 0, 1472, 0, 1473, 1474, 1472, 0, 1473, + 1474, 1475, 0, 674, 3635, 1472, 0, 1473, 1474, 0, + 0, 1953, 0, 0, 0, 3394, 0, 0, 0, 0, + 3651, 2939, 2416, 0, 0, 0, 1475, 0, 0, 0, + 0, 1475, 0, 0, 0, 0, 2831, 0, 0, 0, + 1475, 0, 0, 0, 0, 3662, 2830, 0, 0, 0, + 0, 0, 0, 2826, 1475, 0, 0, 2825, 0, 0, + 674, 0, 0, 2824, 1475, 674, 0, 0, 0, 0, + 0, 1472, 0, 1473, 1474, 0, 1472, 0, 1473, 1474, + 0, 0, 0, 0, 0, 0, 0, 3703, 0, 3704, + 3705, 3706, 1472, 2823, 1473, 1474, 0, 1475, 3713, 0, + 0, 3720, 1472, 3722, 1473, 1474, 0, 0, 0, 1472, + 3693, 1473, 1474, 1472, 0, 1473, 1474, 0, 2822, 1472, + 0, 1473, 1474, 2821, 1475, 0, 3218, 0, 0, 87, + 3723, 3218, 2812, 0, 0, 1475, 0, 0, 0, 1475, + 674, 3582, 3583, 0, 0, 0, 2811, 2961, 0, 1472, + 1475, 1473, 1474, 0, 0, 0, 2810, 1475, 0, 0, + 3724, 0, 0, 0, 2129, 3733, 2127, 3753, 0, 3745, + 3732, 0, 3656, 3740, 1472, 3742, 1473, 1474, 0, 1472, + 0, 1473, 1474, 3743, 0, 0, 0, 0, 1472, 2809, + 1473, 1474, 0, 1521, 3616, 0, 3905, 0, 3620, 3621, + 3622, 3757, 1472, 0, 1473, 1474, 674, 674, 674, 674, + 674, 674, 1472, 0, 1473, 1474, 2806, 0, 0, 0, + 3612, 3613, 0, 0, 0, 0, 0, 2801, 0, 0, + 0, 2794, 0, 0, 674, 674, 3897, 2655, 3896, 0, + 0, 0, 2793, 0, 0, 1472, 3924, 1473, 1474, 2792, + 0, 0, 3916, 0, 2670, 3917, 0, 0, 674, 3912, + 0, 3895, 0, 0, 0, 0, 0, 0, 0, 3963, + 3964, 0, 1472, 0, 1473, 1474, 3066, 3067, 3068, 3069, + 3070, 3747, 0, 1472, 3721, 1473, 1474, 1472, 0, 1473, + 1474, 0, 2129, 0, 2127, 3967, 3085, 0, 1472, 0, + 1473, 1474, 0, 0, 0, 1472, 0, 1473, 1474, 0, + 0, 3754, 3755, 0, 0, 0, 0, 0, 0, 3970, + 0, 0, 0, 3973, 4012, 3218, 0, 0, 3749, 42, + 0, 0, 0, 0, 0, 0, 0, 3214, 0, 1546, + 1547, 1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556, + 1557, 1558, 1559, 1560, 1561, 1562, 1563, 1564, 1566, 1567, + 1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, + 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, + 1588, 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1596, 1597, + 1598, 1599, 1600, 1601, 1602, 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, 1645, 1646, 1647, 1648, + 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1658, + 1659, 1660, 1666, 1667, 1668, 1669, 1683, 1684, 1685, 1686, + 1687, 1688, 1689, 1690, 1691, 1692, 1693, 1694, 1695, 1696, + 3968, 3997, 1475, 3996, 0, 4013, 3987, 3217, 0, 0, + 1475, 1716, 3217, 3993, 4031, 3995, 0, 0, 0, 0, + 0, 1475, 0, 0, 3907, 3908, 3909, 0, 0, 0, + 0, 0, 87, 0, 0, 1067, 3220, 674, 0, 1475, + 0, 0, 0, 0, 1475, 0, 4015, 0, 0, 4016, + 0, 0, 1475, 0, 3238, 0, 3900, 0, 1521, 4020, + 0, 0, 1475, 1521, 674, 674, 674, 674, 674, 4036, + 673, 1475, 4038, 0, 4033, 0, 3237, 3904, 0, 0, + 0, 0, 1953, 0, 674, 0, 0, 674, 3245, 2007, + 1024, 0, 0, 0, 2791, 0, 0, 0, 0, 0, + 0, 0, 2790, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2789, 0, 0, 0, 0, 0, 0, + 4056, 0, 0, 4057, 0, 0, 0, 0, 0, 0, + 4081, 2788, 1095, 674, 0, 87, 2787, 0, 0, 0, + 0, 0, 0, 1476, 2786, 0, 4066, 0, 0, 1521, + 1472, 0, 1473, 1474, 2780, 0, 4075, 0, 1472, 674, + 1473, 1474, 0, 2779, 0, 0, 4098, 4087, 0, 1472, + 4112, 1473, 1474, 674, 1534, 4085, 4090, 3924, 4101, 4095, + 4092, 4091, 3370, 4089, 4094, 4093, 0, 1472, 0, 1473, + 1474, 4120, 1472, 674, 1473, 1474, 674, 0, 4017, 0, + 1472, 0, 1473, 1474, 3387, 3388, 3217, 3389, 3391, 3393, + 1472, 4143, 1473, 1474, 0, 0, 0, 4125, 4133, 1472, + 4138, 1473, 1474, 0, 0, 0, 4151, 4112, 4153, 0, + 0, 0, 42, 4164, 3056, 3406, 0, 0, 0, 0, + 3409, 0, 3411, 3412, 3413, 3415, 3416, 3417, 3418, 3419, + 3420, 3421, 3422, 3423, 3424, 3425, 3426, 3427, 3429, 3431, + 3433, 3435, 3437, 3439, 3441, 3443, 3445, 3447, 3449, 3451, + 3453, 3455, 3457, 3459, 3460, 3462, 3463, 3464, 3466, 2008, + 4187, 3468, 4184, 3470, 3471, 3472, 4194, 4193, 3476, 3477, + 3478, 3479, 3480, 3481, 3482, 3483, 3484, 3485, 3486, 2129, + 4200, 2127, 4197, 4183, 4112, 4208, 4198, 3492, 4168, 4196, + 4163, 3497, 4077, 4216, 0, 3501, 3502, 1475, 3503, 3505, + 4082, 3508, 3510, 4224, 3512, 3513, 3514, 3515, 4222, 0, + 1475, 0, 0, 0, 3523, 42, 3214, 1475, 4022, 0, + 0, 1475, 0, 4233, 4234, 3964, 4232, 1475, 0, 0, + 0, 0, 0, 1475, 0, 0, 0, 2129, 1475, 2127, + 4231, 674, 1475, 0, 0, 4029, 3130, 0, 3132, 3547, + 3548, 1475, 4041, 3552, 0, 0, 0, 0, 0, 0, + 1475, 0, 0, 0, 3143, 3144, 3145, 3146, 0, 0, + 1475, 0, 4159, 0, 1475, 0, 0, 0, 1475, 0, + 0, 0, 1475, 0, 0, 0, 0, 1475, 0, 2778, + 0, 0, 0, 0, 0, 1475, 0, 674, 0, 1475, + 0, 0, 2775, 1475, 0, 0, 0, 0, 0, 2774, + 0, 0, 0, 2773, 0, 0, 0, 0, 0, 2771, + 0, 0, 0, 0, 0, 2764, 674, 0, 0, 0, + 2761, 0, 0, 0, 2759, 0, 0, 0, 0, 4076, + 0, 0, 0, 2757, 1767, 1472, 674, 1473, 1474, 674, + 674, 674, 2716, 0, 0, 0, 0, 0, 1472, 3627, + 1473, 1474, 2696, 0, 0, 1472, 2695, 1473, 1474, 1472, + 2691, 1473, 1474, 0, 2689, 1472, 0, 1473, 1474, 2681, + 0, 1472, 1856, 1473, 1474, 0, 1472, 2652, 1473, 1474, + 1472, 2646, 1473, 1474, 0, 2641, 0, 0, 0, 1472, + 0, 1473, 1474, 0, 3646, 0, 0, 3650, 1472, 0, + 1473, 1474, 0, 0, 0, 0, 0, 1737, 1472, 0, + 1473, 1474, 1472, 0, 1473, 1474, 1472, 0, 1473, 1474, + 1472, 1745, 1473, 1474, 1738, 1472, 0, 1473, 1474, 0, + 0, 3663, 0, 1472, 0, 1473, 1474, 1472, 0, 1473, + 1474, 1472, 0, 1473, 1474, 0, 0, 1737, 0, 2374, + 2375, 1744, 1742, 1743, 1739, 0, 1740, 0, 0, 0, + 0, 1745, 4181, 0, 1738, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1741, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1733, + 1734, 1744, 1742, 1743, 1739, 3686, 1740, 0, 0, 0, + 2013, 0, 0, 0, 0, 0, 0, 0, 3694, 0, + 0, 0, 0, 0, 0, 3701, 0, 0, 0, 1741, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1215, 0, 1221, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1953, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1521, 0, + 0, 0, 1953, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1448, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3913, 0, 0, 0, 0, 0, + 0, 0, 0, 3920, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1953, 0, + 0, 0, 0, 3930, 3931, 3932, 0, 3934, 0, 3935, + 3936, 1710, 0, 0, 0, 3939, 3940, 3941, 3942, 3943, + 3944, 3945, 3946, 3947, 3948, 3949, 3950, 3951, 3952, 3953, + 3954, 3955, 3956, 3957, 3958, 3959, 3960, 0, 3962, 3965, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3974, 3975, 3976, 3977, 3978, 3980, + 3981, 3983, 3985, 3986, 3988, 0, 0, 0, 3992, 0, + 0, 0, 3994, 0, 2080, 2081, 2082, 2083, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2096, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4021, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2135, 2136, 0, 0, 0, + 0, 2159, 0, 0, 2163, 2164, 0, 0, 0, 2169, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2181, 2182, 2183, 2184, 2185, 2186, + 2187, 2188, 2189, 2190, 0, 2192, 0, 0, 0, 2214, + 2215, 2216, 2217, 2218, 2219, 2220, 2221, 2223, 0, 2228, + 0, 2230, 2231, 2232, 0, 2234, 2235, 2236, 0, 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, 2287, 2288, 2289, 2290, 2291, + 2292, 2293, 2294, 2295, 2296, 2297, 2298, 2299, 2300, 2301, + 2302, 2303, 2304, 2305, 2306, 2307, 2308, 2309, 0, 0, + 0, 0, 3684, 2315, 0, 2317, 0, 2324, 2325, 2326, + 2327, 2328, 2329, 4167, 0, 0, 0, 0, 0, 0, + 0, 1779, 1819, 1953, 0, 0, 2340, 2341, 2342, 2343, + 2344, 2345, 2346, 2347, 0, 2349, 2350, 2351, 2352, 2353, + 1796, 0, 674, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4046, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1819, 0, 0, 0, 1066, 0, 0, 4061, 0, + 0, 0, 0, 0, 4064, 0, 4065, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2394, 2395, 0, 4080, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1936, 0, 0, 0, 1521, 0, 0, + 0, 0, 2433, 0, 0, 4106, 4107, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4114, + 4116, 4118, 0, 0, 0, 0, 4100, 0, 1981, 0, + 954, 0, 0, 0, 0, 0, 0, 4124, 0, 0, + 0, 0, 0, 0, 0, 2009, 0, 0, 1806, 4146, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2020, 0, 0, 2476, 190, 1953, 0, 2024, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2035, + 2036, 2037, 2038, 2039, 2040, 2041, 195, 4165, 129, 195, + 151, 0, 0, 725, 0, 0, 0, 1806, 731, 0, + 0, 0, 0, 0, 172, 0, 0, 0, 0, 195, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4188, 4190, 4192, 0, 195, 0, 0, 0, 0, + 4003, 0, 1820, 0, 0, 0, 2007, 0, 162, 0, + 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, + 731, 195, 731, 0, 4213, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 169, 0, 0, 170, 0, 0, + 0, 0, 4225, 4226, 0, 0, 0, 0, 0, 0, + 0, 1820, 0, 0, 0, 0, 0, 0, 0, 138, + 139, 161, 160, 189, 0, 1833, 1836, 1837, 1838, 1839, + 1840, 1841, 0, 1842, 1843, 1845, 1846, 1844, 1847, 1848, + 1821, 1822, 1823, 1824, 1804, 1805, 1834, 0, 1807, 0, + 1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815, 1816, 0, + 0, 1817, 1825, 1826, 1827, 1828, 0, 1829, 1830, 1831, + 1832, 0, 0, 1818, 1833, 1836, 1837, 1838, 1839, 1840, + 1841, 0, 1842, 1843, 1845, 1846, 1844, 1847, 1848, 1821, + 1822, 1823, 1824, 1804, 1805, 1834, 0, 1807, 0, 1808, + 1809, 1810, 1811, 1812, 1813, 1814, 1815, 1816, 0, 2073, + 1817, 1825, 1826, 1827, 1828, 0, 1829, 1830, 1831, 1832, + 0, 0, 1818, 0, 155, 136, 158, 143, 135, 0, + 156, 157, 0, 0, 0, 0, 0, 173, 1710, 0, + 0, 0, 0, 0, 0, 0, 179, 144, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 147, 145, 140, 141, 142, 146, 0, 0, 0, + 0, 0, 0, 137, 0, 0, 0, 0, 0, 0, + 0, 0, 148, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4045, 0, 0, 0, 0, 0, + 0, 0, 4055, 0, 0, 0, 0, 0, 0, 0, + 2650, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2656, 2657, 2658, 2659, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1710, 1534, 0, 0, 190, 0, + 0, 0, 164, 0, 0, 0, 0, 0, 1835, 2968, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 129, 0, 151, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1835, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 162, 0, 0, 0, 0, 0, 150, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 169, 159, 0, + 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1877, 1878, 161, 160, 189, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2400, 0, 0, 0, 0, 0, 0, 0, 2404, 0, + 2407, 0, 0, 2073, 0, 0, 0, 0, 0, 1767, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 152, 0, 0, + 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 155, 1879, 158, + 0, 1876, 0, 156, 157, 0, 0, 0, 0, 0, + 173, 165, 0, 0, 0, 0, 0, 0, 177, 179, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 195, 0, 195, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 731, 0, 731, 731, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 731, 195, 0, 0, 0, 0, 0, + 0, 0, 166, 171, 168, 174, 175, 176, 178, 180, + 181, 182, 183, 0, 0, 0, 0, 0, 184, 186, + 187, 188, 1520, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2073, 0, 0, 0, 0, 0, 0, 2566, + 0, 0, 0, 0, 0, 164, 0, 0, 0, 0, + 2586, 2587, 0, 0, 2591, 0, 0, 0, 0, 0, + 3031, 0, 0, 0, 0, 0, 2596, 0, 0, 0, + 0, 0, 0, 2599, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3057, 3058, 3059, + 0, 0, 3061, 0, 0, 3063, 0, 0, 0, 2602, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3082, 3083, 3084, 0, 0, + 0, 0, 0, 0, 3089, 0, 0, 0, 0, 3091, + 0, 0, 3093, 3094, 3095, 0, 0, 0, 3096, 3097, + 0, 159, 3098, 0, 3099, 0, 0, 0, 0, 0, + 0, 3100, 0, 3101, 0, 0, 0, 3102, 0, 3103, + 0, 0, 3104, 0, 3105, 0, 3106, 0, 3107, 0, + 3108, 0, 3109, 0, 3110, 0, 3111, 0, 3112, 0, + 3113, 0, 3114, 0, 3115, 0, 3116, 0, 3117, 0, + 3118, 0, 3119, 0, 3120, 0, 3121, 0, 0, 0, + 3122, 0, 3123, 0, 3124, 0, 0, 3125, 0, 3126, + 0, 3127, 0, 2287, 3129, 0, 0, 3131, 0, 0, + 3133, 3134, 3135, 3136, 0, 1520, 0, 0, 3137, 2287, + 2287, 2287, 2287, 2287, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3147, 0, 0, 0, 0, 0, + 152, 0, 3160, 153, 0, 3164, 0, 0, 0, 0, + 0, 0, 0, 0, 3167, 3168, 3169, 3170, 3171, 3172, + 0, 0, 0, 3173, 3174, 0, 3175, 0, 3176, 0, + 0, 0, 0, 195, 165, 0, 0, 731, 731, 0, + 0, 177, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1066, 0, 0, 0, 195, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3209, 0, 0, 0, 731, 0, 0, + 195, 0, 185, 953, 0, 0, 0, 0, 0, 0, + 0, 0, 731, 0, 0, 0, 0, 0, 3239, 195, + 0, 0, 0, 731, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 731, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 166, 171, 168, 174, 175, + 176, 178, 180, 181, 182, 183, 731, 0, 731, 0, + 0, 184, 186, 187, 188, 709, 731, 0, 0, 1520, + 731, 730, 0, 731, 731, 731, 731, 0, 731, 3302, + 731, 731, 0, 731, 731, 731, 731, 731, 731, 0, + 0, 0, 0, 0, 0, 0, 1520, 731, 731, 1520, + 731, 1520, 195, 731, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 195, 730, 0, 730, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 731, 0, 195, 0, 0, + 0, 2906, 0, 0, 0, 0, 0, 0, 731, 0, + 0, 731, 0, 195, 195, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 195, 0, 0, 190, 0, 3395, 0, 195, 0, 0, + 0, 0, 0, 0, 1873, 0, 195, 195, 195, 195, + 195, 195, 195, 195, 195, 731, 129, 0, 151, 0, + 0, 0, 0, 3410, 0, 0, 0, 0, 0, 0, + 0, 0, 172, 0, 0, 0, 2955, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 162, 0, 0, 0, + 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 169, 0, 0, 170, 0, 0, 0, 0, + 0, 0, 3004, 3005, 3006, 3007, 3008, 3009, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1877, 1878, 161, + 160, 189, 0, 0, 0, 0, 0, 0, 0, 0, + 2073, 3019, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3027, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 1730, 0, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, + 0, 0, 0, 0, 0, 731, 731, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 731, + 0, 0, 0, 0, 0, 0, 0, 0, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 155, 1879, 158, 0, 1876, 0, 156, 157, + 0, 0, 3608, 0, 0, 173, 0, 0, 0, 0, + 0, 0, 0, 0, 179, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 731, 0, + 0, 0, 0, 0, 0, 3632, 0, 0, 1520, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1520, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3652, 0, 3653, 0, 3654, 0, 3655, + 0, 0, 0, 0, 0, 0, 0, 3658, 3659, 0, + 0, 0, 0, 0, 0, 0, 0, 3664, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3665, 0, 3666, 0, 3667, 0, 3668, 0, 3669, + 164, 3670, 0, 3671, 0, 3672, 0, 3673, 0, 3674, + 0, 3675, 0, 3676, 0, 3677, 0, 3678, 0, 3679, + 0, 3680, 0, 0, 3681, 0, 0, 0, 3682, 0, + 3683, 0, 0, 0, 0, 0, 3685, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2334, 0, 0, 0, 0, 0, 3702, 0, + 0, 0, 0, 0, 0, 0, 0, 3707, 0, 3708, + 3709, 0, 3710, 0, 3711, 0, 0, 0, 0, 3712, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 3687, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 2103, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 159, 195, 0, 0, + 0, 0, 731, 0, 0, 0, 3741, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3750, + 0, 0, 3752, 0, 0, 0, 0, 0, 0, 3292, + 0, 0, 195, 0, 3756, 731, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, + 3892, 0, 0, 731, 0, 3330, 2334, 195, 0, 195, + 0, 195, 195, 730, 1434, 730, 730, 0, 0, 3344, + 0, 0, 0, 0, 0, 0, 731, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 730, 0, 0, 3362, + 0, 0, 3365, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 152, 0, 0, 153, 0, + 0, 0, 0, 0, 0, 1519, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 731, 0, 0, 0, 0, 165, + 0, 731, 731, 731, 0, 0, 177, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 731, 0, 0, 0, 0, 0, 731, 731, 0, + 0, 731, 0, 731, 0, 0, 0, 0, 0, 731, + 0, 0, 0, 0, 0, 0, 0, 185, 0, 4002, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 731, 0, 0, 0, 0, 731, + 0, 0, 0, 731, 731, 0, 0, 0, 0, 0, + 166, 171, 168, 174, 175, 176, 178, 180, 181, 182, + 183, 910, 0, 0, 0, 0, 184, 186, 187, 188, + 0, 0, 0, 0, 0, 0, 0, 3525, 0, 0, + 0, 195, 0, 0, 0, 0, 0, 0, 195, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, + 195, 0, 0, 195, 0, 195, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 195, 0, 0, 0, 0, + 0, 0, 195, 0, 0, 0, 0, 0, 0, 729, + 0, 0, 0, 0, 0, 0, 0, 0, 1519, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 195, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 731, + 0, 0, 3586, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1091, 3601, 1098, 0, 3602, 3603, 3604, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 2104, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 2842, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, + 730, 730, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4044, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1520, 0, 2334, 0, 0, 0, 0, + 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 730, 0, 0, 0, 0, + 0, 0, 4058, 0, 0, 4059, 730, 4060, 0, 0, + 0, 0, 0, 0, 0, 0, 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 2843, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 715, 0, 0, 0, 0, 2827, 0, 0, 0, 0, - 238, 0, 0, 245, 2828, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 730, + 0, 730, 0, 0, 0, 0, 0, 0, 0, 730, + 0, 0, 1519, 730, 0, 0, 730, 730, 730, 730, + 0, 730, 0, 730, 730, 0, 730, 730, 730, 730, + 730, 730, 0, 0, 0, 0, 0, 0, 0, 1519, + 730, 730, 1519, 730, 1519, 0, 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4144, + 0, 0, 0, 0, 0, 0, 0, 0, 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 730, 0, 0, 730, 0, 0, 0, 4160, 0, + 4161, 0, 4162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 730, 0, + 0, 0, 0, 0, 95, 0, 0, 1019, 0, 0, + 0, 0, 959, 1020, 972, 973, 974, 960, 195, 0, + 961, 962, 0, 963, 0, 0, 195, 0, 0, 0, + 0, 0, 4211, 0, 4212, 0, 0, 731, 0, 968, + 0, 975, 976, 0, 0, 0, 0, 0, 0, 0, + 0, 731, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 195, 0, 0, 0, 0, + 195, 0, 0, 0, 0, 0, 0, 0, 0, 3338, + 3339, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 977, 978, 979, 980, 981, 982, 983, 984, 985, + 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, + 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, + 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, + 1016, 1017, 1018, 0, 0, 0, 0, 0, 0, 731, + 0, 0, 0, 0, 0, 195, 0, 0, 0, 0, + 0, 0, 195, 0, 0, 0, 0, 0, 730, 730, + 0, 0, 0, 0, 0, 0, 731, 0, 0, 0, + 0, 0, 730, 731, 3340, 0, 0, 731, 731, 0, + 0, 0, 731, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1520, 731, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 195, 195, 195, 195, 195, 195, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 730, 0, 0, 0, 0, 0, 0, 0, 195, + 195, 1519, 0, 0, 0, 0, 0, 0, 0, 0, + 2137, 0, 3341, 3342, 0, 0, 0, 0, 0, 1519, + 0, 0, 0, 195, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 731, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1019, 0, 0, 2323, 0, 0, 1020, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2128, 0, + 0, 1279, 0, 1279, 1279, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 924, 0, 731, + 0, 0, 0, 928, 1447, 0, 0, 925, 926, 0, + 0, 0, 927, 929, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4042, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 730, 977, 978, 979, 980, + 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, + 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, + 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, + 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 0, 0, + 0, 0, 0, 0, 0, 730, 0, 0, 0, 0, + 0, 0, 0, 0, 731, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 731, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 730, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 730, 731, 0, 730, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 195, 0, 0, 731, 0, 0, 0, 730, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 731, + 0, 0, 0, 1520, 0, 0, 731, 731, 1520, 195, + 195, 195, 195, 195, 0, 0, 0, 0, 0, 0, + 0, 195, 0, 0, 0, 0, 0, 195, 0, 195, + 0, 0, 195, 195, 195, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 730, 0, 0, + 0, 0, 0, 0, 730, 730, 730, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 730, 0, 0, 0, 195, 0, + 730, 730, 0, 0, 730, 0, 730, 0, 0, 0, + 0, 731, 730, 0, 1520, 0, 0, 0, 0, 731, + 0, 0, 0, 0, 195, 0, 0, 0, 1719, 1720, + 0, 0, 0, 0, 0, 0, 0, 0, 195, 0, + 0, 0, 0, 0, 0, 0, 0, 730, 0, 0, + 0, 0, 730, 0, 0, 0, 730, 730, 195, 0, + 0, 195, 0, 0, 0, 0, 0, 0, 1773, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1791, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1850, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1859, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1091, 0, 1885, + 0, 0, 0, 0, 0, 0, 0, 1894, 0, 0, + 0, 1896, 0, 0, 1899, 1900, 1902, 1902, 0, 1902, + 0, 1902, 1902, 0, 1911, 1902, 1902, 1902, 1902, 1902, + 0, 0, 0, 0, 0, 0, 0, 0, 1931, 1932, + 0, 1091, 730, 0, 1937, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 731, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1979, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2001, + 0, 0, 2005, 0, 0, 0, 195, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1519, 0, 730, 0, + 0, 0, 1019, 0, 0, 0, 0, 0, 1020, 0, + 0, 0, 0, 0, 0, 0, 1279, 0, 2128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 1776, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 1775, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, + 0, 0, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 195, 0, 0, 195, 195, 195, 0, 0, 0, + 0, 0, 0, 0, 731, 731, 977, 978, 979, 980, + 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, + 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, + 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, + 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 0, 0, + 0, 0, 0, 731, 731, 731, 731, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1279, 1279, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2061, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 717, 718, 719, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 730, 0, 0, 0, 0, 2123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2919, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 731, 0, 731, 0, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1520, 0, 0, 0, 195, 0, 0, + 731, 0, 731, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 730, + 0, 0, 0, 0, 0, 0, 730, 0, 0, 0, + 730, 730, 0, 0, 0, 730, 0, 0, 0, 0, + 731, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1519, 730, 195, 0, 0, 731, 0, 0, 0, + 0, 0, 0, 1279, 0, 0, 0, 0, 0, 731, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2371, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 730, 0, 731, 0, 2384, 0, 0, 0, + 0, 731, 0, 731, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1773, 0, 0, 1279, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 731, 0, 0, 0, 0, 1091, 0, 0, + 0, 0, 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 4029, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 1936, - 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1098, 0, 0, 0, 0, + 0, 0, 2498, 2499, 2500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1091, 0, 0, 0, 0, 0, 1098, 1894, + 0, 0, 1894, 0, 1894, 0, 0, 0, 0, 0, + 2530, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 730, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 730, + 0, 0, 731, 0, 0, 1091, 0, 0, 0, 0, + 2123, 0, 0, 0, 2123, 2123, 0, 0, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 730, 0, 0, 0, 0, 0, 731, 195, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 730, 0, 0, 0, 1519, 0, 0, 730, + 730, 1519, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, + 0, 0, 731, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 731, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1520, 731, 0, 731, 0, 0, 0, 0, + 2606, 0, 3287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, + 731, 2334, 0, 0, 730, 0, 0, 1519, 0, 0, + 0, 0, 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 195, 731, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1279, 0, 0, 0, + 0, 0, 0, 0, 3369, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 731, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 731, 0, 0, 0, + 0, 195, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 731, 0, 731, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 3687, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 95, 0, 0, 0, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 2396, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3576, 0, 0, 0, 0, 2854, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2869, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 730, 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 1757, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 730, 730, 730, 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2951, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2384, 0, 0, + 0, 0, 0, 0, 2976, 0, 0, 0, 1894, 1894, + 0, 0, 0, 2981, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2992, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 730, 0, 730, 0, 0, 0, 0, + 2123, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1519, 0, 0, 0, + 0, 0, 0, 730, 0, 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 2050, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 2041, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 730, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3149, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1279, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 730, 0, 0, + 0, 0, 0, 0, 730, 0, 730, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1902, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 730, 3194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 1903, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, + 1279, 0, 0, 0, 0, 0, 0, 3221, 1902, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6004,437 +2695,89 @@ 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, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 1901, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, + 0, 0, 1091, 0, 0, 0, 0, 0, 0, 0, + 2384, 0, 0, 0, 0, 0, 0, 3778, 3780, 3779, + 3845, 3846, 3847, 3848, 3849, 3850, 3851, 3781, 3782, 801, + 0, 0, 0, 0, 0, 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 1899, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, + 0, 0, 0, 0, 0, 730, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 730, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1519, 730, 0, 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1850, 0, 0, 730, 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3786, 0, 0, + 0, 0, 0, 0, 0, 730, 0, 0, 0, 0, + 0, 0, 3794, 3795, 0, 0, 3870, 3869, 3868, 0, + 0, 3866, 3867, 3865, 0, 0, 0, 0, 0, 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 1897, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 730, 0, + 730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2384, 2384, 3871, 924, 0, + 777, 778, 3872, 3873, 928, 3874, 780, 781, 925, 926, + 0, 775, 779, 927, 929, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3640, 3641, 3642, 3643, 0, 0, + 3775, 3776, 3777, 3783, 3784, 3785, 3796, 3843, 3844, 3852, + 3854, 880, 3853, 3855, 3856, 3857, 3860, 3861, 3862, 3863, + 3858, 3859, 3864, 3758, 3762, 3759, 3760, 3761, 3773, 3763, + 3764, 3765, 3766, 3767, 3768, 3769, 3770, 3771, 3772, 3774, + 3875, 3876, 3877, 3878, 3879, 3880, 3789, 3793, 3792, 3790, + 3791, 3787, 3788, 3815, 3814, 3816, 3817, 3818, 3819, 3820, + 3821, 3823, 3822, 3824, 3825, 3826, 3827, 3828, 3829, 3797, + 3798, 3801, 3802, 3800, 3799, 3803, 3812, 3813, 3804, 3805, + 3806, 3807, 3808, 3809, 3811, 3810, 3830, 3831, 3832, 3833, + 3834, 3836, 3835, 3839, 3840, 3838, 3837, 3842, 3841, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 930, 0, 931, 0, 0, 935, 0, 0, + 0, 937, 936, 0, 938, 900, 899, 0, 0, 932, + 933, 0, 934, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3718, 0, 3718, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 1895, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, + 0, 3746, 0, 3748, 0, 0, 0, 3881, 3882, 3883, + 3884, 3885, 3886, 3887, 3888, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2384, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3915, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1279, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 1891, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3718, 0, 0, 0, 0, + 0, 0, 3718, 0, 3718, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 1889, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6442,288 +2785,1825 @@ 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, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 1887, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 1862, 0, 0, 0, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4062, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4070, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2384, 0, 4078, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1279, 1279, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 1761, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, - 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4070, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 396, 0, 0, 0, 1850, 0, 4128, 1417, + 1401, 528, 0, 1343, 1420, 1311, 1330, 1430, 1333, 1336, + 1380, 1289, 1358, 416, 1327, 1315, 1284, 1322, 1285, 1313, + 1345, 270, 1310, 1403, 1362, 1419, 366, 267, 1291, 1282, + 204, 505, 1316, 430, 1332, 203, 1382, 487, 252, 377, + 374, 583, 282, 273, 269, 250, 317, 385, 428, 518, + 422, 1426, 370, 1368, 0, 497, 401, 0, 0, 0, + 1407, 1406, 1337, 1347, 1409, 1356, 1394, 1342, 1381, 1299, + 1367, 1421, 1328, 1377, 1422, 323, 248, 325, 202, 413, + 498, 286, 0, 0, 0, 0, 4102, 507, 955, 0, + 0, 0, 0, 4103, 0, 0, 0, 0, 238, 0, + 0, 245, 0, 0, 0, 351, 360, 359, 339, 340, + 342, 344, 350, 357, 363, 336, 345, 1324, 1374, 607, + 1416, 1325, 1376, 265, 321, 272, 264, 580, 1427, 1408, + 1288, 1355, 1415, 1350, 0, 0, 229, 1418, 1349, 0, + 1379, 0, 1433, 1283, 1370, 0, 1286, 1290, 1429, 1413, + 1319, 275, 0, 0, 0, 0, 0, 0, 0, 1346, + 1357, 1391, 1395, 1340, 0, 0, 0, 0, 0, 0, + 0, 0, 1317, 0, 1366, 0, 0, 0, 1295, 1287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, + 0, 0, 1344, 0, 0, 0, 0, 1298, 0, 1318, + 1392, 0, 1281, 297, 1292, 402, 257, 0, 453, 1399, + 1412, 1341, 626, 1414, 1339, 1338, 1386, 1296, 1405, 1331, + 365, 1294, 330, 197, 225, 0, 1329, 412, 461, 473, + 1404, 1314, 1323, 253, 1321, 471, 426, 602, 233, 284, + 458, 432, 469, 440, 287, 1365, 1384, 470, 372, 585, + 450, 599, 627, 628, 263, 406, 612, 522, 620, 645, + 226, 260, 420, 506, 605, 494, 397, 581, 582, 329, + 493, 295, 201, 369, 633, 224, 479, 371, 242, 231, + 587, 609, 299, 289, 456, 640, 213, 517, 597, 239, + 483, 0, 0, 648, 247, 504, 215, 594, 503, 393, + 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, + 415, 589, 590, 256, 649, 228, 619, 220, 1293, 618, + 408, 584, 595, 394, 383, 219, 593, 392, 382, 334, + 355, 356, 280, 307, 447, 375, 448, 306, 308, 404, + 403, 405, 207, 606, 623, 0, 208, 0, 499, 608, + 650, 452, 212, 234, 235, 237, 1309, 279, 283, 291, + 294, 303, 304, 313, 367, 419, 446, 442, 451, 1400, + 579, 600, 613, 625, 631, 632, 634, 635, 636, 637, + 638, 641, 639, 407, 311, 495, 333, 373, 1389, 1432, + 425, 472, 240, 604, 496, 199, 1303, 1308, 1301, 0, + 254, 255, 1371, 575, 1304, 1302, 1360, 1361, 1305, 1423, + 1424, 1425, 1410, 651, 652, 653, 654, 655, 656, 657, + 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, + 668, 646, 508, 514, 509, 510, 511, 512, 513, 0, + 515, 1393, 1297, 0, 1306, 1307, 398, 1402, 591, 592, + 669, 384, 486, 601, 335, 349, 352, 341, 361, 0, + 362, 337, 338, 343, 346, 347, 348, 353, 354, 358, + 364, 249, 210, 390, 399, 578, 312, 216, 217, 218, + 524, 525, 526, 527, 616, 617, 621, 205, 462, 463, + 464, 465, 292, 611, 309, 468, 467, 331, 332, 379, + 449, 540, 542, 553, 557, 559, 561, 567, 570, 541, + 543, 554, 558, 560, 562, 568, 571, 530, 532, 534, + 536, 549, 548, 545, 573, 574, 551, 556, 535, 547, + 552, 565, 572, 569, 529, 533, 537, 546, 564, 563, + 544, 555, 566, 550, 538, 531, 539, 1364, 196, 221, + 368, 1428, 454, 288, 647, 615, 484, 610, 206, 223, + 1300, 262, 1312, 1320, 0, 1326, 1334, 1335, 1348, 1351, + 1352, 1353, 1354, 1372, 1373, 1375, 1383, 1385, 1388, 1390, + 1397, 1411, 1431, 198, 200, 209, 222, 232, 236, 243, + 261, 276, 278, 285, 298, 310, 318, 319, 322, 328, + 380, 386, 387, 388, 389, 409, 410, 411, 414, 417, + 418, 421, 423, 424, 427, 431, 435, 436, 437, 439, + 441, 443, 455, 460, 474, 475, 476, 477, 478, 481, + 482, 488, 489, 490, 491, 492, 500, 501, 516, 586, + 588, 603, 622, 629, 480, 301, 302, 444, 445, 314, + 315, 643, 644, 300, 598, 630, 596, 642, 624, 438, + 378, 1363, 1369, 381, 281, 305, 320, 1378, 614, 502, + 227, 466, 290, 251, 1396, 1398, 211, 246, 230, 259, + 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, + 459, 241, 485, 519, 520, 521, 523, 395, 266, 433, + 1359, 1387, 376, 576, 577, 316, 396, 0, 0, 0, + 0, 0, 0, 1417, 1401, 528, 0, 1343, 1420, 1311, + 1330, 1430, 1333, 1336, 1380, 1289, 1358, 416, 1327, 1315, + 1284, 1322, 1285, 1313, 1345, 270, 1310, 1403, 1362, 1419, + 366, 267, 1291, 1282, 204, 505, 1316, 430, 1332, 203, + 1382, 487, 252, 377, 374, 583, 282, 273, 269, 250, + 317, 385, 428, 518, 422, 1426, 370, 1368, 0, 497, + 401, 0, 0, 0, 1407, 1406, 1337, 1347, 1409, 1356, + 1394, 1342, 1381, 1299, 1367, 1421, 1328, 1377, 1422, 323, + 248, 325, 202, 413, 498, 286, 0, 0, 0, 0, + 0, 507, 194, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 238, 0, 0, 245, 0, 0, 0, 351, + 360, 359, 339, 340, 342, 344, 350, 357, 363, 336, + 345, 1324, 1374, 607, 1416, 1325, 1376, 265, 321, 272, + 264, 580, 1427, 1408, 1288, 1355, 1415, 1350, 0, 0, + 229, 1418, 1349, 0, 1379, 0, 1433, 1283, 1370, 0, + 1286, 1290, 1429, 1413, 1319, 275, 0, 0, 0, 0, + 0, 0, 0, 1346, 1357, 1391, 1395, 1340, 0, 0, + 0, 0, 0, 0, 3246, 0, 1317, 0, 1366, 0, + 0, 0, 1295, 1287, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1344, 0, 0, 0, + 0, 1298, 0, 1318, 1392, 0, 1281, 297, 1292, 402, + 257, 0, 453, 1399, 1412, 1341, 626, 1414, 1339, 1338, + 1386, 1296, 1405, 1331, 365, 1294, 330, 197, 225, 0, + 1329, 412, 461, 473, 1404, 1314, 1323, 253, 1321, 471, + 426, 602, 233, 284, 458, 432, 469, 440, 287, 1365, + 1384, 470, 372, 585, 450, 599, 627, 628, 263, 406, + 612, 522, 620, 645, 226, 260, 420, 506, 605, 494, + 397, 581, 582, 329, 493, 295, 201, 369, 633, 224, + 479, 371, 242, 231, 587, 609, 299, 289, 456, 640, + 213, 517, 597, 239, 483, 0, 0, 648, 247, 504, + 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, + 293, 0, 0, 258, 415, 589, 590, 256, 649, 228, + 619, 220, 1293, 618, 408, 584, 595, 394, 383, 219, + 593, 392, 382, 334, 355, 356, 280, 307, 447, 375, + 448, 306, 308, 404, 403, 405, 207, 606, 623, 0, + 208, 0, 499, 608, 650, 452, 212, 234, 235, 237, + 1309, 279, 283, 291, 294, 303, 304, 313, 367, 419, + 446, 442, 451, 1400, 579, 600, 613, 625, 631, 632, + 634, 635, 636, 637, 638, 641, 639, 407, 311, 495, + 333, 373, 1389, 1432, 425, 472, 240, 604, 496, 199, + 1303, 1308, 1301, 0, 254, 255, 1371, 575, 1304, 1302, + 1360, 1361, 1305, 1423, 1424, 1425, 1410, 651, 652, 653, + 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, + 664, 665, 666, 667, 668, 646, 508, 514, 509, 510, + 511, 512, 513, 0, 515, 1393, 1297, 0, 1306, 1307, + 398, 1402, 591, 592, 669, 384, 486, 601, 335, 349, + 352, 341, 361, 0, 362, 337, 338, 343, 346, 347, + 348, 353, 354, 358, 364, 249, 210, 390, 399, 578, + 312, 216, 217, 218, 524, 525, 526, 527, 616, 617, + 621, 205, 462, 463, 464, 465, 292, 611, 309, 468, + 467, 331, 332, 379, 449, 540, 542, 553, 557, 559, + 561, 567, 570, 541, 543, 554, 558, 560, 562, 568, + 571, 530, 532, 534, 536, 549, 548, 545, 573, 574, + 551, 556, 535, 547, 552, 565, 572, 569, 529, 533, + 537, 546, 564, 563, 544, 555, 566, 550, 538, 531, + 539, 1364, 196, 221, 368, 1428, 454, 288, 647, 615, + 484, 610, 206, 223, 1300, 262, 1312, 1320, 0, 1326, + 1334, 1335, 1348, 1351, 1352, 1353, 1354, 1372, 1373, 1375, + 1383, 1385, 1388, 1390, 1397, 1411, 1431, 198, 200, 209, + 222, 232, 236, 243, 261, 276, 278, 285, 298, 310, + 318, 319, 322, 328, 380, 386, 387, 388, 389, 409, + 410, 411, 414, 417, 418, 421, 423, 424, 427, 431, + 435, 436, 437, 439, 441, 443, 455, 460, 474, 475, + 476, 477, 478, 481, 482, 488, 489, 490, 491, 492, + 500, 501, 516, 586, 588, 603, 622, 629, 480, 301, + 302, 444, 445, 314, 315, 643, 644, 300, 598, 630, + 596, 642, 624, 438, 378, 1363, 1369, 381, 281, 305, + 320, 1378, 614, 502, 227, 466, 290, 251, 1396, 1398, + 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, + 434, 296, 271, 244, 459, 241, 485, 519, 520, 521, + 523, 395, 266, 433, 1359, 1387, 376, 576, 577, 316, + 396, 0, 0, 0, 0, 0, 0, 1417, 1401, 528, + 0, 1343, 1420, 1311, 1330, 1430, 1333, 1336, 1380, 1289, + 1358, 416, 1327, 1315, 1284, 1322, 1285, 1313, 1345, 270, + 1310, 1403, 1362, 1419, 366, 267, 1291, 1282, 204, 505, + 1316, 430, 1332, 203, 1382, 487, 252, 377, 374, 583, + 282, 273, 269, 250, 317, 385, 428, 518, 422, 1426, + 370, 1368, 0, 497, 401, 0, 0, 0, 1407, 1406, + 1337, 1347, 1409, 1356, 1394, 1342, 1381, 1299, 1367, 1421, + 1328, 1377, 1422, 323, 248, 325, 202, 413, 498, 286, + 0, 0, 0, 0, 0, 507, 720, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 238, 0, 0, 245, + 0, 0, 0, 351, 360, 359, 339, 340, 342, 344, + 350, 357, 363, 336, 345, 1324, 1374, 607, 1416, 1325, + 1376, 265, 321, 272, 264, 580, 1427, 1408, 1288, 1355, + 1415, 1350, 0, 0, 229, 1418, 1349, 0, 1379, 0, + 1433, 1283, 1370, 0, 1286, 1290, 1429, 1413, 1319, 275, + 0, 0, 0, 0, 0, 0, 0, 1346, 1357, 1391, + 1395, 1340, 0, 0, 0, 0, 0, 0, 3207, 0, + 1317, 0, 1366, 0, 0, 0, 1295, 1287, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1344, 0, 0, 0, 0, 1298, 0, 1318, 1392, 0, + 1281, 297, 1292, 402, 257, 0, 453, 1399, 1412, 1341, + 626, 1414, 1339, 1338, 1386, 1296, 1405, 1331, 365, 1294, + 330, 197, 225, 0, 1329, 412, 461, 473, 1404, 1314, + 1323, 253, 1321, 471, 426, 602, 233, 284, 458, 432, + 469, 440, 287, 1365, 1384, 470, 372, 585, 450, 599, + 627, 628, 263, 406, 612, 522, 620, 645, 226, 260, + 420, 506, 605, 494, 397, 581, 582, 329, 493, 295, + 201, 369, 633, 224, 479, 371, 242, 231, 587, 609, + 299, 289, 456, 640, 213, 517, 597, 239, 483, 0, + 0, 648, 247, 504, 215, 594, 503, 393, 326, 327, + 214, 0, 457, 268, 293, 0, 0, 258, 415, 589, + 590, 256, 649, 228, 619, 220, 1293, 618, 408, 584, + 595, 394, 383, 219, 593, 392, 382, 334, 355, 356, + 280, 307, 447, 375, 448, 306, 308, 404, 403, 405, + 207, 606, 623, 0, 208, 0, 499, 608, 650, 452, + 212, 234, 235, 237, 1309, 279, 283, 291, 294, 303, + 304, 313, 367, 419, 446, 442, 451, 1400, 579, 600, + 613, 625, 631, 632, 634, 635, 636, 637, 638, 641, + 639, 407, 311, 495, 333, 373, 1389, 1432, 425, 472, + 240, 604, 496, 199, 1303, 1308, 1301, 0, 254, 255, + 1371, 575, 1304, 1302, 1360, 1361, 1305, 1423, 1424, 1425, + 1410, 651, 652, 653, 654, 655, 656, 657, 658, 659, + 660, 661, 662, 663, 664, 665, 666, 667, 668, 646, + 508, 514, 509, 510, 511, 512, 513, 0, 515, 1393, + 1297, 0, 1306, 1307, 398, 1402, 591, 592, 669, 384, + 486, 601, 335, 349, 352, 341, 361, 0, 362, 337, + 338, 343, 346, 347, 348, 353, 354, 358, 364, 249, + 210, 390, 399, 578, 312, 216, 217, 218, 524, 525, + 526, 527, 616, 617, 621, 205, 462, 463, 464, 465, + 292, 611, 309, 468, 467, 331, 332, 379, 449, 540, + 542, 553, 557, 559, 561, 567, 570, 541, 543, 554, + 558, 560, 562, 568, 571, 530, 532, 534, 536, 549, + 548, 545, 573, 574, 551, 556, 535, 547, 552, 565, + 572, 569, 529, 533, 537, 546, 564, 563, 544, 555, + 566, 550, 538, 531, 539, 1364, 196, 221, 368, 1428, + 454, 288, 647, 615, 484, 610, 206, 223, 1300, 262, + 1312, 1320, 0, 1326, 1334, 1335, 1348, 1351, 1352, 1353, + 1354, 1372, 1373, 1375, 1383, 1385, 1388, 1390, 1397, 1411, + 1431, 198, 200, 209, 222, 232, 236, 243, 261, 276, + 278, 285, 298, 310, 318, 319, 322, 328, 380, 386, + 387, 388, 389, 409, 410, 411, 414, 417, 418, 421, + 423, 424, 427, 431, 435, 436, 437, 439, 441, 443, + 455, 460, 474, 475, 476, 477, 478, 481, 482, 488, + 489, 490, 491, 492, 500, 501, 516, 586, 588, 603, + 622, 629, 480, 301, 302, 444, 445, 314, 315, 643, + 644, 300, 598, 630, 596, 642, 624, 438, 378, 1363, + 1369, 381, 281, 305, 320, 1378, 614, 502, 227, 466, + 290, 251, 1396, 1398, 211, 246, 230, 259, 274, 277, + 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, + 485, 519, 520, 521, 523, 395, 266, 433, 1359, 1387, + 376, 576, 577, 316, 396, 0, 0, 0, 0, 0, + 0, 1417, 1401, 528, 0, 1343, 1420, 1311, 1330, 1430, + 1333, 1336, 1380, 1289, 1358, 416, 1327, 1315, 1284, 1322, + 1285, 1313, 1345, 270, 1310, 1403, 1362, 1419, 366, 267, + 1291, 1282, 204, 505, 1316, 430, 1332, 203, 1382, 487, + 252, 377, 374, 583, 282, 273, 269, 250, 317, 385, + 428, 518, 422, 1426, 370, 1368, 0, 497, 401, 0, + 0, 0, 1407, 1406, 1337, 1347, 1409, 1356, 1394, 1342, + 1381, 1299, 1367, 1421, 1328, 1377, 1422, 323, 248, 325, + 202, 413, 498, 286, 0, 0, 0, 0, 0, 507, + 955, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 245, 0, 0, 0, 351, 360, 359, + 339, 340, 342, 344, 350, 357, 363, 336, 345, 1324, + 1374, 607, 1416, 1325, 1376, 265, 321, 272, 264, 580, + 1427, 1408, 1288, 1355, 1415, 1350, 0, 0, 229, 1418, + 1349, 0, 1379, 0, 1433, 1283, 1370, 0, 1286, 1290, + 1429, 1413, 1319, 275, 0, 0, 0, 0, 0, 0, + 0, 1346, 1357, 1391, 1395, 1340, 0, 0, 0, 0, + 0, 0, 2402, 0, 1317, 0, 1366, 0, 0, 0, + 1295, 1287, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1344, 0, 0, 0, 0, 1298, + 0, 1318, 1392, 0, 1281, 297, 1292, 402, 257, 0, + 453, 1399, 1412, 1341, 626, 1414, 1339, 1338, 1386, 1296, + 1405, 1331, 365, 1294, 330, 197, 225, 0, 1329, 412, + 461, 473, 1404, 1314, 1323, 253, 1321, 471, 426, 602, + 233, 284, 458, 432, 469, 440, 287, 1365, 1384, 470, + 372, 585, 450, 599, 627, 628, 263, 406, 612, 522, + 620, 645, 226, 260, 420, 506, 605, 494, 397, 581, + 582, 329, 493, 295, 201, 369, 633, 224, 479, 371, + 242, 231, 587, 609, 299, 289, 456, 640, 213, 517, + 597, 239, 483, 0, 0, 648, 247, 504, 215, 594, + 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, + 0, 258, 415, 589, 590, 256, 649, 228, 619, 220, + 1293, 618, 408, 584, 595, 394, 383, 219, 593, 392, + 382, 334, 355, 356, 280, 307, 447, 375, 448, 306, + 308, 404, 403, 405, 207, 606, 623, 0, 208, 0, + 499, 608, 650, 452, 212, 234, 235, 237, 1309, 279, + 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, + 451, 1400, 579, 600, 613, 625, 631, 632, 634, 635, + 636, 637, 638, 641, 639, 407, 311, 495, 333, 373, + 1389, 1432, 425, 472, 240, 604, 496, 199, 1303, 1308, + 1301, 0, 254, 255, 1371, 575, 1304, 1302, 1360, 1361, + 1305, 1423, 1424, 1425, 1410, 651, 652, 653, 654, 655, + 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, + 666, 667, 668, 646, 508, 514, 509, 510, 511, 512, + 513, 0, 515, 1393, 1297, 0, 1306, 1307, 398, 1402, + 591, 592, 669, 384, 486, 601, 335, 349, 352, 341, + 361, 0, 362, 337, 338, 343, 346, 347, 348, 353, + 354, 358, 364, 249, 210, 390, 399, 578, 312, 216, + 217, 218, 524, 525, 526, 527, 616, 617, 621, 205, + 462, 463, 464, 465, 292, 611, 309, 468, 467, 331, + 332, 379, 449, 540, 542, 553, 557, 559, 561, 567, + 570, 541, 543, 554, 558, 560, 562, 568, 571, 530, + 532, 534, 536, 549, 548, 545, 573, 574, 551, 556, + 535, 547, 552, 565, 572, 569, 529, 533, 537, 546, + 564, 563, 544, 555, 566, 550, 538, 531, 539, 1364, + 196, 221, 368, 1428, 454, 288, 647, 615, 484, 610, + 206, 223, 1300, 262, 1312, 1320, 0, 1326, 1334, 1335, + 1348, 1351, 1352, 1353, 1354, 1372, 1373, 1375, 1383, 1385, + 1388, 1390, 1397, 1411, 1431, 198, 200, 209, 222, 232, + 236, 243, 261, 276, 278, 285, 298, 310, 318, 319, + 322, 328, 380, 386, 387, 388, 389, 409, 410, 411, + 414, 417, 418, 421, 423, 424, 427, 431, 435, 436, + 437, 439, 441, 443, 455, 460, 474, 475, 476, 477, + 478, 481, 482, 488, 489, 490, 491, 492, 500, 501, + 516, 586, 588, 603, 622, 629, 480, 301, 302, 444, + 445, 314, 315, 643, 644, 300, 598, 630, 596, 642, + 624, 438, 378, 1363, 1369, 381, 281, 305, 320, 1378, + 614, 502, 227, 466, 290, 251, 1396, 1398, 211, 246, + 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, + 271, 244, 459, 241, 485, 519, 520, 521, 523, 395, + 266, 433, 1359, 1387, 376, 576, 577, 316, 396, 0, + 0, 0, 0, 0, 0, 1417, 1401, 528, 0, 1343, + 1420, 1311, 1330, 1430, 1333, 1336, 1380, 1289, 1358, 416, + 1327, 1315, 1284, 1322, 1285, 1313, 1345, 270, 1310, 1403, + 1362, 1419, 366, 267, 1291, 1282, 204, 505, 1316, 430, + 1332, 203, 1382, 487, 252, 377, 374, 583, 282, 273, + 269, 250, 317, 385, 428, 518, 422, 1426, 370, 1368, + 0, 497, 401, 0, 0, 0, 1407, 1406, 1337, 1347, + 1409, 1356, 1394, 1342, 1381, 1299, 1367, 1421, 1328, 1377, + 1422, 323, 248, 325, 202, 413, 498, 286, 0, 95, + 0, 0, 0, 507, 720, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 238, 0, 0, 245, 0, 0, + 0, 351, 360, 359, 339, 340, 342, 344, 350, 357, + 363, 336, 345, 1324, 1374, 607, 1416, 1325, 1376, 265, + 321, 272, 264, 580, 1427, 1408, 1288, 1355, 1415, 1350, + 0, 0, 229, 1418, 1349, 0, 1379, 0, 1433, 1283, + 1370, 0, 1286, 1290, 1429, 1413, 1319, 275, 0, 0, + 0, 0, 0, 0, 0, 1346, 1357, 1391, 1395, 1340, + 0, 0, 0, 0, 0, 0, 0, 0, 1317, 0, + 1366, 0, 0, 0, 1295, 1287, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1344, 0, + 0, 0, 0, 1298, 0, 1318, 1392, 0, 1281, 297, + 1292, 402, 257, 0, 453, 1399, 1412, 1341, 626, 1414, + 1339, 1338, 1386, 1296, 1405, 1331, 365, 1294, 330, 197, + 225, 0, 1329, 412, 461, 473, 1404, 1314, 1323, 253, + 1321, 471, 426, 602, 233, 284, 458, 432, 469, 440, + 287, 1365, 1384, 470, 372, 585, 450, 599, 627, 628, + 263, 406, 612, 522, 620, 645, 226, 260, 420, 506, + 605, 494, 397, 581, 582, 329, 493, 295, 201, 369, + 633, 224, 479, 371, 242, 231, 587, 609, 299, 289, + 456, 640, 213, 517, 597, 239, 483, 0, 0, 648, + 247, 504, 215, 594, 503, 393, 326, 327, 214, 0, + 457, 268, 293, 0, 0, 258, 415, 589, 590, 256, + 649, 228, 619, 220, 1293, 618, 408, 584, 595, 394, + 383, 219, 593, 392, 382, 334, 355, 356, 280, 307, + 447, 375, 448, 306, 308, 404, 403, 405, 207, 606, + 623, 0, 208, 0, 499, 608, 650, 452, 212, 234, + 235, 237, 1309, 279, 283, 291, 294, 303, 304, 313, + 367, 419, 446, 442, 451, 1400, 579, 600, 613, 625, + 631, 632, 634, 635, 636, 637, 638, 641, 639, 407, + 311, 495, 333, 373, 1389, 1432, 425, 472, 240, 604, + 496, 199, 1303, 1308, 1301, 0, 254, 255, 1371, 575, + 1304, 1302, 1360, 1361, 1305, 1423, 1424, 1425, 1410, 651, + 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, + 662, 663, 664, 665, 666, 667, 668, 646, 508, 514, + 509, 510, 511, 512, 513, 0, 515, 1393, 1297, 0, + 1306, 1307, 398, 1402, 591, 592, 669, 384, 486, 601, + 335, 349, 352, 341, 361, 0, 362, 337, 338, 343, + 346, 347, 348, 353, 354, 358, 364, 249, 210, 390, + 399, 578, 312, 216, 217, 218, 524, 525, 526, 527, + 616, 617, 621, 205, 462, 463, 464, 465, 292, 611, + 309, 468, 467, 331, 332, 379, 449, 540, 542, 553, + 557, 559, 561, 567, 570, 541, 543, 554, 558, 560, + 562, 568, 571, 530, 532, 534, 536, 549, 548, 545, + 573, 574, 551, 556, 535, 547, 552, 565, 572, 569, + 529, 533, 537, 546, 564, 563, 544, 555, 566, 550, + 538, 531, 539, 1364, 196, 221, 368, 1428, 454, 288, + 647, 615, 484, 610, 206, 223, 1300, 262, 1312, 1320, + 0, 1326, 1334, 1335, 1348, 1351, 1352, 1353, 1354, 1372, + 1373, 1375, 1383, 1385, 1388, 1390, 1397, 1411, 1431, 198, + 200, 209, 222, 232, 236, 243, 261, 276, 278, 285, + 298, 310, 318, 319, 322, 328, 380, 386, 387, 388, + 389, 409, 410, 411, 414, 417, 418, 421, 423, 424, + 427, 431, 435, 436, 437, 439, 441, 443, 455, 460, + 474, 475, 476, 477, 478, 481, 482, 488, 489, 490, + 491, 492, 500, 501, 516, 586, 588, 603, 622, 629, + 480, 301, 302, 444, 445, 314, 315, 643, 644, 300, + 598, 630, 596, 642, 624, 438, 378, 1363, 1369, 381, + 281, 305, 320, 1378, 614, 502, 227, 466, 290, 251, + 1396, 1398, 211, 246, 230, 259, 274, 277, 324, 391, + 400, 429, 434, 296, 271, 244, 459, 241, 485, 519, + 520, 521, 523, 395, 266, 433, 1359, 1387, 376, 576, + 577, 316, 396, 0, 0, 0, 0, 0, 0, 1417, + 1401, 528, 0, 1343, 1420, 1311, 1330, 1430, 1333, 1336, + 1380, 1289, 1358, 416, 1327, 1315, 1284, 1322, 1285, 1313, + 1345, 270, 1310, 1403, 1362, 1419, 366, 267, 1291, 1282, + 204, 505, 1316, 430, 1332, 203, 1382, 487, 252, 377, + 374, 583, 282, 273, 269, 250, 317, 385, 428, 518, + 422, 1426, 370, 1368, 0, 497, 401, 0, 0, 0, + 1407, 1406, 1337, 1347, 1409, 1356, 1394, 1342, 1381, 1299, + 1367, 1421, 1328, 1377, 1422, 323, 248, 325, 202, 413, + 498, 286, 0, 0, 0, 0, 0, 507, 194, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 238, 0, + 0, 245, 0, 0, 0, 351, 360, 359, 339, 340, + 342, 344, 350, 357, 363, 336, 345, 1324, 1374, 607, + 1416, 1325, 1376, 265, 321, 272, 264, 580, 1427, 1408, + 1288, 1355, 1415, 1350, 0, 0, 229, 1418, 1349, 0, + 1379, 0, 1433, 1283, 1370, 0, 1286, 1290, 1429, 1413, + 1319, 275, 0, 0, 0, 0, 0, 0, 0, 1346, + 1357, 1391, 1395, 1340, 0, 0, 0, 0, 0, 0, + 0, 0, 1317, 0, 1366, 0, 0, 0, 1295, 1287, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1344, 0, 0, 0, 0, 1298, 0, 1318, + 1392, 0, 1281, 297, 1292, 402, 257, 0, 453, 1399, + 1412, 1341, 626, 1414, 1339, 1338, 1386, 1296, 1405, 1331, + 365, 1294, 330, 197, 225, 0, 1329, 412, 461, 473, + 1404, 1314, 1323, 253, 1321, 471, 426, 602, 233, 284, + 458, 432, 469, 440, 287, 1365, 1384, 470, 372, 585, + 450, 599, 627, 628, 263, 406, 612, 522, 620, 645, + 226, 260, 420, 506, 605, 494, 397, 581, 582, 329, + 493, 295, 201, 369, 633, 224, 479, 371, 242, 231, + 587, 609, 299, 289, 456, 640, 213, 517, 597, 239, + 483, 0, 0, 648, 247, 504, 215, 594, 503, 393, + 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, + 415, 589, 590, 256, 649, 228, 619, 220, 1293, 618, + 408, 584, 595, 394, 383, 219, 593, 392, 382, 334, + 355, 356, 280, 307, 447, 375, 448, 306, 308, 404, + 403, 405, 207, 606, 623, 0, 208, 0, 499, 608, + 650, 452, 212, 234, 235, 237, 1309, 279, 283, 291, + 294, 303, 304, 313, 367, 419, 446, 442, 451, 1400, + 579, 600, 613, 625, 631, 632, 634, 635, 636, 637, + 638, 641, 639, 407, 311, 495, 333, 373, 1389, 1432, + 425, 472, 240, 604, 496, 199, 1303, 1308, 1301, 0, + 254, 255, 1371, 575, 1304, 1302, 1360, 1361, 1305, 1423, + 1424, 1425, 1410, 651, 652, 653, 654, 655, 656, 657, + 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, + 668, 646, 508, 514, 509, 510, 511, 512, 513, 0, + 515, 1393, 1297, 0, 1306, 1307, 398, 1402, 591, 592, + 669, 384, 486, 601, 335, 349, 352, 341, 361, 0, + 362, 337, 338, 343, 346, 347, 348, 353, 354, 358, + 364, 249, 210, 390, 399, 578, 312, 216, 217, 218, + 524, 525, 526, 527, 616, 617, 621, 205, 462, 463, + 464, 465, 292, 611, 309, 468, 467, 331, 332, 379, + 449, 540, 542, 553, 557, 559, 561, 567, 570, 541, + 543, 554, 558, 560, 562, 568, 571, 530, 532, 534, + 536, 549, 548, 545, 573, 574, 551, 556, 535, 547, + 552, 565, 572, 569, 529, 533, 537, 546, 564, 563, + 544, 555, 566, 550, 538, 531, 539, 1364, 196, 221, + 368, 1428, 454, 288, 647, 615, 484, 610, 206, 223, + 1300, 262, 1312, 1320, 0, 1326, 1334, 1335, 1348, 1351, + 1352, 1353, 1354, 1372, 1373, 1375, 1383, 1385, 1388, 1390, + 1397, 1411, 1431, 198, 200, 209, 222, 232, 236, 243, + 261, 276, 278, 285, 298, 310, 318, 319, 322, 328, + 380, 386, 387, 388, 389, 409, 410, 411, 414, 417, + 418, 421, 423, 424, 427, 431, 435, 436, 437, 439, + 441, 443, 455, 460, 474, 475, 476, 477, 478, 481, + 482, 488, 489, 490, 491, 492, 500, 501, 516, 586, + 588, 603, 622, 629, 480, 301, 302, 444, 445, 314, + 315, 643, 644, 300, 598, 630, 596, 642, 624, 438, + 378, 1363, 1369, 381, 281, 305, 320, 1378, 614, 502, + 227, 466, 290, 251, 1396, 1398, 211, 246, 230, 259, + 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, + 459, 241, 485, 519, 520, 521, 523, 395, 266, 433, + 1359, 1387, 376, 576, 577, 316, 396, 0, 0, 0, + 0, 0, 0, 1417, 1401, 528, 0, 1343, 1420, 1311, + 1330, 1430, 1333, 1336, 1380, 1289, 1358, 416, 1327, 1315, + 1284, 1322, 1285, 1313, 1345, 270, 1310, 1403, 1362, 1419, + 366, 267, 1291, 1282, 204, 505, 1316, 430, 1332, 203, + 1382, 487, 252, 377, 374, 583, 282, 273, 269, 250, + 317, 385, 428, 518, 422, 1426, 370, 1368, 0, 497, + 401, 0, 0, 0, 1407, 1406, 1337, 1347, 1409, 1356, + 1394, 1342, 1381, 1299, 1367, 1421, 1328, 1377, 1422, 323, + 248, 325, 202, 413, 498, 286, 0, 0, 0, 0, + 0, 507, 720, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 238, 0, 0, 245, 0, 0, 0, 351, + 360, 359, 339, 340, 342, 344, 350, 357, 363, 336, + 345, 1324, 1374, 607, 1416, 1325, 1376, 265, 321, 272, + 264, 580, 1427, 1408, 1288, 1355, 1415, 1350, 0, 0, + 229, 1418, 1349, 0, 1379, 0, 1433, 1283, 1370, 0, + 1286, 1290, 1429, 1413, 1319, 275, 0, 0, 0, 0, + 0, 0, 0, 1346, 1357, 1391, 1395, 1340, 0, 0, + 0, 0, 0, 0, 0, 0, 1317, 0, 1366, 0, + 0, 0, 1295, 1287, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1344, 0, 0, 0, + 0, 1298, 0, 1318, 1392, 0, 1281, 297, 1292, 402, + 257, 0, 453, 1399, 1412, 1341, 626, 1414, 1339, 1338, + 1386, 1296, 1405, 1331, 365, 1294, 330, 197, 225, 0, + 1329, 412, 461, 473, 1404, 1314, 1323, 253, 1321, 471, + 426, 602, 233, 284, 458, 432, 469, 440, 287, 1365, + 1384, 470, 372, 585, 450, 599, 627, 628, 263, 406, + 612, 522, 620, 645, 226, 260, 420, 506, 605, 494, + 397, 581, 582, 329, 493, 295, 201, 369, 633, 224, + 479, 371, 242, 231, 587, 609, 299, 289, 456, 640, + 213, 517, 597, 239, 483, 0, 0, 648, 247, 504, + 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, + 293, 0, 0, 258, 415, 589, 590, 256, 649, 228, + 619, 220, 1293, 618, 408, 584, 595, 394, 383, 219, + 593, 392, 382, 334, 355, 356, 280, 307, 447, 375, + 448, 306, 308, 404, 403, 405, 207, 606, 623, 0, + 208, 0, 499, 608, 650, 452, 212, 234, 235, 237, + 1309, 279, 283, 291, 294, 303, 304, 313, 367, 419, + 446, 442, 451, 1400, 579, 600, 613, 625, 631, 632, + 634, 635, 636, 637, 638, 641, 639, 407, 311, 495, + 333, 373, 1389, 1432, 425, 472, 240, 604, 496, 199, + 1303, 1308, 1301, 0, 254, 255, 1371, 575, 1304, 1302, + 1360, 1361, 1305, 1423, 1424, 1425, 1410, 651, 652, 653, + 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, + 664, 665, 666, 667, 668, 646, 508, 514, 509, 510, + 511, 512, 513, 0, 515, 1393, 1297, 0, 1306, 1307, + 398, 1402, 591, 592, 669, 384, 486, 601, 335, 349, + 352, 341, 361, 0, 362, 337, 338, 343, 346, 347, + 348, 353, 354, 358, 364, 249, 210, 390, 399, 578, + 312, 216, 217, 218, 524, 525, 526, 527, 616, 617, + 621, 205, 462, 463, 464, 465, 292, 611, 309, 468, + 467, 331, 332, 379, 449, 540, 542, 553, 557, 559, + 561, 567, 570, 541, 543, 554, 558, 560, 562, 568, + 571, 530, 532, 534, 536, 549, 548, 545, 573, 574, + 551, 556, 535, 547, 552, 565, 572, 569, 529, 533, + 537, 546, 564, 563, 544, 555, 566, 550, 538, 531, + 539, 1364, 196, 221, 368, 1428, 454, 288, 647, 615, + 484, 610, 206, 223, 1300, 262, 1312, 1320, 0, 1326, + 1334, 1335, 1348, 1351, 1352, 1353, 1354, 1372, 1373, 1375, + 1383, 1385, 1388, 1390, 1397, 1411, 1431, 198, 200, 209, + 222, 232, 236, 243, 261, 276, 278, 285, 298, 310, + 318, 319, 322, 328, 380, 386, 387, 388, 389, 409, + 410, 411, 414, 417, 418, 421, 423, 424, 427, 431, + 435, 436, 437, 439, 441, 443, 455, 460, 474, 475, + 476, 477, 478, 481, 482, 488, 489, 490, 491, 492, + 500, 501, 516, 586, 588, 603, 622, 629, 480, 301, + 302, 444, 445, 314, 315, 643, 644, 300, 598, 630, + 596, 642, 624, 438, 378, 1363, 1369, 381, 281, 305, + 320, 1378, 614, 502, 227, 466, 290, 251, 1396, 1398, + 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, + 434, 296, 271, 244, 459, 241, 485, 519, 520, 521, + 523, 395, 266, 433, 1359, 1387, 376, 576, 577, 316, + 396, 0, 0, 0, 0, 0, 0, 1417, 1401, 528, + 0, 1343, 1420, 1311, 1330, 1430, 1333, 1336, 1380, 1289, + 1358, 416, 1327, 1315, 1284, 1322, 1285, 1313, 1345, 270, + 1310, 1403, 1362, 1419, 366, 267, 1291, 1282, 204, 505, + 1316, 430, 1332, 203, 1382, 487, 252, 377, 374, 583, + 282, 273, 269, 250, 317, 385, 428, 518, 422, 1426, + 370, 1368, 0, 497, 401, 0, 0, 0, 1407, 1406, + 1337, 1347, 1409, 1356, 1394, 1342, 1381, 1299, 1367, 1421, + 1328, 1377, 1422, 323, 248, 325, 202, 413, 498, 286, + 0, 0, 0, 0, 0, 507, 955, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 238, 0, 0, 245, + 0, 0, 0, 351, 360, 359, 339, 340, 342, 344, + 350, 357, 363, 336, 345, 1324, 1374, 607, 1416, 1325, + 1376, 265, 321, 272, 264, 580, 1427, 1408, 1288, 1355, + 1415, 1350, 0, 0, 229, 1418, 1349, 0, 1379, 0, + 1433, 1283, 1370, 0, 1286, 1290, 1429, 1413, 1319, 275, + 0, 0, 0, 0, 0, 0, 0, 1346, 1357, 1391, + 1395, 1340, 0, 0, 0, 0, 0, 0, 0, 0, + 1317, 0, 1366, 0, 0, 0, 1295, 1287, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1344, 0, 0, 0, 0, 1298, 0, 1318, 1392, 0, + 1281, 297, 1292, 402, 257, 0, 453, 1399, 1412, 1341, + 626, 1414, 1339, 1338, 1386, 1296, 1405, 1331, 365, 1294, + 330, 197, 225, 0, 1329, 412, 461, 473, 1404, 1314, + 1323, 253, 1321, 471, 426, 602, 233, 284, 458, 432, + 469, 440, 287, 1365, 1384, 470, 372, 585, 450, 599, + 627, 628, 263, 406, 612, 522, 620, 645, 226, 260, + 420, 506, 605, 494, 397, 581, 582, 329, 493, 295, + 201, 369, 633, 224, 479, 371, 242, 231, 587, 609, + 299, 289, 456, 640, 213, 517, 597, 239, 483, 0, + 0, 648, 247, 504, 215, 594, 503, 393, 326, 327, + 214, 0, 457, 268, 293, 0, 0, 258, 415, 589, + 590, 256, 649, 228, 619, 220, 1293, 618, 408, 584, + 595, 394, 383, 219, 593, 392, 382, 334, 355, 356, + 280, 307, 447, 375, 448, 306, 308, 404, 403, 405, + 207, 606, 623, 0, 208, 0, 499, 608, 650, 452, + 212, 234, 235, 237, 1309, 279, 283, 291, 294, 303, + 304, 313, 367, 419, 446, 442, 451, 1400, 579, 600, + 613, 625, 631, 632, 634, 635, 636, 637, 638, 641, + 639, 407, 311, 495, 333, 373, 1389, 1432, 425, 472, + 240, 604, 496, 199, 1303, 1308, 1301, 0, 254, 255, + 1371, 575, 1304, 1302, 1360, 1361, 1305, 1423, 1424, 1425, + 1410, 651, 652, 653, 654, 655, 656, 657, 658, 659, + 660, 661, 662, 663, 664, 665, 666, 667, 668, 646, + 508, 514, 509, 510, 511, 512, 513, 0, 515, 1393, + 1297, 0, 1306, 1307, 398, 1402, 591, 592, 669, 384, + 486, 601, 335, 349, 352, 341, 361, 0, 362, 337, + 338, 343, 346, 347, 348, 353, 354, 358, 364, 249, + 210, 390, 399, 578, 312, 216, 217, 218, 524, 525, + 526, 527, 616, 617, 621, 205, 462, 463, 464, 465, + 292, 611, 309, 468, 467, 331, 332, 379, 449, 540, + 542, 553, 557, 559, 561, 567, 570, 541, 543, 554, + 558, 560, 562, 568, 571, 530, 532, 534, 536, 549, + 548, 545, 573, 574, 551, 556, 535, 547, 552, 565, + 572, 569, 529, 533, 537, 546, 564, 563, 544, 555, + 566, 550, 538, 531, 539, 1364, 196, 221, 368, 1428, + 454, 288, 647, 615, 484, 610, 206, 223, 1300, 262, + 1312, 1320, 0, 1326, 1334, 1335, 1348, 1351, 1352, 1353, + 1354, 1372, 1373, 1375, 1383, 1385, 1388, 1390, 1397, 1411, + 1431, 198, 200, 209, 222, 232, 236, 243, 261, 276, + 278, 285, 298, 310, 318, 319, 322, 328, 380, 386, + 387, 388, 389, 409, 410, 411, 414, 417, 418, 421, + 423, 424, 427, 431, 435, 436, 437, 439, 441, 443, + 455, 460, 474, 475, 476, 477, 478, 481, 482, 488, + 489, 490, 491, 492, 500, 501, 516, 586, 588, 603, + 622, 629, 480, 301, 302, 444, 445, 314, 315, 643, + 644, 300, 598, 630, 596, 642, 624, 438, 378, 1363, + 1369, 381, 281, 305, 320, 1378, 614, 502, 227, 466, + 290, 251, 1396, 1398, 211, 246, 230, 259, 274, 277, + 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, + 485, 519, 520, 521, 523, 395, 266, 433, 1359, 1387, + 376, 576, 577, 316, 396, 0, 0, 0, 0, 0, + 0, 0, 0, 528, 0, 773, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 416, 0, 0, 0, 760, + 0, 0, 0, 270, 765, 0, 0, 0, 366, 267, + 0, 0, 204, 505, 0, 430, 0, 203, 0, 487, + 252, 377, 374, 583, 282, 273, 269, 250, 317, 385, + 428, 518, 422, 772, 370, 0, 0, 497, 401, 0, + 0, 0, 0, 0, 0, 0, 0, 767, 768, 0, + 0, 0, 0, 0, 0, 0, 0, 323, 248, 325, + 202, 413, 498, 286, 0, 95, 0, 0, 1019, 507, + 955, 744, 921, 959, 1020, 972, 973, 974, 960, 0, + 238, 961, 962, 245, 963, 0, 920, 803, 805, 804, + 870, 871, 872, 873, 874, 875, 876, 806, 807, 801, + 968, 607, 975, 976, 0, 265, 321, 272, 264, 580, + 0, 0, 2224, 2225, 2226, 0, 0, 0, 229, 0, + 0, 0, 0, 0, 0, 0, 740, 757, 0, 771, + 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 754, 755, 0, 0, 0, 0, 915, 0, 756, 0, + 0, 764, 977, 978, 979, 980, 981, 982, 983, 984, + 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, + 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, + 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, + 1015, 1016, 1017, 1018, 766, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 297, 0, 402, 257, 0, + 453, 914, 0, 0, 626, 0, 0, 912, 0, 0, + 0, 0, 365, 0, 330, 197, 225, 0, 0, 412, + 461, 473, 0, 0, 0, 965, 0, 471, 426, 602, + 233, 284, 458, 432, 469, 440, 287, 0, 0, 470, + 372, 585, 450, 599, 627, 628, 263, 406, 612, 522, + 620, 645, 226, 260, 420, 506, 605, 494, 397, 581, + 582, 329, 493, 295, 201, 369, 633, 224, 479, 371, + 242, 231, 587, 609, 299, 289, 456, 640, 213, 517, + 597, 239, 483, 0, 0, 648, 247, 504, 215, 594, + 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, + 0, 258, 415, 966, 967, 256, 649, 811, 619, 220, + 0, 618, 408, 584, 595, 394, 383, 219, 593, 392, + 382, 334, 819, 820, 280, 307, 896, 895, 894, 306, + 308, 892, 893, 891, 207, 606, 623, 0, 208, 0, + 499, 608, 650, 452, 212, 234, 235, 237, 0, 279, + 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, + 451, 0, 579, 600, 613, 625, 631, 632, 634, 635, + 636, 637, 638, 641, 639, 407, 311, 495, 333, 373, + 0, 0, 425, 472, 240, 604, 496, 902, 924, 913, + 777, 778, 903, 904, 928, 905, 780, 781, 925, 926, + 774, 775, 779, 927, 929, 651, 652, 653, 654, 655, + 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, + 666, 667, 668, 646, 508, 514, 509, 510, 511, 512, + 513, 0, 515, 916, 763, 762, 0, 769, 770, 0, + 799, 800, 802, 808, 809, 810, 821, 868, 869, 877, + 879, 880, 878, 881, 882, 883, 886, 887, 888, 889, + 884, 885, 890, 782, 786, 783, 784, 785, 797, 787, + 788, 789, 790, 791, 792, 793, 794, 795, 796, 798, + 939, 940, 941, 942, 943, 944, 814, 818, 817, 815, + 816, 812, 813, 840, 839, 841, 842, 843, 844, 845, + 846, 848, 847, 849, 850, 851, 852, 853, 854, 822, + 823, 826, 827, 825, 824, 828, 837, 838, 829, 830, + 831, 832, 833, 834, 836, 835, 855, 856, 857, 858, + 859, 861, 860, 864, 865, 863, 862, 867, 866, 761, + 196, 221, 368, 0, 454, 288, 647, 615, 484, 610, + 206, 223, 930, 262, 931, 0, 0, 935, 0, 0, + 0, 937, 936, 0, 938, 900, 899, 0, 0, 932, + 933, 0, 934, 0, 0, 198, 200, 209, 222, 232, + 236, 243, 261, 276, 278, 285, 298, 310, 318, 319, + 322, 328, 380, 386, 387, 388, 389, 409, 410, 411, + 414, 417, 418, 421, 423, 424, 427, 431, 435, 436, + 437, 439, 441, 443, 455, 460, 474, 475, 476, 477, + 478, 481, 482, 488, 489, 490, 491, 492, 500, 501, + 516, 586, 588, 603, 622, 629, 480, 945, 946, 947, + 948, 949, 950, 951, 952, 300, 598, 630, 596, 642, + 624, 438, 378, 0, 0, 381, 281, 305, 320, 0, + 614, 502, 227, 466, 290, 251, 970, 0, 211, 246, + 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, + 271, 244, 459, 241, 485, 519, 520, 521, 523, 395, + 266, 433, 396, 0, 376, 576, 577, 316, 0, 0, + 0, 528, 0, 773, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 416, 0, 0, 0, 760, 0, 0, + 0, 270, 765, 0, 0, 0, 366, 267, 0, 0, + 204, 505, 0, 430, 0, 203, 0, 487, 252, 377, + 374, 583, 282, 273, 269, 250, 317, 385, 428, 518, + 422, 772, 370, 0, 0, 497, 401, 0, 0, 0, + 0, 0, 0, 0, 0, 767, 768, 0, 0, 0, + 0, 0, 0, 2431, 0, 323, 248, 325, 202, 413, + 498, 286, 0, 95, 0, 0, 1019, 507, 955, 744, + 921, 959, 1020, 972, 973, 974, 960, 0, 238, 961, + 962, 245, 963, 0, 920, 803, 805, 804, 870, 871, + 872, 873, 874, 875, 876, 806, 807, 801, 968, 607, + 975, 976, 2432, 265, 321, 272, 264, 580, 0, 0, + 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, + 0, 0, 0, 0, 740, 757, 0, 771, 0, 0, + 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 754, 755, + 0, 0, 0, 0, 915, 0, 756, 0, 0, 764, + 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, + 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, + 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, + 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, + 1017, 1018, 766, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 297, 0, 402, 257, 0, 453, 914, + 0, 0, 626, 0, 0, 912, 0, 0, 0, 0, + 365, 0, 330, 197, 225, 0, 0, 412, 461, 473, + 0, 0, 0, 965, 0, 471, 426, 602, 233, 284, + 458, 432, 469, 440, 287, 0, 0, 470, 372, 585, + 450, 599, 627, 628, 263, 406, 612, 522, 620, 645, + 226, 260, 420, 506, 605, 494, 397, 581, 582, 329, + 493, 295, 201, 369, 633, 224, 479, 371, 242, 231, + 587, 609, 299, 289, 456, 640, 213, 517, 597, 239, + 483, 0, 0, 648, 247, 504, 215, 594, 503, 393, + 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, + 415, 966, 967, 256, 649, 811, 619, 220, 0, 618, + 408, 584, 595, 394, 383, 219, 593, 392, 382, 334, + 819, 820, 280, 307, 896, 895, 894, 306, 308, 892, + 893, 891, 207, 606, 623, 0, 208, 0, 499, 608, + 650, 452, 212, 234, 235, 237, 0, 279, 283, 291, + 294, 303, 304, 313, 367, 419, 446, 442, 451, 0, + 579, 600, 613, 625, 631, 632, 634, 635, 636, 637, + 638, 641, 639, 407, 311, 495, 333, 373, 0, 0, + 425, 472, 240, 604, 496, 902, 924, 913, 777, 778, + 903, 904, 928, 905, 780, 781, 925, 926, 774, 775, + 779, 927, 929, 651, 652, 653, 654, 655, 656, 657, + 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, + 668, 646, 508, 514, 509, 510, 511, 512, 513, 0, + 515, 916, 763, 762, 0, 769, 770, 0, 799, 800, + 802, 808, 809, 810, 821, 868, 869, 877, 879, 880, + 878, 881, 882, 883, 886, 887, 888, 889, 884, 885, + 890, 782, 786, 783, 784, 785, 797, 787, 788, 789, + 790, 791, 792, 793, 794, 795, 796, 798, 939, 940, + 941, 942, 943, 944, 814, 818, 817, 815, 816, 812, + 813, 840, 839, 841, 842, 843, 844, 845, 846, 848, + 847, 849, 850, 851, 852, 853, 854, 822, 823, 826, + 827, 825, 824, 828, 837, 838, 829, 830, 831, 832, + 833, 834, 836, 835, 855, 856, 857, 858, 859, 861, + 860, 864, 865, 863, 862, 867, 866, 761, 196, 221, + 368, 0, 454, 288, 647, 615, 484, 610, 206, 223, + 930, 262, 931, 0, 0, 935, 0, 0, 0, 937, + 936, 0, 938, 900, 899, 0, 0, 932, 933, 0, + 934, 0, 0, 198, 200, 209, 222, 232, 236, 243, + 261, 276, 278, 285, 298, 310, 318, 319, 322, 328, + 380, 386, 387, 388, 389, 409, 410, 411, 414, 417, + 418, 421, 423, 424, 427, 431, 435, 436, 437, 439, + 441, 443, 455, 460, 474, 475, 476, 477, 478, 481, + 482, 488, 489, 490, 491, 492, 500, 501, 516, 586, + 588, 603, 622, 629, 480, 945, 946, 947, 948, 949, + 950, 951, 952, 300, 598, 630, 596, 642, 624, 438, + 378, 0, 0, 381, 281, 305, 320, 0, 614, 502, + 227, 466, 290, 251, 970, 0, 211, 246, 230, 259, + 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, + 459, 241, 485, 519, 520, 521, 523, 395, 266, 433, + 396, 0, 376, 576, 577, 316, 0, 0, 86, 528, + 0, 773, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 416, 0, 0, 0, 760, 0, 0, 0, 270, + 765, 0, 0, 0, 366, 267, 0, 0, 204, 505, + 0, 430, 0, 203, 0, 487, 252, 377, 374, 583, + 282, 273, 269, 250, 317, 385, 428, 518, 422, 772, + 370, 0, 0, 497, 401, 0, 0, 0, 0, 0, + 0, 0, 0, 767, 768, 0, 0, 0, 0, 0, + 0, 0, 0, 323, 248, 325, 202, 413, 498, 286, + 0, 95, 0, 0, 1019, 507, 955, 744, 921, 959, + 1020, 972, 973, 974, 960, 0, 238, 961, 962, 245, + 963, 0, 920, 803, 805, 804, 870, 871, 872, 873, + 874, 875, 876, 806, 807, 801, 968, 607, 975, 976, + 0, 265, 321, 272, 264, 580, 0, 0, 0, 0, + 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, + 0, 0, 740, 757, 0, 771, 0, 0, 0, 275, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 754, 755, 0, 0, + 0, 0, 915, 0, 756, 0, 0, 764, 977, 978, + 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, + 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, + 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, + 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, + 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 297, 0, 402, 257, 0, 453, 914, 0, 0, + 626, 0, 0, 912, 0, 0, 0, 0, 365, 0, + 330, 197, 225, 0, 0, 412, 461, 473, 0, 0, + 0, 965, 0, 471, 426, 602, 233, 284, 458, 432, + 469, 440, 287, 0, 0, 470, 372, 585, 450, 599, + 627, 628, 263, 406, 612, 522, 620, 645, 226, 260, + 420, 506, 605, 494, 397, 581, 582, 329, 493, 295, + 201, 369, 633, 224, 479, 371, 242, 231, 587, 609, + 299, 289, 456, 640, 213, 517, 597, 239, 483, 0, + 0, 648, 247, 504, 215, 594, 503, 393, 326, 327, + 214, 0, 457, 268, 293, 0, 0, 258, 415, 966, + 967, 256, 649, 811, 619, 220, 0, 618, 408, 584, + 595, 394, 383, 219, 593, 392, 382, 334, 819, 820, + 280, 307, 896, 895, 894, 306, 308, 892, 893, 891, + 207, 606, 623, 0, 208, 0, 499, 608, 650, 452, + 212, 234, 235, 237, 0, 279, 283, 291, 294, 303, + 304, 313, 367, 419, 446, 442, 451, 0, 579, 600, + 613, 625, 631, 632, 634, 635, 636, 637, 638, 641, + 639, 407, 311, 495, 333, 373, 0, 0, 425, 472, + 240, 604, 496, 902, 924, 913, 777, 778, 903, 904, + 928, 905, 780, 781, 925, 926, 774, 775, 779, 927, + 929, 651, 652, 653, 654, 655, 656, 657, 658, 659, + 660, 661, 662, 663, 664, 665, 666, 667, 668, 646, + 508, 514, 509, 510, 511, 512, 513, 0, 515, 916, + 763, 762, 0, 769, 770, 0, 799, 800, 802, 808, + 809, 810, 821, 868, 869, 877, 879, 880, 878, 881, + 882, 883, 886, 887, 888, 889, 884, 885, 890, 782, + 786, 783, 784, 785, 797, 787, 788, 789, 790, 791, + 792, 793, 794, 795, 796, 798, 939, 940, 941, 942, + 943, 944, 814, 818, 817, 815, 816, 812, 813, 840, + 839, 841, 842, 843, 844, 845, 846, 848, 847, 849, + 850, 851, 852, 853, 854, 822, 823, 826, 827, 825, + 824, 828, 837, 838, 829, 830, 831, 832, 833, 834, + 836, 835, 855, 856, 857, 858, 859, 861, 860, 864, + 865, 863, 862, 867, 866, 761, 196, 221, 368, 94, + 454, 288, 647, 615, 484, 610, 206, 223, 930, 262, + 931, 0, 0, 935, 0, 0, 0, 937, 936, 0, + 938, 900, 899, 0, 0, 932, 933, 0, 934, 0, + 0, 198, 200, 209, 222, 232, 236, 243, 261, 276, + 278, 285, 298, 310, 318, 319, 322, 328, 380, 386, + 387, 388, 389, 409, 410, 411, 414, 417, 418, 421, + 423, 424, 427, 431, 435, 436, 437, 439, 441, 443, + 455, 460, 474, 475, 476, 477, 478, 481, 482, 488, + 489, 490, 491, 492, 500, 501, 516, 586, 588, 603, + 622, 629, 480, 945, 946, 947, 948, 949, 950, 951, + 952, 300, 598, 630, 596, 642, 624, 438, 378, 0, + 0, 381, 281, 305, 320, 0, 614, 502, 227, 466, + 290, 251, 970, 0, 211, 246, 230, 259, 274, 277, + 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, + 485, 519, 520, 521, 523, 395, 266, 433, 396, 0, + 376, 576, 577, 316, 0, 0, 0, 528, 0, 773, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, + 0, 0, 0, 760, 0, 0, 0, 270, 765, 0, + 0, 0, 366, 267, 0, 0, 204, 505, 0, 430, + 0, 203, 0, 487, 252, 377, 374, 583, 282, 273, + 269, 250, 317, 385, 428, 518, 422, 772, 370, 0, + 0, 497, 401, 0, 0, 0, 0, 0, 0, 0, + 0, 767, 768, 0, 0, 0, 0, 0, 0, 0, + 0, 323, 248, 325, 202, 413, 498, 286, 0, 95, + 0, 0, 1019, 507, 955, 744, 921, 959, 1020, 972, + 973, 974, 960, 0, 238, 961, 962, 245, 963, 0, + 920, 803, 805, 804, 870, 871, 872, 873, 874, 875, + 876, 806, 807, 801, 968, 607, 975, 976, 0, 265, + 321, 272, 264, 580, 0, 0, 0, 0, 0, 0, + 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, + 740, 757, 0, 771, 0, 0, 0, 275, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 754, 755, 0, 0, 0, 0, + 915, 0, 756, 0, 0, 764, 977, 978, 979, 980, + 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, + 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, + 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, + 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 766, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 297, + 0, 402, 257, 0, 453, 914, 0, 0, 626, 0, + 0, 912, 0, 0, 0, 0, 365, 0, 330, 197, + 225, 0, 0, 412, 461, 473, 0, 0, 0, 965, + 0, 471, 426, 602, 233, 284, 458, 432, 469, 440, + 287, 4088, 0, 470, 372, 585, 450, 599, 627, 628, + 263, 406, 612, 522, 620, 645, 226, 260, 420, 506, + 605, 494, 397, 581, 582, 329, 493, 295, 201, 369, + 633, 224, 479, 371, 242, 231, 587, 609, 299, 289, + 456, 640, 213, 517, 597, 239, 483, 0, 0, 648, + 247, 504, 215, 594, 503, 393, 326, 327, 214, 0, + 457, 268, 293, 0, 0, 258, 415, 966, 967, 256, + 649, 811, 619, 220, 0, 618, 408, 584, 595, 394, + 383, 219, 593, 392, 382, 334, 819, 820, 280, 307, + 896, 895, 894, 306, 308, 892, 893, 891, 207, 606, + 623, 0, 208, 0, 499, 608, 650, 452, 212, 234, + 235, 237, 0, 279, 283, 291, 294, 303, 304, 313, + 367, 419, 446, 442, 451, 0, 579, 600, 613, 625, + 631, 632, 634, 635, 636, 637, 638, 641, 639, 407, + 311, 495, 333, 373, 0, 0, 425, 472, 240, 604, + 496, 902, 924, 913, 777, 778, 903, 904, 928, 905, + 780, 781, 925, 926, 774, 775, 779, 927, 929, 651, + 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, + 662, 663, 664, 665, 666, 667, 668, 646, 508, 514, + 509, 510, 511, 512, 513, 0, 515, 916, 763, 762, + 0, 769, 770, 0, 799, 800, 802, 808, 809, 810, + 821, 868, 869, 877, 879, 880, 878, 881, 882, 883, + 886, 887, 888, 889, 884, 885, 890, 782, 786, 783, + 784, 785, 797, 787, 788, 789, 790, 791, 792, 793, + 794, 795, 796, 798, 939, 940, 941, 942, 943, 944, + 814, 818, 817, 815, 816, 812, 813, 840, 839, 841, + 842, 843, 844, 845, 846, 848, 847, 849, 850, 851, + 852, 853, 854, 822, 823, 826, 827, 825, 824, 828, + 837, 838, 829, 830, 831, 832, 833, 834, 836, 835, + 855, 856, 857, 858, 859, 861, 860, 864, 865, 863, + 862, 867, 866, 761, 196, 221, 368, 0, 454, 288, + 647, 615, 484, 610, 206, 223, 930, 262, 931, 0, + 0, 935, 0, 0, 0, 937, 936, 0, 938, 900, + 899, 0, 0, 932, 933, 0, 934, 0, 0, 198, + 200, 209, 222, 232, 236, 243, 261, 276, 278, 285, + 298, 310, 318, 319, 322, 328, 380, 386, 387, 388, + 389, 409, 410, 411, 414, 417, 418, 421, 423, 424, + 427, 431, 435, 436, 437, 439, 441, 443, 455, 460, + 474, 475, 476, 477, 478, 481, 482, 488, 489, 490, + 491, 492, 500, 501, 516, 586, 588, 603, 622, 629, + 480, 945, 946, 947, 948, 949, 950, 951, 952, 300, + 598, 630, 596, 642, 624, 438, 378, 0, 0, 381, + 281, 305, 320, 0, 614, 502, 227, 466, 290, 251, + 970, 0, 211, 246, 230, 259, 274, 277, 324, 391, + 400, 429, 434, 296, 271, 244, 459, 241, 485, 519, + 520, 521, 523, 395, 266, 433, 396, 0, 376, 576, + 577, 316, 0, 0, 0, 528, 0, 773, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, + 0, 760, 0, 0, 0, 270, 765, 0, 0, 0, + 366, 267, 0, 0, 204, 505, 0, 430, 0, 203, + 0, 487, 252, 377, 374, 583, 282, 273, 269, 250, + 317, 385, 428, 518, 422, 772, 370, 0, 0, 497, + 401, 0, 0, 0, 0, 0, 0, 0, 0, 767, + 768, 0, 0, 0, 0, 0, 0, 0, 0, 323, + 248, 325, 202, 413, 498, 286, 0, 95, 0, 1747, + 1019, 507, 955, 744, 921, 959, 1020, 972, 973, 974, + 960, 0, 238, 961, 962, 245, 963, 0, 920, 803, + 805, 804, 870, 871, 872, 873, 874, 875, 876, 806, + 807, 801, 968, 607, 975, 976, 0, 265, 321, 272, + 264, 580, 0, 0, 0, 0, 0, 0, 0, 0, + 229, 0, 0, 0, 0, 0, 0, 0, 740, 757, + 0, 771, 0, 0, 0, 275, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 754, 755, 0, 0, 0, 0, 915, 0, + 756, 0, 0, 764, 977, 978, 979, 980, 981, 982, + 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, + 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, + 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, + 1013, 1014, 1015, 1016, 1017, 1018, 766, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 297, 0, 402, + 257, 0, 453, 914, 0, 0, 626, 0, 0, 912, + 0, 0, 0, 0, 365, 0, 330, 197, 225, 0, + 0, 412, 461, 473, 0, 0, 0, 965, 0, 471, + 426, 602, 233, 284, 458, 432, 469, 440, 287, 0, + 0, 470, 372, 585, 450, 599, 627, 628, 263, 406, + 612, 522, 620, 645, 226, 260, 420, 506, 605, 494, + 397, 581, 582, 329, 493, 295, 201, 369, 633, 224, + 479, 371, 242, 231, 587, 609, 299, 289, 456, 640, + 213, 517, 597, 239, 483, 0, 0, 648, 247, 504, + 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, + 293, 0, 0, 258, 415, 966, 967, 256, 649, 811, + 619, 220, 0, 618, 408, 584, 595, 394, 383, 219, + 593, 392, 382, 334, 819, 820, 280, 307, 896, 895, + 894, 306, 308, 892, 893, 891, 207, 606, 623, 0, + 208, 0, 499, 608, 650, 452, 212, 234, 235, 237, + 0, 279, 283, 291, 294, 303, 304, 313, 367, 419, + 446, 442, 451, 0, 579, 600, 613, 625, 631, 632, + 634, 635, 636, 637, 638, 641, 639, 407, 311, 495, + 333, 373, 0, 0, 425, 472, 240, 604, 496, 902, + 924, 913, 777, 778, 903, 904, 928, 905, 780, 781, + 925, 926, 774, 775, 779, 927, 929, 651, 652, 653, + 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, + 664, 665, 666, 667, 668, 646, 508, 514, 509, 510, + 511, 512, 513, 0, 515, 916, 763, 762, 0, 769, + 770, 0, 799, 800, 802, 808, 809, 810, 821, 868, + 869, 877, 879, 880, 878, 881, 882, 883, 886, 887, + 888, 889, 884, 885, 890, 782, 786, 783, 784, 785, + 797, 787, 788, 789, 790, 791, 792, 793, 794, 795, + 796, 798, 939, 940, 941, 942, 943, 944, 814, 818, + 817, 815, 816, 812, 813, 840, 839, 841, 842, 843, + 844, 845, 846, 848, 847, 849, 850, 851, 852, 853, + 854, 822, 823, 826, 827, 825, 824, 828, 837, 838, + 829, 830, 831, 832, 833, 834, 836, 835, 855, 856, + 857, 858, 859, 861, 860, 864, 865, 863, 862, 867, + 866, 761, 196, 221, 368, 0, 454, 288, 647, 615, + 484, 610, 206, 223, 930, 262, 931, 0, 0, 935, + 0, 0, 0, 937, 936, 0, 938, 900, 899, 0, + 0, 932, 933, 0, 934, 0, 0, 198, 200, 209, + 222, 232, 236, 243, 261, 276, 278, 285, 298, 310, + 318, 319, 322, 328, 380, 386, 387, 388, 389, 409, + 410, 411, 414, 417, 418, 421, 423, 424, 427, 431, + 435, 436, 437, 439, 441, 443, 455, 460, 474, 475, + 476, 477, 478, 481, 482, 488, 489, 490, 491, 492, + 500, 501, 516, 586, 588, 603, 622, 629, 480, 945, + 946, 947, 948, 949, 950, 951, 952, 300, 598, 630, + 596, 642, 624, 438, 378, 0, 0, 381, 281, 305, + 320, 0, 614, 502, 227, 466, 290, 251, 970, 0, + 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, + 434, 296, 271, 244, 459, 241, 485, 519, 520, 521, + 523, 395, 266, 433, 396, 0, 376, 576, 577, 316, + 0, 0, 0, 528, 0, 773, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 416, 0, 0, 0, 760, + 0, 0, 0, 270, 765, 0, 0, 0, 366, 267, + 0, 0, 204, 505, 0, 430, 0, 203, 0, 487, + 252, 377, 374, 583, 282, 273, 269, 250, 317, 385, + 428, 518, 422, 772, 370, 0, 0, 497, 401, 0, + 0, 0, 0, 0, 0, 0, 0, 767, 768, 0, + 0, 0, 0, 0, 0, 0, 0, 323, 248, 325, + 202, 413, 498, 286, 0, 95, 0, 0, 1019, 507, + 955, 744, 921, 959, 1020, 972, 973, 974, 960, 0, + 238, 961, 962, 245, 963, 0, 920, 803, 805, 804, + 870, 871, 872, 873, 874, 875, 876, 806, 807, 801, + 968, 607, 975, 976, 0, 265, 321, 272, 264, 580, + 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, + 0, 0, 0, 0, 0, 0, 740, 757, 0, 771, + 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 754, 755, 1065, 0, 0, 0, 915, 0, 756, 0, + 0, 764, 977, 978, 979, 980, 981, 982, 983, 984, + 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, + 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, + 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, + 1015, 1016, 1017, 1018, 766, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 297, 0, 402, 257, 0, + 453, 914, 0, 0, 626, 0, 0, 912, 0, 0, + 0, 0, 365, 0, 330, 197, 225, 0, 0, 412, + 461, 473, 0, 0, 0, 965, 0, 471, 426, 602, + 233, 284, 458, 432, 469, 440, 287, 0, 0, 470, + 372, 585, 450, 599, 627, 628, 263, 406, 612, 522, + 620, 645, 226, 260, 420, 506, 605, 494, 397, 581, + 582, 329, 493, 295, 201, 369, 633, 224, 479, 371, + 242, 231, 587, 609, 299, 289, 456, 640, 213, 517, + 597, 239, 483, 0, 0, 648, 247, 504, 215, 594, + 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, + 0, 258, 415, 966, 967, 256, 649, 811, 619, 220, + 0, 618, 408, 584, 595, 394, 383, 219, 593, 392, + 382, 334, 819, 820, 280, 307, 896, 895, 894, 306, + 308, 892, 893, 891, 207, 606, 623, 0, 208, 0, + 499, 608, 650, 452, 212, 234, 235, 237, 0, 279, + 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, + 451, 0, 579, 600, 613, 625, 631, 632, 634, 635, + 636, 637, 638, 641, 639, 407, 311, 495, 333, 373, + 0, 0, 425, 472, 240, 604, 496, 902, 924, 913, + 777, 778, 903, 904, 928, 905, 780, 781, 925, 926, + 774, 775, 779, 927, 929, 651, 652, 653, 654, 655, + 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, + 666, 667, 668, 646, 508, 514, 509, 510, 511, 512, + 513, 0, 515, 916, 763, 762, 0, 769, 770, 0, + 799, 800, 802, 808, 809, 810, 821, 868, 869, 877, + 879, 880, 878, 881, 882, 883, 886, 887, 888, 889, + 884, 885, 890, 782, 786, 783, 784, 785, 797, 787, + 788, 789, 790, 791, 792, 793, 794, 795, 796, 798, + 939, 940, 941, 942, 943, 944, 814, 818, 817, 815, + 816, 812, 813, 840, 839, 841, 842, 843, 844, 845, + 846, 848, 847, 849, 850, 851, 852, 853, 854, 822, + 823, 826, 827, 825, 824, 828, 837, 838, 829, 830, + 831, 832, 833, 834, 836, 835, 855, 856, 857, 858, + 859, 861, 860, 864, 865, 863, 862, 867, 866, 761, + 196, 221, 368, 0, 454, 288, 647, 615, 484, 610, + 206, 223, 930, 262, 931, 0, 0, 935, 0, 0, + 0, 937, 936, 0, 938, 900, 899, 0, 0, 932, + 933, 0, 934, 0, 0, 198, 200, 209, 222, 232, + 236, 243, 261, 276, 278, 285, 298, 310, 318, 319, + 322, 328, 380, 386, 387, 388, 389, 409, 410, 411, + 414, 417, 418, 421, 423, 424, 427, 431, 435, 436, + 437, 439, 441, 443, 455, 460, 474, 475, 476, 477, + 478, 481, 482, 488, 489, 490, 491, 492, 500, 501, + 516, 586, 588, 603, 622, 629, 480, 945, 946, 947, + 948, 949, 950, 951, 952, 300, 598, 630, 596, 642, + 624, 438, 378, 0, 0, 381, 281, 305, 320, 0, + 614, 502, 227, 466, 290, 251, 970, 0, 211, 246, + 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, + 271, 244, 459, 241, 485, 519, 520, 521, 523, 395, + 266, 433, 396, 0, 376, 576, 577, 316, 0, 0, + 0, 528, 0, 773, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 416, 0, 0, 0, 760, 0, 0, + 0, 270, 765, 0, 0, 0, 366, 267, 0, 0, + 204, 505, 0, 430, 0, 203, 0, 487, 252, 377, + 374, 583, 282, 273, 269, 250, 317, 385, 428, 518, + 422, 772, 370, 0, 0, 497, 401, 0, 0, 0, + 0, 0, 0, 0, 0, 767, 768, 0, 0, 0, + 0, 0, 0, 0, 0, 323, 248, 325, 202, 413, + 498, 286, 0, 95, 0, 0, 1019, 507, 955, 744, + 921, 959, 1020, 972, 973, 974, 960, 0, 238, 961, + 962, 245, 963, 0, 920, 803, 805, 804, 870, 871, + 872, 873, 874, 875, 876, 806, 807, 801, 968, 607, + 975, 976, 0, 265, 321, 272, 264, 580, 0, 0, + 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, + 0, 0, 0, 0, 740, 757, 0, 771, 0, 0, + 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 754, 755, + 0, 0, 0, 0, 915, 0, 756, 0, 0, 764, + 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, + 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, + 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, + 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, + 1017, 1018, 766, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 297, 0, 402, 257, 0, 453, 914, + 0, 0, 626, 0, 0, 912, 0, 0, 0, 0, + 365, 0, 330, 197, 225, 0, 0, 412, 461, 473, + 0, 0, 0, 965, 0, 471, 426, 602, 233, 284, + 458, 432, 469, 440, 287, 0, 0, 470, 372, 585, + 450, 599, 627, 628, 263, 406, 612, 522, 620, 645, + 226, 260, 420, 506, 605, 494, 397, 581, 582, 329, + 493, 295, 201, 369, 633, 224, 479, 371, 242, 231, + 587, 609, 299, 289, 456, 640, 213, 517, 597, 239, + 483, 0, 0, 648, 247, 504, 215, 594, 503, 393, + 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, + 415, 966, 967, 256, 649, 811, 619, 220, 0, 618, + 408, 584, 595, 394, 383, 219, 593, 392, 382, 334, + 819, 820, 280, 307, 896, 895, 894, 306, 308, 892, + 893, 891, 207, 606, 623, 0, 208, 0, 499, 608, + 650, 452, 212, 234, 235, 237, 0, 279, 283, 291, + 294, 303, 304, 313, 367, 419, 446, 442, 451, 0, + 579, 600, 613, 625, 631, 632, 634, 635, 636, 637, + 638, 641, 639, 407, 311, 495, 333, 373, 0, 0, + 425, 472, 240, 604, 496, 902, 924, 913, 777, 778, + 903, 904, 928, 905, 780, 781, 925, 926, 774, 775, + 779, 927, 929, 651, 652, 653, 654, 655, 656, 657, + 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, + 668, 646, 508, 514, 509, 510, 511, 512, 513, 0, + 515, 916, 763, 762, 0, 769, 770, 0, 799, 800, + 802, 808, 809, 810, 821, 868, 869, 877, 879, 880, + 878, 881, 882, 883, 886, 887, 888, 889, 884, 885, + 890, 782, 786, 783, 784, 785, 797, 787, 788, 789, + 790, 791, 792, 793, 794, 795, 796, 798, 939, 940, + 941, 942, 943, 944, 814, 818, 817, 815, 816, 812, + 813, 840, 839, 841, 842, 843, 844, 845, 846, 848, + 847, 849, 850, 851, 852, 853, 854, 822, 823, 826, + 827, 825, 824, 828, 837, 838, 829, 830, 831, 832, + 833, 834, 836, 835, 855, 856, 857, 858, 859, 861, + 860, 864, 865, 863, 862, 867, 866, 761, 196, 221, + 368, 0, 454, 288, 647, 615, 484, 610, 206, 223, + 930, 262, 931, 0, 0, 935, 0, 0, 0, 937, + 936, 0, 938, 900, 899, 0, 0, 932, 933, 0, + 934, 0, 0, 198, 200, 209, 222, 232, 236, 243, + 261, 276, 278, 285, 298, 310, 318, 319, 322, 328, + 380, 386, 387, 388, 389, 409, 410, 411, 414, 417, + 418, 421, 423, 424, 427, 431, 435, 436, 437, 439, + 441, 443, 455, 460, 474, 475, 476, 477, 478, 481, + 482, 488, 489, 490, 491, 492, 500, 501, 516, 586, + 588, 603, 622, 629, 480, 945, 946, 947, 948, 949, + 950, 951, 952, 300, 598, 630, 596, 642, 624, 438, + 378, 0, 0, 381, 281, 305, 320, 0, 614, 502, + 227, 466, 290, 251, 970, 0, 211, 246, 230, 259, + 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, + 459, 241, 485, 519, 520, 521, 523, 395, 266, 433, + 396, 0, 376, 576, 577, 316, 0, 0, 0, 528, + 0, 773, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 416, 0, 0, 0, 760, 0, 0, 0, 270, + 765, 0, 0, 0, 366, 267, 0, 0, 204, 505, + 0, 430, 0, 203, 0, 487, 252, 377, 374, 583, + 282, 273, 269, 250, 317, 385, 428, 518, 422, 772, + 370, 0, 0, 497, 401, 0, 0, 0, 0, 0, + 0, 0, 0, 767, 768, 0, 0, 0, 0, 0, + 0, 0, 0, 323, 248, 325, 202, 413, 498, 286, + 0, 95, 0, 0, 1019, 507, 955, 744, 921, 959, + 1020, 972, 973, 974, 960, 0, 238, 961, 962, 245, + 963, 0, 920, 803, 805, 804, 870, 871, 872, 873, + 874, 875, 876, 806, 807, 801, 968, 607, 975, 976, + 0, 265, 321, 272, 264, 580, 0, 0, 0, 0, + 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, + 0, 0, 740, 757, 0, 771, 0, 0, 0, 275, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 754, 755, 0, 0, + 0, 0, 915, 0, 756, 0, 0, 764, 977, 978, + 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, + 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, + 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, + 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, + 3163, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 297, 0, 402, 257, 0, 453, 914, 0, 0, + 626, 0, 0, 912, 0, 0, 0, 0, 365, 0, + 330, 197, 225, 0, 0, 412, 461, 473, 0, 0, + 0, 965, 0, 471, 426, 602, 233, 284, 458, 432, + 469, 440, 287, 0, 0, 470, 372, 585, 450, 599, + 627, 628, 263, 406, 612, 522, 620, 645, 226, 260, + 420, 506, 605, 494, 397, 581, 582, 329, 493, 295, + 201, 369, 633, 224, 479, 371, 242, 231, 587, 609, + 299, 289, 456, 640, 213, 517, 597, 239, 483, 0, + 0, 648, 247, 504, 215, 594, 503, 393, 326, 327, + 214, 0, 457, 268, 293, 0, 0, 258, 415, 966, + 967, 256, 649, 811, 619, 220, 0, 618, 408, 584, + 595, 394, 383, 219, 593, 392, 382, 334, 819, 820, + 280, 307, 896, 895, 894, 306, 308, 892, 893, 891, + 207, 606, 623, 0, 208, 0, 499, 608, 650, 452, + 212, 234, 235, 237, 0, 279, 283, 291, 294, 303, + 304, 313, 367, 419, 446, 442, 451, 0, 579, 600, + 613, 625, 631, 632, 634, 635, 636, 637, 638, 641, + 639, 407, 311, 495, 333, 373, 0, 0, 425, 472, + 240, 604, 496, 902, 924, 913, 777, 778, 903, 904, + 928, 905, 780, 781, 925, 926, 774, 775, 779, 927, + 929, 651, 652, 653, 654, 655, 656, 657, 658, 659, + 660, 661, 662, 663, 664, 665, 666, 667, 668, 646, + 508, 514, 509, 510, 511, 512, 513, 0, 515, 916, + 763, 762, 0, 769, 770, 0, 799, 800, 802, 808, + 809, 810, 821, 868, 869, 877, 879, 880, 878, 881, + 882, 883, 886, 887, 888, 889, 884, 885, 890, 782, + 786, 783, 784, 785, 797, 787, 788, 789, 790, 791, + 792, 793, 794, 795, 796, 798, 939, 940, 941, 942, + 943, 944, 814, 818, 817, 815, 816, 812, 813, 840, + 839, 841, 842, 843, 844, 845, 846, 848, 847, 849, + 850, 851, 852, 853, 854, 822, 823, 826, 827, 825, + 824, 828, 837, 838, 829, 830, 831, 832, 833, 834, + 836, 835, 855, 856, 857, 858, 859, 861, 860, 864, + 865, 863, 862, 867, 866, 761, 196, 221, 368, 0, + 454, 288, 647, 615, 484, 610, 206, 223, 930, 262, + 931, 0, 0, 935, 0, 0, 0, 937, 936, 0, + 938, 900, 899, 0, 0, 932, 933, 0, 934, 0, + 0, 198, 200, 209, 222, 232, 236, 243, 261, 276, + 278, 285, 298, 310, 318, 319, 322, 328, 380, 386, + 387, 388, 389, 409, 410, 411, 414, 417, 418, 421, + 423, 424, 427, 431, 435, 436, 437, 439, 441, 443, + 455, 460, 474, 475, 476, 477, 478, 481, 482, 488, + 489, 490, 491, 492, 500, 501, 516, 586, 588, 603, + 622, 629, 480, 945, 946, 947, 948, 949, 950, 951, + 952, 300, 598, 630, 596, 642, 624, 438, 378, 0, + 0, 381, 281, 305, 320, 0, 614, 502, 227, 466, + 290, 251, 970, 0, 211, 246, 230, 259, 274, 277, + 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, + 485, 519, 520, 521, 523, 395, 266, 433, 396, 0, + 376, 576, 577, 316, 0, 0, 0, 528, 0, 773, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, + 0, 0, 0, 760, 0, 0, 0, 270, 765, 0, + 0, 0, 366, 267, 0, 0, 204, 505, 0, 430, + 0, 203, 0, 487, 252, 377, 374, 583, 282, 273, + 269, 250, 317, 385, 428, 518, 422, 772, 370, 0, + 0, 497, 401, 0, 0, 0, 0, 0, 0, 0, + 0, 767, 768, 0, 0, 0, 0, 0, 0, 0, + 0, 323, 248, 325, 202, 413, 498, 286, 0, 95, + 0, 0, 1019, 507, 955, 744, 921, 959, 1020, 972, + 973, 974, 960, 0, 238, 961, 962, 245, 963, 0, + 920, 803, 805, 804, 870, 871, 872, 873, 874, 875, + 876, 806, 807, 801, 968, 607, 975, 976, 0, 265, + 321, 272, 264, 580, 0, 0, 0, 0, 0, 0, + 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, + 740, 757, 0, 771, 0, 0, 0, 275, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 754, 755, 0, 0, 0, 0, + 915, 0, 756, 0, 0, 764, 977, 978, 979, 980, + 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, + 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, + 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, + 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 3159, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 297, + 0, 402, 257, 0, 453, 914, 0, 0, 626, 0, + 0, 912, 0, 0, 0, 0, 365, 0, 330, 197, + 225, 0, 0, 412, 461, 473, 0, 0, 0, 965, + 0, 471, 426, 602, 233, 284, 458, 432, 469, 440, + 287, 0, 0, 470, 372, 585, 450, 599, 627, 628, + 263, 406, 612, 522, 620, 645, 226, 260, 420, 506, + 605, 494, 397, 581, 582, 329, 493, 295, 201, 369, + 633, 224, 479, 371, 242, 231, 587, 609, 299, 289, + 456, 640, 213, 517, 597, 239, 483, 0, 0, 648, + 247, 504, 215, 594, 503, 393, 326, 327, 214, 0, + 457, 268, 293, 0, 0, 258, 415, 966, 967, 256, + 649, 811, 619, 220, 0, 618, 408, 584, 595, 394, + 383, 219, 593, 392, 382, 334, 819, 820, 280, 307, + 896, 895, 894, 306, 308, 892, 893, 891, 207, 606, + 623, 0, 208, 0, 499, 608, 650, 452, 212, 234, + 235, 237, 0, 279, 283, 291, 294, 303, 304, 313, + 367, 419, 446, 442, 451, 0, 579, 600, 613, 625, + 631, 632, 634, 635, 636, 637, 638, 641, 639, 407, + 311, 495, 333, 373, 0, 0, 425, 472, 240, 604, + 496, 902, 924, 913, 777, 778, 903, 904, 928, 905, + 780, 781, 925, 926, 774, 775, 779, 927, 929, 651, + 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, + 662, 663, 664, 665, 666, 667, 668, 646, 508, 514, + 509, 510, 511, 512, 513, 0, 515, 916, 763, 762, + 0, 769, 770, 0, 799, 800, 802, 808, 809, 810, + 821, 868, 869, 877, 879, 880, 878, 881, 882, 883, + 886, 887, 888, 889, 884, 885, 890, 782, 786, 783, + 784, 785, 797, 787, 788, 789, 790, 791, 792, 793, + 794, 795, 796, 798, 939, 940, 941, 942, 943, 944, + 814, 818, 817, 815, 816, 812, 813, 840, 839, 841, + 842, 843, 844, 845, 846, 848, 847, 849, 850, 851, + 852, 853, 854, 822, 823, 826, 827, 825, 824, 828, + 837, 838, 829, 830, 831, 832, 833, 834, 836, 835, + 855, 856, 857, 858, 859, 861, 860, 864, 865, 863, + 862, 867, 866, 761, 196, 221, 368, 0, 454, 288, + 647, 615, 484, 610, 206, 223, 930, 262, 931, 0, + 0, 935, 0, 0, 0, 937, 936, 0, 938, 900, + 899, 0, 0, 932, 933, 0, 934, 0, 0, 198, + 200, 209, 222, 232, 236, 243, 261, 276, 278, 285, + 298, 310, 318, 319, 322, 328, 380, 386, 387, 388, + 389, 409, 410, 411, 414, 417, 418, 421, 423, 424, + 427, 431, 435, 436, 437, 439, 441, 443, 455, 460, + 474, 475, 476, 477, 478, 481, 482, 488, 489, 490, + 491, 492, 500, 501, 516, 586, 588, 603, 622, 629, + 480, 945, 946, 947, 948, 949, 950, 951, 952, 300, + 598, 630, 596, 642, 624, 438, 378, 0, 0, 381, + 281, 305, 320, 0, 614, 502, 227, 466, 290, 251, + 970, 0, 211, 246, 230, 259, 274, 277, 324, 391, + 400, 429, 434, 296, 271, 244, 459, 241, 485, 519, + 520, 521, 523, 395, 266, 433, 396, 0, 376, 576, + 577, 316, 0, 0, 0, 528, 0, 773, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, + 0, 760, 0, 0, 0, 270, 765, 0, 0, 0, + 366, 267, 0, 0, 204, 505, 0, 430, 0, 203, + 0, 487, 252, 377, 374, 583, 282, 273, 269, 250, + 317, 385, 428, 518, 422, 772, 370, 0, 0, 497, + 401, 0, 0, 0, 0, 0, 0, 0, 0, 767, + 768, 0, 0, 0, 0, 0, 0, 0, 0, 323, + 248, 325, 202, 413, 498, 286, 0, 95, 0, 0, + 1019, 507, 955, 1086, 921, 959, 1020, 972, 973, 974, + 960, 0, 238, 961, 962, 245, 963, 0, 920, 803, + 805, 804, 870, 871, 872, 873, 874, 875, 876, 806, + 807, 801, 968, 607, 975, 976, 0, 265, 321, 272, + 264, 580, 0, 0, 0, 0, 0, 0, 0, 0, + 229, 0, 0, 0, 0, 0, 0, 0, 0, 757, + 0, 771, 0, 0, 0, 275, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 754, 755, 0, 0, 0, 0, 915, 0, + 756, 0, 0, 764, 977, 978, 979, 980, 981, 982, + 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, + 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, + 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, + 1013, 1014, 1015, 1016, 1017, 1018, 766, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 297, 0, 402, + 257, 0, 453, 914, 0, 0, 626, 0, 0, 912, + 0, 0, 0, 0, 365, 0, 330, 197, 225, 0, + 0, 412, 461, 473, 0, 0, 0, 965, 0, 471, + 426, 602, 233, 284, 458, 432, 469, 440, 287, 0, + 0, 470, 372, 585, 450, 599, 627, 628, 263, 406, + 612, 522, 620, 645, 226, 260, 420, 506, 605, 494, + 397, 581, 582, 329, 493, 295, 201, 369, 633, 224, + 479, 371, 242, 231, 587, 609, 299, 289, 456, 640, + 213, 517, 597, 239, 483, 0, 0, 648, 247, 504, + 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, + 293, 0, 0, 258, 415, 966, 967, 256, 649, 811, + 619, 220, 0, 618, 408, 584, 595, 394, 383, 219, + 593, 392, 382, 334, 819, 820, 280, 307, 896, 895, + 894, 306, 308, 892, 893, 891, 207, 606, 623, 0, + 208, 0, 499, 608, 650, 452, 212, 234, 235, 237, + 0, 279, 283, 291, 294, 303, 304, 313, 367, 419, + 446, 442, 451, 0, 579, 600, 613, 625, 631, 632, + 634, 635, 636, 637, 638, 641, 639, 407, 311, 495, + 333, 373, 0, 0, 425, 472, 240, 604, 496, 902, + 924, 913, 777, 778, 903, 904, 928, 905, 780, 781, + 925, 926, 774, 775, 779, 927, 929, 651, 652, 653, + 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, + 664, 665, 666, 667, 668, 646, 508, 514, 509, 510, + 511, 512, 513, 0, 515, 916, 763, 762, 0, 769, + 770, 0, 799, 800, 802, 808, 809, 810, 821, 868, + 869, 877, 879, 880, 878, 881, 882, 883, 886, 887, + 888, 889, 884, 885, 890, 782, 786, 783, 784, 785, + 797, 787, 788, 789, 790, 791, 792, 793, 794, 795, + 796, 798, 939, 940, 941, 942, 943, 944, 814, 818, + 817, 815, 816, 812, 813, 840, 839, 841, 842, 843, + 844, 845, 846, 848, 847, 849, 850, 851, 852, 853, + 854, 822, 823, 826, 827, 825, 824, 828, 837, 838, + 829, 830, 831, 832, 833, 834, 836, 835, 855, 856, + 857, 858, 859, 861, 860, 864, 865, 863, 862, 867, + 866, 761, 196, 221, 368, 0, 454, 288, 647, 615, + 484, 610, 206, 223, 930, 262, 931, 0, 0, 935, + 0, 0, 0, 937, 936, 0, 938, 900, 899, 0, + 0, 932, 933, 0, 934, 0, 0, 198, 200, 209, + 222, 232, 236, 243, 261, 276, 278, 285, 298, 310, + 318, 319, 322, 328, 380, 386, 387, 388, 389, 409, + 410, 411, 414, 417, 418, 421, 423, 424, 427, 431, + 435, 436, 437, 439, 441, 443, 455, 460, 474, 475, + 476, 477, 478, 481, 482, 488, 489, 490, 491, 492, + 500, 501, 516, 586, 588, 603, 622, 629, 480, 945, + 946, 947, 948, 949, 950, 951, 952, 300, 598, 630, + 596, 642, 624, 438, 378, 0, 0, 381, 281, 305, + 320, 0, 614, 502, 227, 466, 290, 251, 970, 0, + 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, + 434, 296, 271, 244, 459, 241, 485, 519, 520, 521, + 523, 395, 266, 433, 396, 0, 376, 576, 577, 316, + 0, 0, 0, 528, 0, 773, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 416, 0, 0, 0, 760, + 0, 0, 0, 270, 765, 0, 0, 0, 366, 267, + 0, 0, 204, 505, 0, 430, 0, 203, 0, 487, + 252, 377, 374, 583, 282, 273, 269, 250, 317, 385, + 428, 518, 422, 772, 370, 0, 0, 497, 401, 0, + 0, 0, 0, 0, 0, 0, 0, 767, 768, 0, + 0, 0, 0, 0, 0, 0, 0, 323, 248, 325, + 202, 413, 498, 286, 0, 95, 0, 0, 1019, 507, + 955, 1086, 921, 959, 1020, 972, 973, 974, 960, 0, + 238, 961, 962, 245, 963, 0, 920, 803, 805, 804, + 870, 871, 872, 873, 874, 875, 876, 806, 807, 801, + 968, 607, 975, 976, 0, 265, 321, 272, 264, 580, + 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, + 0, 0, 0, 0, 0, 0, 0, 757, 0, 771, + 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 754, 755, 0, 0, 0, 0, 915, 0, 756, 0, + 0, 764, 977, 978, 979, 980, 981, 982, 983, 984, + 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, + 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, + 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, + 1015, 1016, 1017, 1018, 2115, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 297, 0, 402, 257, 0, + 453, 914, 0, 0, 626, 0, 0, 912, 0, 0, + 0, 0, 365, 0, 330, 197, 225, 0, 0, 412, + 461, 473, 0, 0, 0, 965, 0, 471, 426, 602, + 233, 284, 458, 432, 469, 440, 287, 0, 0, 470, + 372, 585, 450, 599, 627, 628, 263, 406, 612, 522, + 620, 645, 226, 260, 420, 506, 605, 494, 397, 581, + 582, 329, 493, 295, 201, 369, 633, 224, 479, 371, + 242, 231, 587, 609, 299, 289, 456, 640, 213, 517, + 597, 239, 483, 0, 0, 648, 247, 504, 215, 594, + 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, + 0, 258, 415, 966, 967, 256, 649, 811, 619, 220, + 0, 618, 408, 584, 595, 394, 383, 219, 593, 392, + 382, 334, 819, 820, 280, 307, 896, 895, 894, 306, + 308, 892, 893, 891, 207, 606, 623, 0, 208, 0, + 499, 608, 650, 452, 212, 234, 235, 237, 0, 279, + 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, + 451, 0, 579, 600, 613, 625, 631, 632, 634, 635, + 636, 637, 638, 641, 639, 407, 311, 495, 333, 373, + 0, 0, 425, 472, 240, 604, 496, 902, 924, 913, + 777, 778, 903, 904, 928, 905, 780, 781, 925, 926, + 774, 775, 779, 927, 929, 651, 652, 653, 654, 655, + 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, + 666, 667, 668, 646, 508, 514, 509, 510, 511, 512, + 513, 0, 515, 916, 763, 762, 0, 769, 770, 0, + 799, 800, 802, 808, 809, 810, 821, 868, 869, 877, + 879, 880, 878, 881, 882, 883, 886, 887, 888, 889, + 884, 885, 890, 782, 786, 783, 784, 785, 797, 787, + 788, 789, 790, 791, 792, 793, 794, 795, 796, 798, + 939, 940, 941, 942, 943, 944, 814, 818, 817, 815, + 816, 812, 813, 840, 839, 841, 842, 843, 844, 845, + 846, 848, 847, 849, 850, 851, 852, 853, 854, 822, + 823, 826, 827, 825, 824, 828, 837, 838, 829, 830, + 831, 832, 833, 834, 836, 835, 855, 856, 857, 858, + 859, 861, 860, 864, 865, 863, 862, 867, 866, 761, + 196, 221, 368, 0, 454, 288, 647, 615, 484, 610, + 206, 223, 930, 262, 931, 0, 0, 935, 0, 0, + 0, 937, 936, 0, 938, 900, 899, 0, 0, 932, + 933, 0, 934, 0, 0, 198, 200, 209, 222, 232, + 236, 243, 261, 276, 278, 285, 298, 310, 318, 319, + 322, 328, 380, 386, 387, 388, 389, 409, 410, 411, + 414, 417, 418, 421, 423, 424, 427, 431, 435, 436, + 437, 439, 441, 443, 455, 460, 474, 475, 476, 477, + 478, 481, 482, 488, 489, 490, 491, 492, 500, 501, + 516, 586, 588, 603, 622, 629, 480, 945, 946, 947, + 948, 949, 950, 951, 952, 300, 598, 630, 596, 642, + 624, 438, 378, 0, 0, 381, 281, 305, 320, 0, + 614, 502, 227, 466, 290, 251, 970, 0, 211, 246, + 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, + 271, 244, 459, 241, 485, 519, 520, 521, 523, 395, + 266, 433, 396, 0, 376, 576, 577, 316, 0, 0, + 0, 528, 0, 773, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 416, 0, 0, 0, 760, 0, 0, + 0, 270, 765, 0, 0, 0, 366, 267, 0, 0, + 204, 505, 0, 430, 0, 203, 0, 487, 252, 377, + 374, 583, 282, 273, 269, 250, 317, 385, 428, 518, + 422, 772, 370, 0, 0, 497, 401, 0, 0, 0, + 0, 0, 0, 0, 0, 767, 768, 0, 0, 0, + 0, 0, 0, 0, 0, 323, 248, 325, 202, 413, + 498, 286, 0, 95, 0, 0, 1019, 507, 955, 1086, + 921, 959, 1020, 972, 973, 974, 960, 0, 238, 961, + 962, 245, 963, 0, 920, 803, 805, 804, 870, 871, + 872, 873, 874, 875, 876, 806, 807, 801, 968, 607, + 975, 976, 0, 265, 321, 272, 264, 580, 0, 0, + 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, + 0, 0, 0, 0, 0, 757, 0, 771, 0, 0, + 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 754, 755, + 0, 0, 0, 0, 915, 0, 756, 0, 0, 764, + 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, + 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, + 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, + 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, + 1017, 1018, 2113, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 297, 0, 402, 257, 0, 453, 914, + 0, 0, 626, 0, 0, 912, 0, 0, 0, 0, + 365, 0, 330, 197, 225, 0, 0, 412, 461, 473, + 0, 0, 0, 965, 0, 471, 426, 602, 233, 284, + 458, 432, 469, 440, 287, 0, 0, 470, 372, 585, + 450, 599, 627, 628, 263, 406, 612, 522, 620, 645, + 226, 260, 420, 506, 605, 494, 397, 581, 582, 329, + 493, 295, 201, 369, 633, 224, 479, 371, 242, 231, + 587, 609, 299, 289, 456, 640, 213, 517, 597, 239, + 483, 0, 0, 648, 247, 504, 215, 594, 503, 393, + 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, + 415, 966, 967, 256, 649, 811, 619, 220, 0, 618, + 408, 584, 595, 394, 383, 219, 593, 392, 382, 334, + 819, 820, 280, 307, 896, 895, 894, 306, 308, 892, + 893, 891, 207, 606, 623, 0, 208, 0, 499, 608, + 650, 452, 212, 234, 235, 237, 0, 279, 283, 291, + 294, 303, 304, 313, 367, 419, 446, 442, 451, 0, + 579, 600, 613, 625, 631, 632, 634, 635, 636, 637, + 638, 641, 639, 407, 311, 495, 333, 373, 0, 0, + 425, 472, 240, 604, 496, 902, 924, 913, 777, 778, + 903, 904, 928, 905, 780, 781, 925, 926, 774, 775, + 779, 927, 929, 651, 652, 653, 654, 655, 656, 657, + 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, + 668, 646, 508, 514, 509, 510, 511, 512, 513, 0, + 515, 916, 763, 762, 0, 769, 770, 0, 799, 800, + 802, 808, 809, 810, 821, 868, 869, 877, 879, 880, + 878, 881, 882, 883, 886, 887, 888, 889, 884, 885, + 890, 782, 786, 783, 784, 785, 797, 787, 788, 789, + 790, 791, 792, 793, 794, 795, 796, 798, 939, 940, + 941, 942, 943, 944, 814, 818, 817, 815, 816, 812, + 813, 840, 839, 841, 842, 843, 844, 845, 846, 848, + 847, 849, 850, 851, 852, 853, 854, 822, 823, 826, + 827, 825, 824, 828, 837, 838, 829, 830, 831, 832, + 833, 834, 836, 835, 855, 856, 857, 858, 859, 861, + 860, 864, 865, 863, 862, 867, 866, 761, 196, 221, + 368, 0, 454, 288, 647, 615, 484, 610, 206, 223, + 930, 262, 931, 0, 0, 935, 0, 0, 0, 937, + 936, 0, 938, 900, 899, 0, 0, 932, 933, 0, + 934, 0, 0, 198, 200, 209, 222, 232, 236, 243, + 261, 276, 278, 285, 298, 310, 318, 319, 322, 328, + 380, 386, 387, 388, 389, 409, 410, 411, 414, 417, + 418, 421, 423, 424, 427, 431, 435, 436, 437, 439, + 441, 443, 455, 460, 474, 475, 476, 477, 478, 481, + 482, 488, 489, 490, 491, 492, 500, 501, 516, 586, + 588, 603, 622, 629, 480, 945, 946, 947, 948, 949, + 950, 951, 952, 300, 598, 630, 596, 642, 624, 438, + 378, 0, 0, 381, 281, 305, 320, 0, 614, 502, + 227, 466, 290, 251, 970, 0, 211, 246, 230, 259, + 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, + 459, 241, 485, 519, 520, 521, 523, 395, 266, 433, + 396, 0, 376, 576, 577, 316, 0, 0, 0, 528, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 416, 0, 0, 0, 0, 0, 0, 0, 270, + 0, 0, 0, 0, 366, 267, 0, 0, 204, 505, + 0, 430, 0, 203, 0, 487, 252, 377, 374, 583, + 282, 273, 269, 250, 317, 385, 428, 518, 422, 0, + 370, 0, 0, 497, 401, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 323, 248, 325, 202, 413, 498, 286, + 0, 0, 0, 0, 0, 507, 720, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 238, 0, 0, 245, + 0, 0, 0, 351, 360, 359, 339, 340, 342, 344, + 350, 357, 363, 336, 345, 0, 0, 607, 0, 0, + 0, 265, 321, 272, 264, 580, 0, 0, 0, 0, + 0, 0, 0, 0, 229, 0, 1137, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 297, 0, 402, 257, 0, 453, 0, 0, 1136, + 626, 0, 0, 0, 0, 0, 1133, 1134, 365, 1094, + 330, 197, 225, 1127, 1131, 412, 461, 473, 0, 0, + 0, 253, 0, 471, 426, 602, 233, 284, 458, 432, + 469, 440, 287, 0, 0, 470, 372, 585, 450, 599, + 627, 628, 263, 406, 612, 522, 620, 645, 226, 260, + 420, 506, 605, 494, 397, 581, 582, 329, 493, 295, + 201, 369, 633, 224, 479, 371, 242, 231, 587, 609, + 299, 289, 456, 640, 213, 517, 597, 239, 483, 0, + 0, 648, 247, 504, 215, 594, 503, 393, 326, 327, + 214, 0, 457, 268, 293, 0, 0, 258, 415, 589, + 590, 256, 649, 228, 619, 220, 0, 618, 408, 584, + 595, 394, 383, 219, 593, 392, 382, 334, 355, 356, + 280, 307, 447, 375, 448, 306, 308, 404, 403, 405, + 207, 606, 623, 0, 208, 0, 499, 608, 650, 452, + 212, 234, 235, 237, 0, 279, 283, 291, 294, 303, + 304, 313, 367, 419, 446, 442, 451, 0, 579, 600, + 613, 625, 631, 632, 634, 635, 636, 637, 638, 641, + 639, 407, 311, 495, 333, 373, 0, 0, 425, 472, + 240, 604, 496, 199, 0, 0, 0, 0, 254, 255, + 0, 575, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 651, 652, 653, 654, 655, 656, 657, 658, 659, + 660, 661, 662, 663, 664, 665, 666, 667, 668, 646, + 508, 514, 509, 510, 511, 512, 513, 0, 515, 0, + 0, 0, 0, 0, 398, 0, 591, 592, 669, 384, + 486, 601, 335, 349, 352, 341, 361, 0, 362, 337, + 338, 343, 346, 347, 348, 353, 354, 358, 364, 249, + 210, 390, 399, 578, 312, 216, 217, 218, 524, 525, + 526, 527, 616, 617, 621, 205, 462, 463, 464, 465, + 292, 611, 309, 468, 467, 331, 332, 379, 449, 540, + 542, 553, 557, 559, 561, 567, 570, 541, 543, 554, + 558, 560, 562, 568, 571, 530, 532, 534, 536, 549, + 548, 545, 573, 574, 551, 556, 535, 547, 552, 565, + 572, 569, 529, 533, 537, 546, 564, 563, 544, 555, + 566, 550, 538, 531, 539, 0, 196, 221, 368, 0, + 454, 288, 647, 615, 484, 610, 206, 223, 0, 262, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 198, 200, 209, 222, 232, 236, 243, 261, 276, + 278, 285, 298, 310, 318, 319, 322, 328, 380, 386, + 387, 388, 389, 409, 410, 411, 414, 417, 418, 421, + 423, 424, 427, 431, 435, 436, 437, 439, 441, 443, + 455, 460, 474, 475, 476, 477, 478, 481, 482, 488, + 489, 490, 491, 492, 500, 501, 516, 586, 588, 603, + 622, 629, 480, 301, 302, 444, 445, 314, 315, 643, + 644, 300, 598, 630, 596, 642, 624, 438, 378, 0, + 0, 381, 281, 305, 320, 0, 614, 502, 227, 466, + 290, 251, 0, 0, 211, 246, 230, 259, 274, 277, + 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, + 485, 519, 520, 521, 523, 395, 266, 433, 396, 0, + 376, 576, 577, 316, 0, 0, 0, 528, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 95, 0, 0, 0, - 948, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, + 0, 0, 366, 267, 0, 0, 204, 505, 0, 430, + 0, 203, 0, 487, 252, 377, 374, 583, 282, 273, + 269, 250, 317, 385, 428, 518, 422, 0, 370, 0, + 0, 497, 401, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 323, 248, 325, 202, 413, 498, 286, 0, 0, + 0, 0, 1704, 507, 955, 0, 0, 1701, 0, 0, + 0, 0, 1699, 0, 238, 1700, 1698, 245, 1703, 0, + 920, 351, 360, 359, 339, 340, 342, 344, 350, 357, + 363, 336, 345, 0, 0, 607, 0, 0, 0, 265, + 321, 272, 264, 580, 0, 0, 0, 0, 0, 0, + 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 275, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 297, + 0, 402, 257, 0, 453, 0, 0, 0, 626, 0, + 0, 0, 0, 0, 0, 0, 365, 0, 330, 197, + 225, 0, 0, 412, 461, 473, 0, 0, 0, 253, + 0, 471, 426, 602, 233, 284, 458, 432, 469, 440, + 287, 0, 0, 470, 372, 585, 450, 599, 627, 628, + 263, 406, 612, 522, 620, 645, 226, 260, 420, 506, + 605, 494, 397, 581, 582, 329, 493, 295, 201, 369, + 633, 224, 479, 371, 242, 231, 587, 609, 299, 289, + 456, 640, 213, 517, 597, 239, 483, 0, 0, 648, + 247, 504, 215, 594, 503, 393, 326, 327, 214, 0, + 457, 268, 293, 0, 0, 258, 415, 589, 590, 256, + 649, 228, 619, 220, 0, 618, 408, 584, 595, 394, + 383, 219, 593, 392, 382, 334, 355, 356, 280, 307, + 447, 375, 448, 306, 308, 404, 403, 405, 207, 606, + 623, 0, 208, 0, 499, 608, 650, 452, 212, 234, + 235, 237, 0, 279, 283, 291, 294, 303, 304, 313, + 367, 419, 446, 442, 451, 0, 579, 600, 613, 625, + 631, 632, 634, 635, 636, 637, 638, 641, 639, 407, + 311, 495, 333, 373, 0, 0, 425, 472, 240, 604, + 496, 199, 0, 0, 0, 0, 254, 255, 0, 575, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 651, + 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, + 662, 663, 664, 665, 666, 667, 668, 646, 508, 514, + 509, 510, 511, 512, 513, 0, 515, 0, 0, 0, + 0, 0, 398, 0, 591, 592, 669, 384, 486, 601, + 335, 349, 352, 341, 361, 0, 362, 337, 338, 343, + 346, 347, 348, 353, 354, 358, 364, 249, 210, 390, + 399, 578, 312, 216, 217, 218, 524, 525, 526, 527, + 616, 617, 621, 205, 462, 463, 464, 465, 292, 611, + 309, 468, 467, 331, 332, 379, 449, 540, 542, 553, + 557, 559, 561, 567, 570, 541, 543, 554, 558, 560, + 562, 568, 571, 530, 532, 534, 536, 549, 548, 545, + 573, 574, 551, 556, 535, 547, 552, 565, 572, 569, + 529, 533, 537, 546, 564, 563, 544, 555, 566, 550, + 538, 531, 539, 0, 196, 221, 368, 0, 454, 288, + 647, 615, 484, 610, 206, 223, 0, 262, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, + 200, 209, 222, 232, 236, 243, 261, 276, 278, 285, + 298, 310, 318, 319, 322, 328, 380, 386, 387, 388, + 389, 409, 410, 411, 414, 417, 418, 421, 423, 424, + 427, 431, 435, 436, 437, 439, 441, 443, 455, 460, + 474, 475, 476, 477, 478, 481, 482, 488, 489, 490, + 491, 492, 500, 501, 516, 586, 588, 603, 622, 629, + 480, 301, 302, 444, 445, 314, 315, 643, 644, 300, + 598, 630, 596, 642, 624, 438, 378, 0, 0, 381, + 281, 305, 320, 0, 614, 502, 227, 466, 290, 251, + 0, 0, 211, 246, 230, 259, 274, 277, 324, 391, + 400, 429, 434, 296, 271, 244, 459, 241, 485, 519, + 520, 521, 523, 395, 266, 433, 396, 0, 376, 576, + 577, 316, 0, 0, 86, 528, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, + 0, 0, 0, 0, 0, 270, 0, 0, 0, 0, + 366, 267, 0, 0, 204, 505, 0, 430, 0, 203, + 0, 487, 252, 377, 374, 583, 282, 273, 269, 250, + 317, 385, 428, 518, 422, 0, 370, 0, 0, 497, + 401, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 323, + 248, 325, 202, 413, 498, 286, 0, 95, 0, 0, + 0, 507, 194, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 238, 0, 0, 245, 0, 0, 0, 351, + 360, 359, 339, 340, 342, 344, 350, 357, 363, 336, + 345, 0, 0, 607, 0, 0, 0, 265, 321, 272, + 264, 580, 0, 0, 0, 0, 0, 0, 0, 0, + 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 275, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 297, 0, 402, + 257, 0, 453, 0, 0, 0, 626, 0, 0, 0, + 0, 0, 0, 0, 365, 0, 330, 197, 225, 0, + 0, 412, 461, 473, 0, 0, 0, 253, 0, 471, + 426, 602, 233, 284, 458, 432, 469, 440, 287, 0, + 0, 470, 372, 585, 450, 599, 627, 628, 263, 406, + 612, 522, 620, 645, 226, 260, 420, 506, 605, 494, + 397, 581, 582, 329, 493, 295, 201, 369, 633, 224, + 479, 371, 242, 231, 587, 609, 299, 289, 456, 640, + 213, 517, 597, 239, 483, 0, 0, 648, 247, 504, + 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, + 293, 0, 0, 258, 415, 589, 590, 256, 649, 228, + 619, 220, 0, 618, 408, 584, 595, 394, 383, 219, + 593, 392, 382, 334, 355, 356, 280, 307, 447, 375, + 448, 306, 308, 404, 403, 405, 207, 606, 623, 0, + 208, 0, 499, 608, 650, 452, 212, 234, 235, 237, + 0, 279, 283, 291, 294, 303, 304, 313, 367, 419, + 446, 442, 451, 0, 579, 600, 613, 625, 631, 632, + 634, 635, 636, 637, 638, 641, 639, 407, 311, 495, + 333, 373, 0, 0, 425, 472, 240, 604, 496, 199, + 0, 0, 0, 0, 254, 255, 0, 575, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 651, 652, 653, + 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, + 664, 665, 666, 667, 668, 646, 508, 514, 509, 510, + 511, 512, 513, 0, 515, 0, 0, 0, 0, 0, + 398, 0, 591, 592, 669, 384, 486, 601, 335, 349, + 352, 341, 361, 0, 362, 337, 338, 343, 346, 347, + 348, 353, 354, 358, 364, 249, 210, 390, 399, 578, + 312, 216, 217, 218, 524, 525, 526, 527, 616, 617, + 621, 205, 462, 463, 464, 465, 292, 611, 309, 468, + 467, 331, 332, 379, 449, 540, 542, 553, 557, 559, + 561, 567, 570, 541, 543, 554, 558, 560, 562, 568, + 571, 530, 532, 534, 536, 549, 548, 545, 573, 574, + 551, 556, 535, 547, 552, 565, 572, 569, 529, 533, + 537, 546, 564, 563, 544, 555, 566, 550, 538, 531, + 539, 0, 196, 221, 368, 94, 454, 288, 647, 615, + 484, 610, 206, 223, 0, 262, 0, 0, 0, 0, + 0, 0, 2418, 0, 0, 2417, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 198, 200, 209, + 222, 232, 236, 243, 261, 276, 278, 285, 298, 310, + 318, 319, 322, 328, 380, 386, 387, 388, 389, 409, + 410, 411, 414, 417, 418, 421, 423, 424, 427, 431, + 435, 436, 437, 439, 441, 443, 455, 460, 474, 475, + 476, 477, 478, 481, 482, 488, 489, 490, 491, 492, + 500, 501, 516, 586, 588, 603, 622, 629, 480, 301, + 302, 444, 445, 314, 315, 643, 644, 300, 598, 630, + 596, 642, 624, 438, 378, 0, 0, 381, 281, 305, + 320, 0, 614, 502, 227, 466, 290, 251, 0, 0, + 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, + 434, 296, 271, 244, 459, 241, 485, 519, 520, 521, + 523, 395, 266, 433, 1770, 0, 376, 576, 577, 316, + 0, 0, 0, 528, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 416, 0, 0, 1772, 0, + 0, 0, 0, 270, 0, 0, 0, 0, 366, 267, + 0, 0, 204, 505, 0, 430, 0, 203, 0, 487, + 252, 377, 374, 583, 282, 273, 269, 250, 317, 385, + 428, 518, 422, 0, 370, 0, 0, 497, 401, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 323, 248, 325, + 202, 413, 498, 286, 0, 0, 0, 0, 1774, 507, + 720, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 245, 0, 0, 0, 351, 360, 359, + 339, 340, 342, 344, 350, 357, 363, 336, 345, 0, + 0, 607, 0, 0, 0, 265, 321, 272, 264, 580, + 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, + 0, 0, 1472, 0, 1473, 1474, 0, 0, 0, 0, + 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 297, 0, 402, 257, 0, + 453, 0, 0, 0, 626, 0, 0, 0, 0, 0, + 0, 0, 365, 0, 330, 197, 225, 0, 0, 412, + 461, 473, 0, 0, 0, 253, 0, 471, 426, 602, + 233, 284, 458, 432, 469, 440, 287, 0, 0, 470, + 372, 585, 450, 599, 627, 628, 263, 406, 612, 522, + 620, 645, 226, 260, 420, 506, 605, 494, 397, 581, + 582, 329, 493, 295, 201, 369, 633, 224, 479, 371, + 242, 231, 587, 609, 299, 289, 456, 640, 213, 517, + 597, 239, 483, 0, 0, 648, 247, 504, 215, 594, + 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, + 0, 258, 415, 589, 590, 256, 649, 228, 619, 220, + 0, 618, 408, 584, 595, 394, 383, 219, 593, 392, + 382, 334, 355, 356, 280, 307, 447, 375, 448, 306, + 308, 404, 403, 405, 207, 606, 623, 0, 208, 0, + 499, 608, 650, 452, 212, 234, 235, 237, 0, 279, + 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, + 451, 0, 579, 600, 613, 625, 631, 632, 634, 635, + 636, 637, 638, 641, 639, 407, 311, 495, 333, 373, + 0, 0, 425, 472, 240, 604, 496, 199, 0, 0, + 0, 0, 254, 255, 0, 575, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 651, 652, 653, 654, 655, + 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, + 666, 667, 668, 646, 508, 514, 509, 510, 511, 512, + 513, 0, 515, 0, 0, 0, 0, 0, 398, 0, + 591, 592, 669, 384, 486, 601, 335, 349, 352, 341, + 361, 0, 362, 337, 338, 343, 346, 347, 348, 353, + 354, 358, 364, 249, 210, 390, 399, 578, 312, 216, + 217, 218, 524, 525, 526, 527, 616, 617, 621, 205, + 462, 463, 464, 465, 292, 611, 309, 468, 467, 331, + 332, 379, 449, 540, 542, 553, 557, 559, 561, 567, + 570, 541, 543, 554, 558, 560, 562, 568, 571, 530, + 532, 534, 536, 549, 548, 545, 573, 574, 551, 556, + 535, 547, 552, 565, 572, 569, 529, 533, 537, 546, + 564, 563, 544, 555, 566, 550, 538, 531, 539, 0, + 196, 221, 368, 0, 454, 288, 647, 615, 484, 610, + 206, 223, 0, 262, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 198, 200, 209, 222, 232, + 236, 243, 261, 276, 278, 285, 298, 310, 318, 319, + 322, 328, 380, 386, 387, 388, 389, 409, 410, 411, + 414, 417, 418, 421, 423, 424, 427, 431, 435, 436, + 437, 439, 441, 443, 455, 460, 474, 475, 476, 477, + 478, 481, 482, 488, 489, 490, 491, 492, 500, 501, + 516, 586, 588, 603, 622, 629, 480, 301, 302, 444, + 445, 314, 315, 643, 644, 300, 598, 630, 596, 642, + 624, 438, 378, 0, 0, 381, 281, 305, 320, 0, + 614, 502, 227, 466, 290, 251, 0, 0, 211, 246, + 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, + 271, 244, 459, 241, 485, 519, 520, 521, 523, 395, + 266, 433, 396, 0, 376, 576, 577, 316, 0, 0, + 86, 528, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 270, 0, 0, 0, 0, 366, 267, 0, 0, + 204, 505, 0, 430, 0, 203, 0, 487, 252, 377, + 374, 583, 282, 273, 269, 250, 317, 385, 428, 518, + 422, 0, 370, 0, 0, 497, 401, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 323, 248, 325, 202, 413, + 498, 286, 0, 95, 0, 1747, 0, 507, 720, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 238, 0, + 0, 245, 0, 0, 0, 351, 360, 359, 339, 340, + 342, 344, 350, 357, 363, 336, 345, 0, 0, 607, + 0, 0, 0, 265, 321, 272, 264, 580, 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6734,69 +4614,365 @@ 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, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, - 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, + 0, 0, 0, 297, 0, 402, 257, 0, 453, 0, + 0, 0, 626, 0, 0, 0, 0, 0, 0, 0, + 365, 0, 330, 197, 225, 0, 0, 412, 461, 473, + 0, 0, 0, 253, 0, 471, 426, 602, 233, 284, + 458, 432, 469, 440, 287, 0, 0, 470, 372, 585, + 450, 599, 627, 628, 263, 406, 612, 522, 620, 645, + 226, 260, 420, 506, 605, 494, 397, 581, 582, 329, + 493, 295, 201, 369, 633, 224, 479, 371, 242, 231, + 587, 609, 299, 289, 456, 640, 213, 517, 597, 239, + 483, 0, 0, 648, 247, 504, 215, 594, 503, 393, + 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, + 415, 589, 590, 256, 649, 228, 619, 220, 0, 618, + 408, 584, 595, 394, 383, 219, 593, 392, 382, 334, + 355, 356, 280, 307, 447, 375, 448, 306, 308, 404, + 403, 405, 207, 606, 623, 0, 208, 0, 499, 608, + 650, 452, 212, 234, 235, 237, 0, 279, 283, 291, + 294, 303, 304, 313, 367, 419, 446, 442, 451, 0, + 579, 600, 613, 625, 631, 632, 634, 635, 636, 637, + 638, 641, 639, 407, 311, 495, 333, 373, 0, 0, + 425, 472, 240, 604, 496, 199, 0, 0, 0, 0, + 254, 255, 0, 575, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 651, 652, 653, 654, 655, 656, 657, + 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, + 668, 646, 508, 514, 509, 510, 511, 512, 513, 0, + 515, 0, 0, 0, 0, 0, 398, 0, 591, 592, + 669, 384, 486, 601, 335, 349, 352, 341, 361, 0, + 362, 337, 338, 343, 346, 347, 348, 353, 354, 358, + 364, 249, 210, 390, 399, 578, 312, 216, 217, 218, + 524, 525, 526, 527, 616, 617, 621, 205, 462, 463, + 464, 465, 292, 611, 309, 468, 467, 331, 332, 379, + 449, 540, 542, 553, 557, 559, 561, 567, 570, 541, + 543, 554, 558, 560, 562, 568, 571, 530, 532, 534, + 536, 549, 548, 545, 573, 574, 551, 556, 535, 547, + 552, 565, 572, 569, 529, 533, 537, 546, 564, 563, + 544, 555, 566, 550, 538, 531, 539, 0, 196, 221, + 368, 94, 454, 288, 647, 615, 484, 610, 206, 223, + 0, 262, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 198, 200, 209, 222, 232, 236, 243, + 261, 276, 278, 285, 298, 310, 318, 319, 322, 328, + 380, 386, 387, 388, 389, 409, 410, 411, 414, 417, + 418, 421, 423, 424, 427, 431, 435, 436, 437, 439, + 441, 443, 455, 460, 474, 475, 476, 477, 478, 481, + 482, 488, 489, 490, 491, 492, 500, 501, 516, 586, + 588, 603, 622, 629, 480, 301, 302, 444, 445, 314, + 315, 643, 644, 300, 598, 630, 596, 642, 624, 438, + 378, 0, 0, 381, 281, 305, 320, 0, 614, 502, + 227, 466, 290, 251, 0, 0, 211, 246, 230, 259, + 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, + 459, 241, 485, 519, 520, 521, 523, 395, 266, 433, + 396, 0, 376, 576, 577, 316, 0, 0, 0, 528, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 416, 0, 0, 0, 0, 0, 0, 0, 270, + 0, 0, 0, 0, 366, 267, 0, 0, 204, 505, + 0, 430, 0, 203, 0, 487, 252, 377, 374, 583, + 282, 273, 269, 250, 317, 385, 428, 518, 422, 0, + 370, 0, 0, 497, 401, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 323, 248, 325, 202, 413, 498, 286, + 0, 95, 0, 0, 0, 507, 194, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 238, 0, 0, 245, + 0, 0, 0, 351, 360, 359, 339, 340, 342, 344, + 350, 357, 363, 336, 345, 0, 0, 607, 0, 0, + 0, 265, 321, 272, 264, 580, 0, 0, 0, 0, + 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 297, 0, 402, 257, 0, 453, 0, 0, 0, + 626, 0, 0, 0, 0, 0, 0, 0, 365, 0, + 330, 197, 225, 0, 0, 412, 461, 473, 0, 0, + 0, 253, 0, 471, 426, 602, 233, 284, 458, 432, + 469, 440, 287, 0, 0, 470, 372, 585, 450, 599, + 627, 628, 263, 406, 612, 522, 620, 645, 226, 260, + 420, 506, 605, 494, 397, 581, 582, 329, 493, 295, + 201, 369, 633, 224, 479, 371, 242, 231, 587, 609, + 299, 289, 456, 640, 213, 517, 597, 239, 483, 0, + 0, 648, 247, 504, 215, 594, 503, 393, 326, 327, + 214, 0, 457, 268, 293, 0, 0, 258, 415, 589, + 590, 256, 649, 228, 619, 220, 0, 618, 408, 584, + 595, 394, 383, 219, 593, 392, 382, 334, 355, 356, + 280, 307, 447, 375, 448, 306, 308, 404, 403, 405, + 207, 606, 623, 0, 208, 0, 499, 608, 650, 452, + 212, 234, 235, 237, 0, 279, 283, 291, 294, 303, + 304, 313, 367, 419, 446, 442, 451, 0, 579, 600, + 613, 625, 631, 632, 634, 635, 636, 637, 638, 641, + 639, 407, 311, 495, 333, 373, 0, 0, 425, 472, + 240, 604, 496, 199, 0, 0, 0, 0, 254, 255, + 0, 575, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 651, 652, 653, 654, 655, 656, 657, 658, 659, + 660, 661, 662, 663, 664, 665, 666, 667, 668, 646, + 508, 514, 509, 510, 511, 512, 513, 0, 515, 0, + 0, 0, 0, 0, 398, 0, 591, 592, 669, 384, + 486, 601, 335, 349, 352, 341, 361, 0, 362, 337, + 338, 343, 346, 347, 348, 353, 354, 358, 364, 249, + 210, 390, 399, 578, 312, 216, 217, 218, 524, 525, + 526, 527, 616, 617, 621, 205, 462, 463, 464, 465, + 292, 611, 309, 468, 467, 331, 332, 379, 449, 540, + 542, 553, 557, 559, 561, 567, 570, 541, 543, 554, + 558, 560, 562, 568, 571, 530, 532, 534, 536, 549, + 548, 545, 573, 574, 551, 556, 535, 547, 552, 565, + 572, 569, 529, 533, 537, 546, 564, 563, 544, 555, + 566, 550, 538, 531, 539, 0, 196, 221, 368, 0, + 454, 288, 647, 615, 484, 610, 206, 223, 0, 262, + 0, 0, 0, 0, 0, 0, 2418, 0, 0, 2417, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 198, 200, 209, 222, 232, 236, 243, 261, 276, + 278, 285, 298, 310, 318, 319, 322, 328, 380, 386, + 387, 388, 389, 409, 410, 411, 414, 417, 418, 421, + 423, 424, 427, 431, 435, 436, 437, 439, 441, 443, + 455, 460, 474, 475, 476, 477, 478, 481, 482, 488, + 489, 490, 491, 492, 500, 501, 516, 586, 588, 603, + 622, 629, 480, 301, 302, 444, 445, 314, 315, 643, + 644, 300, 598, 630, 596, 642, 624, 438, 378, 0, + 0, 381, 281, 305, 320, 0, 614, 502, 227, 466, + 290, 251, 0, 0, 211, 246, 230, 259, 274, 277, + 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, + 485, 519, 520, 521, 523, 395, 266, 433, 396, 0, + 376, 576, 577, 316, 0, 0, 0, 528, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, + 0, 0, 2365, 0, 0, 0, 0, 270, 0, 0, + 0, 0, 366, 267, 0, 0, 204, 505, 0, 430, + 0, 203, 0, 487, 252, 377, 374, 583, 282, 273, + 269, 250, 317, 385, 428, 518, 422, 0, 370, 0, + 0, 497, 401, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 323, 248, 325, 202, 413, 498, 286, 0, 0, + 0, 0, 1954, 507, 194, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 238, 0, 0, 245, 0, 0, + 0, 351, 360, 359, 339, 340, 342, 344, 350, 357, + 363, 336, 345, 0, 0, 607, 0, 0, 0, 265, + 321, 272, 264, 580, 0, 0, 0, 0, 0, 0, + 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 275, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 297, + 0, 402, 257, 0, 453, 0, 0, 0, 626, 0, + 0, 0, 0, 0, 0, 0, 365, 0, 330, 197, + 225, 0, 0, 412, 461, 473, 0, 0, 0, 253, + 0, 471, 426, 602, 233, 284, 458, 432, 469, 440, + 287, 0, 2363, 470, 372, 585, 450, 599, 627, 628, + 263, 406, 612, 522, 620, 645, 226, 260, 420, 506, + 605, 494, 397, 581, 582, 329, 493, 295, 201, 369, + 633, 224, 479, 371, 242, 231, 587, 609, 299, 289, + 456, 640, 213, 517, 597, 239, 483, 0, 0, 648, + 247, 504, 215, 594, 503, 393, 326, 327, 214, 0, + 457, 268, 293, 0, 0, 258, 415, 589, 590, 256, + 649, 228, 619, 220, 0, 618, 408, 584, 595, 394, + 383, 219, 593, 392, 382, 334, 355, 356, 280, 307, + 447, 375, 448, 306, 308, 404, 403, 405, 207, 606, + 623, 0, 208, 0, 499, 608, 650, 452, 212, 234, + 235, 237, 0, 279, 283, 291, 294, 303, 304, 313, + 367, 419, 446, 442, 451, 0, 579, 600, 613, 625, + 631, 632, 634, 635, 636, 637, 638, 641, 639, 407, + 311, 495, 333, 373, 0, 0, 425, 472, 240, 604, + 496, 199, 0, 0, 0, 0, 254, 255, 0, 575, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 651, + 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, + 662, 663, 664, 665, 666, 667, 668, 646, 508, 514, + 509, 510, 511, 512, 513, 0, 515, 0, 0, 0, + 0, 0, 398, 0, 591, 592, 669, 384, 486, 601, + 335, 349, 352, 341, 361, 0, 362, 337, 338, 343, + 346, 347, 348, 353, 354, 358, 364, 249, 210, 390, + 399, 578, 312, 216, 217, 218, 524, 525, 526, 527, + 616, 617, 621, 205, 462, 463, 464, 465, 292, 611, + 309, 468, 467, 331, 332, 379, 449, 540, 542, 553, + 557, 559, 561, 567, 570, 541, 543, 554, 558, 560, + 562, 568, 571, 530, 532, 534, 536, 549, 548, 545, + 573, 574, 551, 556, 535, 547, 552, 565, 572, 569, + 529, 533, 537, 546, 564, 563, 544, 555, 566, 550, + 538, 531, 539, 0, 196, 221, 368, 0, 454, 288, + 647, 615, 484, 610, 206, 223, 0, 262, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, + 200, 209, 222, 232, 236, 243, 261, 276, 278, 285, + 298, 310, 318, 319, 322, 328, 380, 386, 387, 388, + 389, 409, 410, 411, 414, 417, 418, 421, 423, 424, + 427, 431, 435, 436, 437, 439, 441, 443, 455, 460, + 474, 475, 476, 477, 478, 481, 482, 488, 489, 490, + 491, 492, 500, 501, 516, 586, 588, 603, 622, 629, + 480, 301, 302, 444, 445, 314, 315, 643, 644, 300, + 598, 630, 596, 642, 624, 438, 378, 0, 0, 381, + 281, 305, 320, 0, 614, 502, 227, 466, 290, 251, + 0, 0, 211, 246, 230, 259, 274, 277, 324, 391, + 400, 429, 434, 296, 271, 244, 459, 241, 485, 519, + 520, 521, 523, 395, 266, 433, 396, 0, 376, 576, + 577, 316, 0, 0, 0, 528, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, + 0, 0, 0, 0, 0, 270, 0, 0, 0, 0, + 366, 267, 0, 0, 204, 505, 0, 430, 0, 203, + 0, 487, 252, 377, 374, 583, 282, 273, 269, 250, + 317, 385, 428, 518, 422, 0, 370, 0, 0, 497, + 401, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 323, + 248, 325, 202, 413, 498, 286, 0, 0, 0, 0, + 0, 507, 720, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 238, 0, 0, 245, 0, 0, 0, 351, + 360, 359, 339, 340, 342, 344, 350, 357, 363, 336, + 345, 0, 0, 607, 0, 0, 0, 265, 321, 272, + 264, 580, 0, 0, 0, 0, 0, 0, 0, 0, + 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 275, 0, 0, 0, 0, + 0, 0, 0, 0, 1088, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 297, 0, 402, + 257, 0, 453, 0, 0, 0, 626, 0, 0, 0, + 0, 0, 0, 0, 365, 1094, 330, 197, 225, 1092, + 0, 412, 461, 473, 0, 0, 0, 253, 0, 471, + 426, 602, 233, 284, 458, 432, 469, 440, 287, 0, + 0, 470, 372, 585, 450, 599, 627, 628, 263, 406, + 612, 522, 620, 645, 226, 260, 420, 506, 605, 494, + 397, 581, 582, 329, 493, 295, 201, 369, 633, 224, + 479, 371, 242, 231, 587, 609, 299, 289, 456, 640, + 213, 517, 597, 239, 483, 0, 0, 648, 247, 504, + 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, + 293, 0, 0, 258, 415, 589, 590, 256, 649, 228, + 619, 220, 0, 618, 408, 584, 595, 394, 383, 219, + 593, 392, 382, 334, 355, 356, 280, 307, 447, 375, + 448, 306, 308, 404, 403, 405, 207, 606, 623, 0, + 208, 0, 499, 608, 650, 452, 212, 234, 235, 237, + 0, 279, 283, 291, 294, 303, 304, 313, 367, 419, + 446, 442, 451, 0, 579, 600, 613, 625, 631, 632, + 634, 635, 636, 637, 638, 641, 639, 407, 311, 495, + 333, 373, 0, 0, 425, 472, 240, 604, 496, 199, + 0, 0, 0, 0, 254, 255, 0, 575, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 651, 652, 653, + 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, + 664, 665, 666, 667, 668, 646, 508, 514, 509, 510, + 511, 512, 513, 0, 515, 0, 0, 0, 0, 0, + 398, 0, 591, 592, 669, 384, 486, 601, 335, 349, + 352, 341, 361, 0, 362, 337, 338, 343, 346, 347, + 348, 353, 354, 358, 364, 249, 210, 390, 399, 578, + 312, 216, 217, 218, 524, 525, 526, 527, 616, 617, + 621, 205, 462, 463, 464, 465, 292, 611, 309, 468, + 467, 331, 332, 379, 449, 540, 542, 553, 557, 559, + 561, 567, 570, 541, 543, 554, 558, 560, 562, 568, + 571, 530, 532, 534, 536, 549, 548, 545, 573, 574, + 551, 556, 535, 547, 552, 565, 572, 569, 529, 533, + 537, 546, 564, 563, 544, 555, 566, 550, 538, 531, + 539, 0, 196, 221, 368, 0, 454, 288, 647, 615, + 484, 610, 206, 223, 0, 262, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 198, 200, 209, + 222, 232, 236, 243, 261, 276, 278, 285, 298, 310, + 318, 319, 322, 328, 380, 386, 387, 388, 389, 409, + 410, 411, 414, 417, 418, 421, 423, 424, 427, 431, + 435, 436, 437, 439, 441, 443, 455, 460, 474, 475, + 476, 477, 478, 481, 482, 488, 489, 490, 491, 492, + 500, 501, 516, 586, 588, 603, 622, 629, 480, 301, + 302, 444, 445, 314, 315, 643, 644, 300, 598, 630, + 596, 642, 624, 438, 378, 0, 0, 381, 281, 305, + 320, 0, 614, 502, 227, 466, 290, 251, 0, 0, + 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, + 434, 296, 271, 244, 459, 241, 485, 519, 520, 521, + 523, 395, 266, 433, 396, 0, 376, 576, 577, 316, + 0, 0, 0, 528, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 416, 0, 0, 2365, 0, + 0, 0, 0, 270, 0, 0, 0, 0, 366, 267, + 0, 0, 204, 505, 0, 430, 0, 203, 0, 487, + 252, 377, 374, 583, 282, 273, 269, 250, 317, 385, + 428, 518, 422, 0, 370, 0, 0, 497, 401, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 323, 248, 325, + 202, 413, 498, 286, 0, 0, 0, 0, 1954, 507, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, + 238, 0, 0, 245, 0, 0, 0, 351, 360, 359, + 339, 340, 342, 344, 350, 357, 363, 336, 345, 0, + 0, 607, 0, 0, 0, 265, 321, 272, 264, 580, + 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 297, 0, 402, 257, 0, + 453, 0, 0, 0, 626, 0, 0, 0, 0, 0, + 0, 0, 365, 0, 330, 197, 225, 0, 0, 412, + 461, 473, 0, 0, 0, 253, 0, 471, 426, 602, + 233, 284, 458, 432, 469, 440, 287, 0, 0, 470, + 372, 585, 450, 599, 627, 628, 263, 406, 612, 522, + 620, 645, 226, 260, 420, 506, 605, 494, 397, 581, + 582, 329, 493, 295, 201, 369, 633, 224, 479, 371, + 242, 231, 587, 609, 299, 289, 456, 640, 213, 517, + 597, 239, 483, 0, 0, 648, 247, 504, 215, 594, + 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, + 0, 258, 415, 589, 590, 256, 649, 228, 619, 220, + 0, 618, 408, 584, 595, 394, 383, 219, 593, 392, + 382, 334, 355, 356, 280, 307, 447, 375, 448, 306, + 308, 404, 403, 405, 207, 606, 623, 0, 208, 0, + 499, 608, 650, 452, 212, 234, 235, 237, 0, 279, + 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, + 451, 0, 579, 600, 613, 625, 631, 632, 634, 635, + 636, 637, 638, 641, 639, 407, 311, 495, 333, 373, + 0, 0, 425, 472, 240, 604, 496, 199, 0, 0, + 0, 0, 254, 255, 0, 575, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 651, 652, 653, 654, 655, + 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, + 666, 667, 668, 646, 508, 514, 509, 510, 511, 512, + 513, 0, 515, 0, 0, 0, 0, 0, 398, 0, + 591, 592, 669, 384, 486, 601, 335, 349, 352, 341, + 361, 0, 362, 337, 338, 343, 346, 347, 348, 353, + 354, 358, 364, 249, 210, 390, 399, 578, 312, 216, + 217, 218, 524, 525, 526, 527, 616, 617, 621, 205, + 462, 463, 464, 465, 292, 611, 309, 468, 467, 331, + 332, 379, 449, 540, 542, 553, 557, 559, 561, 567, + 570, 541, 543, 554, 558, 560, 562, 568, 571, 530, + 532, 534, 536, 549, 548, 545, 573, 574, 551, 556, + 535, 547, 552, 565, 572, 569, 529, 533, 537, 546, + 564, 563, 544, 555, 566, 550, 538, 531, 539, 0, + 196, 221, 368, 0, 454, 288, 647, 615, 484, 610, + 206, 223, 0, 262, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 198, 200, 209, 222, 232, + 236, 243, 261, 276, 278, 285, 298, 310, 318, 319, + 322, 328, 380, 386, 387, 388, 389, 409, 410, 411, + 414, 417, 418, 421, 423, 424, 427, 431, 435, 436, + 437, 439, 441, 443, 455, 460, 474, 475, 476, 477, + 478, 481, 482, 488, 489, 490, 491, 492, 500, 501, + 516, 586, 588, 603, 622, 629, 480, 301, 302, 444, + 445, 314, 315, 643, 644, 300, 598, 630, 596, 642, + 624, 438, 378, 0, 0, 381, 281, 305, 320, 0, + 614, 502, 227, 466, 290, 251, 0, 0, 211, 246, + 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, + 271, 244, 459, 241, 485, 519, 520, 521, 523, 395, + 266, 433, 396, 0, 376, 576, 577, 316, 0, 0, + 0, 528, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 270, 0, 0, 0, 0, 366, 267, 0, 0, + 204, 505, 0, 430, 0, 203, 0, 487, 252, 377, + 374, 583, 282, 273, 269, 250, 317, 385, 428, 518, + 422, 0, 370, 0, 0, 497, 401, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 323, 248, 325, 202, 413, + 498, 286, 0, 0, 0, 1747, 0, 507, 720, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 238, 0, + 0, 245, 0, 0, 0, 351, 360, 359, 339, 340, + 342, 344, 350, 357, 363, 336, 345, 0, 0, 607, + 0, 0, 0, 265, 321, 272, 264, 580, 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6807,69 +4983,365 @@ 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, 1440, 0, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 1439, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, + 0, 0, 0, 297, 0, 402, 257, 0, 453, 0, + 0, 0, 626, 0, 0, 0, 3719, 0, 0, 0, + 365, 0, 330, 197, 225, 0, 0, 412, 461, 473, + 0, 0, 0, 253, 0, 471, 426, 602, 233, 284, + 458, 432, 469, 440, 287, 0, 0, 470, 372, 585, + 450, 599, 627, 628, 263, 406, 612, 522, 620, 645, + 226, 260, 420, 506, 605, 494, 397, 581, 582, 329, + 493, 295, 201, 369, 633, 224, 479, 371, 242, 231, + 587, 609, 299, 289, 456, 640, 213, 517, 597, 239, + 483, 0, 0, 648, 247, 504, 215, 594, 503, 393, + 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, + 415, 589, 590, 256, 649, 228, 619, 220, 0, 618, + 408, 584, 595, 394, 383, 219, 593, 392, 382, 334, + 355, 356, 280, 307, 447, 375, 448, 306, 308, 404, + 403, 405, 207, 606, 623, 0, 208, 0, 499, 608, + 650, 452, 212, 234, 235, 237, 0, 279, 283, 291, + 294, 303, 304, 313, 367, 419, 446, 442, 451, 0, + 579, 600, 613, 625, 631, 632, 634, 635, 636, 637, + 638, 641, 639, 407, 311, 495, 333, 373, 0, 0, + 425, 472, 240, 604, 496, 199, 0, 0, 0, 0, + 254, 255, 0, 575, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 651, 652, 653, 654, 655, 656, 657, + 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, + 668, 646, 508, 514, 509, 510, 511, 512, 513, 0, + 515, 0, 0, 0, 0, 0, 398, 0, 591, 592, + 669, 384, 486, 601, 335, 349, 352, 341, 361, 0, + 362, 337, 338, 343, 346, 347, 348, 353, 354, 358, + 364, 249, 210, 390, 399, 578, 312, 216, 217, 218, + 524, 525, 526, 527, 616, 617, 621, 205, 462, 463, + 464, 465, 292, 611, 309, 468, 467, 331, 332, 379, + 449, 540, 542, 553, 557, 559, 561, 567, 570, 541, + 543, 554, 558, 560, 562, 568, 571, 530, 532, 534, + 536, 549, 548, 545, 573, 574, 551, 556, 535, 547, + 552, 565, 572, 569, 529, 533, 537, 546, 564, 563, + 544, 555, 566, 550, 538, 531, 539, 0, 196, 221, + 368, 0, 454, 288, 647, 615, 484, 610, 206, 223, + 0, 262, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 198, 200, 209, 222, 232, 236, 243, + 261, 276, 278, 285, 298, 310, 318, 319, 322, 328, + 380, 386, 387, 388, 389, 409, 410, 411, 414, 417, + 418, 421, 423, 424, 427, 431, 435, 436, 437, 439, + 441, 443, 455, 460, 474, 475, 476, 477, 478, 481, + 482, 488, 489, 490, 491, 492, 500, 501, 516, 586, + 588, 603, 622, 629, 480, 301, 302, 444, 445, 314, + 315, 643, 644, 300, 598, 630, 596, 642, 624, 438, + 378, 0, 0, 381, 281, 305, 320, 0, 614, 502, + 227, 466, 290, 251, 0, 0, 211, 246, 230, 259, + 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, + 459, 241, 485, 519, 520, 521, 523, 395, 266, 433, + 396, 0, 376, 576, 577, 316, 0, 0, 0, 528, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 416, 0, 0, 0, 0, 0, 0, 0, 270, + 0, 0, 0, 0, 366, 267, 0, 0, 204, 505, + 0, 430, 0, 203, 0, 487, 252, 377, 374, 583, + 282, 273, 269, 250, 317, 385, 428, 518, 422, 0, + 370, 0, 0, 497, 401, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 323, 248, 325, 202, 413, 498, 286, + 0, 0, 0, 0, 2124, 507, 720, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 238, 0, 0, 245, + 0, 0, 0, 351, 360, 359, 339, 340, 342, 344, + 350, 357, 363, 336, 345, 0, 0, 607, 0, 0, + 0, 265, 321, 272, 264, 580, 0, 0, 0, 0, + 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2125, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 297, 0, 402, 257, 0, 453, 0, 0, 0, + 626, 0, 0, 0, 0, 0, 0, 0, 365, 0, + 330, 197, 225, 0, 0, 412, 461, 473, 0, 0, + 0, 253, 0, 471, 426, 602, 233, 284, 458, 432, + 469, 440, 287, 0, 0, 470, 372, 585, 450, 599, + 627, 628, 263, 406, 612, 522, 620, 645, 226, 260, + 420, 506, 605, 494, 397, 581, 582, 329, 493, 295, + 201, 369, 633, 224, 479, 371, 242, 231, 587, 609, + 299, 289, 456, 640, 213, 517, 597, 239, 483, 0, + 0, 648, 247, 504, 215, 594, 503, 393, 326, 327, + 214, 0, 457, 268, 293, 0, 0, 258, 415, 589, + 590, 256, 649, 228, 619, 220, 0, 618, 408, 584, + 595, 394, 383, 219, 593, 392, 382, 334, 355, 356, + 280, 307, 447, 375, 448, 306, 308, 404, 403, 405, + 207, 606, 623, 0, 208, 0, 499, 608, 650, 452, + 212, 234, 235, 237, 0, 279, 283, 291, 294, 303, + 304, 313, 367, 419, 446, 442, 451, 0, 579, 600, + 613, 625, 631, 632, 634, 635, 636, 637, 638, 641, + 639, 407, 311, 495, 333, 373, 0, 0, 425, 472, + 240, 604, 496, 199, 0, 0, 0, 0, 254, 255, + 0, 575, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 651, 652, 653, 654, 655, 656, 657, 658, 659, + 660, 661, 662, 663, 664, 665, 666, 667, 668, 646, + 508, 514, 509, 510, 511, 512, 513, 0, 515, 0, + 0, 0, 0, 0, 398, 0, 591, 592, 669, 384, + 486, 601, 335, 349, 352, 341, 361, 0, 362, 337, + 338, 343, 346, 347, 348, 353, 354, 358, 364, 249, + 210, 390, 399, 578, 312, 216, 217, 218, 524, 525, + 526, 527, 616, 617, 621, 205, 462, 463, 464, 465, + 292, 611, 309, 468, 467, 331, 332, 379, 449, 540, + 542, 553, 557, 559, 561, 567, 570, 541, 543, 554, + 558, 560, 562, 568, 571, 530, 532, 534, 536, 549, + 548, 545, 573, 574, 551, 556, 535, 547, 552, 565, + 572, 569, 529, 533, 537, 546, 564, 563, 544, 555, + 566, 550, 538, 531, 539, 0, 196, 221, 368, 0, + 454, 288, 647, 615, 484, 610, 206, 223, 0, 262, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 198, 200, 209, 222, 232, 236, 243, 261, 276, + 278, 285, 298, 310, 318, 319, 322, 328, 380, 386, + 387, 388, 389, 409, 410, 411, 414, 417, 418, 421, + 423, 424, 427, 431, 435, 436, 437, 439, 441, 443, + 455, 460, 474, 475, 476, 477, 478, 481, 482, 488, + 489, 490, 491, 492, 500, 501, 516, 586, 588, 603, + 622, 629, 480, 301, 302, 444, 445, 314, 315, 643, + 644, 300, 598, 630, 596, 642, 624, 438, 378, 0, + 0, 381, 281, 305, 320, 0, 614, 502, 227, 466, + 290, 251, 0, 0, 211, 246, 230, 259, 274, 277, + 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, + 485, 519, 520, 521, 523, 395, 266, 433, 396, 0, + 376, 576, 577, 316, 0, 0, 0, 528, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, + 0, 0, 366, 267, 0, 0, 204, 505, 0, 430, + 0, 203, 0, 487, 252, 377, 374, 583, 282, 273, + 269, 250, 317, 385, 428, 518, 422, 0, 370, 0, + 0, 497, 401, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 323, 248, 325, 202, 413, 498, 286, 0, 0, + 0, 0, 2870, 507, 720, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 238, 0, 0, 245, 0, 0, + 0, 351, 360, 359, 339, 340, 342, 344, 350, 357, + 363, 336, 345, 0, 0, 607, 0, 0, 0, 265, + 321, 272, 264, 580, 0, 0, 0, 0, 0, 0, + 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 275, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2871, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 297, + 0, 402, 257, 0, 453, 0, 0, 0, 626, 0, + 0, 0, 0, 0, 0, 0, 365, 0, 330, 197, + 225, 0, 0, 412, 461, 473, 0, 0, 0, 253, + 0, 471, 426, 602, 233, 284, 458, 432, 469, 440, + 287, 0, 0, 470, 372, 585, 450, 599, 627, 628, + 263, 406, 612, 522, 620, 645, 226, 260, 420, 506, + 605, 494, 397, 581, 582, 329, 493, 295, 201, 369, + 633, 224, 479, 371, 242, 231, 587, 609, 299, 289, + 456, 640, 213, 517, 597, 239, 483, 0, 0, 648, + 247, 504, 215, 594, 503, 393, 326, 327, 214, 0, + 457, 268, 293, 0, 0, 258, 415, 589, 590, 256, + 649, 228, 619, 220, 0, 618, 408, 584, 595, 394, + 383, 219, 593, 392, 382, 334, 355, 356, 280, 307, + 447, 375, 448, 306, 308, 404, 403, 405, 207, 606, + 623, 0, 208, 0, 499, 608, 650, 452, 212, 234, + 235, 237, 0, 279, 283, 291, 294, 303, 304, 313, + 367, 419, 446, 442, 451, 0, 579, 600, 613, 625, + 631, 632, 634, 635, 636, 637, 638, 641, 639, 407, + 311, 495, 333, 373, 0, 0, 425, 472, 240, 604, + 496, 199, 0, 0, 0, 0, 254, 255, 0, 575, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 651, + 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, + 662, 663, 664, 665, 666, 667, 668, 646, 508, 514, + 509, 510, 511, 512, 513, 0, 515, 0, 0, 0, + 0, 0, 398, 0, 591, 592, 669, 384, 486, 601, + 335, 349, 352, 341, 361, 0, 362, 337, 338, 343, + 346, 347, 348, 353, 354, 358, 364, 249, 210, 390, + 399, 578, 312, 216, 217, 218, 524, 525, 526, 527, + 616, 617, 621, 205, 462, 463, 464, 465, 292, 611, + 309, 468, 467, 331, 332, 379, 449, 540, 542, 553, + 557, 559, 561, 567, 570, 541, 543, 554, 558, 560, + 562, 568, 571, 530, 532, 534, 536, 549, 548, 545, + 573, 574, 551, 556, 535, 547, 552, 565, 572, 569, + 529, 533, 537, 546, 564, 563, 544, 555, 566, 550, + 538, 531, 539, 0, 196, 221, 368, 0, 454, 288, + 647, 615, 484, 610, 206, 223, 0, 262, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, + 200, 209, 222, 232, 236, 243, 261, 276, 278, 285, + 298, 310, 318, 319, 322, 328, 380, 386, 387, 388, + 389, 409, 410, 411, 414, 417, 418, 421, 423, 424, + 427, 431, 435, 436, 437, 439, 441, 443, 455, 460, + 474, 475, 476, 477, 478, 481, 482, 488, 489, 490, + 491, 492, 500, 501, 516, 586, 588, 603, 622, 629, + 480, 301, 302, 444, 445, 314, 315, 643, 644, 300, + 598, 630, 596, 642, 624, 438, 378, 0, 0, 381, + 281, 305, 320, 0, 614, 502, 227, 466, 290, 251, + 0, 0, 211, 246, 230, 259, 274, 277, 324, 391, + 400, 429, 434, 296, 271, 244, 459, 241, 485, 519, + 520, 521, 523, 395, 266, 433, 396, 0, 376, 576, + 577, 316, 0, 0, 0, 528, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, + 0, 0, 0, 0, 0, 270, 0, 0, 0, 0, + 366, 267, 0, 0, 204, 505, 0, 430, 0, 203, + 0, 487, 252, 377, 374, 583, 282, 273, 269, 250, + 317, 385, 428, 518, 422, 0, 370, 0, 0, 497, + 401, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 323, + 248, 325, 202, 413, 498, 286, 0, 0, 0, 0, + 0, 507, 720, 0, 0, 0, 0, 2855, 0, 0, + 0, 0, 238, 0, 0, 245, 2856, 0, 0, 351, + 360, 359, 339, 340, 342, 344, 350, 357, 363, 336, + 345, 0, 0, 607, 0, 0, 0, 265, 321, 272, + 264, 580, 0, 0, 0, 0, 0, 0, 0, 0, + 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 275, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 297, 0, 402, + 257, 0, 453, 0, 0, 0, 626, 0, 0, 0, + 0, 0, 0, 0, 365, 0, 330, 197, 225, 0, + 0, 412, 461, 473, 0, 0, 0, 253, 0, 471, + 426, 602, 233, 284, 458, 432, 469, 440, 287, 0, + 0, 470, 372, 585, 450, 599, 627, 628, 263, 406, + 612, 522, 620, 645, 226, 260, 420, 506, 605, 494, + 397, 581, 582, 329, 493, 295, 201, 369, 633, 224, + 479, 371, 242, 231, 587, 609, 299, 289, 456, 640, + 213, 517, 597, 239, 483, 0, 0, 648, 247, 504, + 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, + 293, 0, 0, 258, 415, 589, 590, 256, 649, 228, + 619, 220, 0, 618, 408, 584, 595, 394, 383, 219, + 593, 392, 382, 334, 355, 356, 280, 307, 447, 375, + 448, 306, 308, 404, 403, 405, 207, 606, 623, 0, + 208, 0, 499, 608, 650, 452, 212, 234, 235, 237, + 0, 279, 283, 291, 294, 303, 304, 313, 367, 419, + 446, 442, 451, 0, 579, 600, 613, 625, 631, 632, + 634, 635, 636, 637, 638, 641, 639, 407, 311, 495, + 333, 373, 0, 0, 425, 472, 240, 604, 496, 199, + 0, 0, 0, 0, 254, 255, 0, 575, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 651, 652, 653, + 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, + 664, 665, 666, 667, 668, 646, 508, 514, 509, 510, + 511, 512, 513, 0, 515, 0, 0, 0, 0, 0, + 398, 0, 591, 592, 669, 384, 486, 601, 335, 349, + 352, 341, 361, 0, 362, 337, 338, 343, 346, 347, + 348, 353, 354, 358, 364, 249, 210, 390, 399, 578, + 312, 216, 217, 218, 524, 525, 526, 527, 616, 617, + 621, 205, 462, 463, 464, 465, 292, 611, 309, 468, + 467, 331, 332, 379, 449, 540, 542, 553, 557, 559, + 561, 567, 570, 541, 543, 554, 558, 560, 562, 568, + 571, 530, 532, 534, 536, 549, 548, 545, 573, 574, + 551, 556, 535, 547, 552, 565, 572, 569, 529, 533, + 537, 546, 564, 563, 544, 555, 566, 550, 538, 531, + 539, 0, 196, 221, 368, 0, 454, 288, 647, 615, + 484, 610, 206, 223, 0, 262, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 198, 200, 209, + 222, 232, 236, 243, 261, 276, 278, 285, 298, 310, + 318, 319, 322, 328, 380, 386, 387, 388, 389, 409, + 410, 411, 414, 417, 418, 421, 423, 424, 427, 431, + 435, 436, 437, 439, 441, 443, 455, 460, 474, 475, + 476, 477, 478, 481, 482, 488, 489, 490, 491, 492, + 500, 501, 516, 586, 588, 603, 622, 629, 480, 301, + 302, 444, 445, 314, 315, 643, 644, 300, 598, 630, + 596, 642, 624, 438, 378, 0, 0, 381, 281, 305, + 320, 0, 614, 502, 227, 466, 290, 251, 0, 0, + 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, + 434, 296, 271, 244, 459, 241, 485, 519, 520, 521, + 523, 395, 266, 433, 396, 0, 376, 576, 577, 316, + 0, 0, 0, 528, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, + 0, 0, 0, 270, 1793, 0, 0, 0, 366, 267, + 0, 0, 204, 505, 0, 430, 0, 203, 0, 487, + 252, 377, 374, 583, 282, 273, 269, 250, 317, 385, + 428, 518, 422, 0, 370, 0, 0, 497, 401, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 323, 248, 325, + 202, 413, 498, 286, 0, 0, 0, 0, 1792, 507, + 720, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 245, 0, 0, 0, 351, 360, 359, + 339, 340, 342, 344, 350, 357, 363, 336, 345, 0, + 0, 607, 0, 0, 0, 265, 321, 272, 264, 580, + 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 297, 0, 402, 257, 0, + 453, 0, 0, 0, 626, 0, 0, 0, 0, 0, + 0, 0, 365, 0, 330, 197, 225, 0, 0, 412, + 461, 473, 0, 0, 0, 253, 0, 471, 426, 602, + 233, 284, 458, 432, 469, 440, 287, 0, 0, 470, + 372, 585, 450, 599, 627, 628, 263, 406, 612, 522, + 620, 645, 226, 260, 420, 506, 605, 494, 397, 581, + 582, 329, 493, 295, 201, 369, 633, 224, 479, 371, + 242, 231, 587, 609, 299, 289, 456, 640, 213, 517, + 597, 239, 483, 0, 0, 648, 247, 504, 215, 594, + 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, + 0, 258, 415, 589, 590, 256, 649, 228, 619, 220, + 0, 618, 408, 584, 595, 394, 383, 219, 593, 392, + 382, 334, 355, 356, 280, 307, 447, 375, 448, 306, + 308, 404, 403, 405, 207, 606, 623, 0, 208, 0, + 499, 608, 650, 452, 212, 234, 235, 237, 0, 279, + 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, + 451, 0, 579, 600, 613, 625, 631, 632, 634, 635, + 636, 637, 638, 641, 639, 407, 311, 495, 333, 373, + 0, 0, 425, 472, 240, 604, 496, 199, 0, 0, + 0, 0, 254, 255, 0, 575, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 651, 652, 653, 654, 655, + 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, + 666, 667, 668, 646, 508, 514, 509, 510, 511, 512, + 513, 0, 515, 0, 0, 0, 0, 0, 398, 0, + 591, 592, 669, 384, 486, 601, 335, 349, 352, 341, + 361, 0, 362, 337, 338, 343, 346, 347, 348, 353, + 354, 358, 364, 249, 210, 390, 399, 578, 312, 216, + 217, 218, 524, 525, 526, 527, 616, 617, 621, 205, + 462, 463, 464, 465, 292, 611, 309, 468, 467, 331, + 332, 379, 449, 540, 542, 553, 557, 559, 561, 567, + 570, 541, 543, 554, 558, 560, 562, 568, 571, 530, + 532, 534, 536, 549, 548, 545, 573, 574, 551, 556, + 535, 547, 552, 565, 572, 569, 529, 533, 537, 546, + 564, 563, 544, 555, 566, 550, 538, 531, 539, 0, + 196, 221, 368, 0, 454, 288, 647, 615, 484, 610, + 206, 223, 0, 262, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 198, 200, 209, 222, 232, + 236, 243, 261, 276, 278, 285, 298, 310, 318, 319, + 322, 328, 380, 386, 387, 388, 389, 409, 410, 411, + 414, 417, 418, 421, 423, 424, 427, 431, 435, 436, + 437, 439, 441, 443, 455, 460, 474, 475, 476, 477, + 478, 481, 482, 488, 489, 490, 491, 492, 500, 501, + 516, 586, 588, 603, 622, 629, 480, 301, 302, 444, + 445, 314, 315, 643, 644, 300, 598, 630, 596, 642, + 624, 438, 378, 0, 0, 381, 281, 305, 320, 0, + 614, 502, 227, 466, 290, 251, 0, 0, 211, 246, + 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, + 271, 244, 459, 241, 485, 519, 520, 521, 523, 395, + 266, 433, 396, 0, 376, 576, 577, 316, 0, 0, + 0, 528, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 270, 0, 0, 0, 0, 366, 267, 0, 0, + 204, 505, 0, 430, 0, 203, 0, 487, 252, 377, + 374, 583, 282, 273, 269, 250, 317, 385, 428, 518, + 422, 0, 370, 0, 0, 497, 401, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 323, 248, 325, 202, 413, + 498, 286, 0, 0, 0, 0, 0, 507, 722, 723, + 724, 0, 0, 0, 0, 0, 0, 0, 238, 0, + 0, 245, 0, 0, 0, 351, 360, 359, 339, 340, + 342, 344, 350, 357, 363, 336, 345, 0, 0, 607, + 0, 0, 0, 265, 321, 272, 264, 580, 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6880,69 +5352,365 @@ 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, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1038, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, + 0, 0, 0, 297, 0, 402, 257, 0, 453, 0, + 0, 0, 626, 0, 0, 0, 0, 0, 0, 0, + 365, 0, 330, 197, 225, 0, 0, 412, 461, 473, + 0, 0, 0, 253, 0, 471, 426, 602, 233, 284, + 458, 432, 469, 440, 287, 0, 0, 470, 372, 585, + 450, 599, 627, 628, 263, 406, 612, 522, 620, 645, + 226, 260, 420, 506, 605, 494, 397, 581, 582, 329, + 493, 295, 201, 369, 633, 224, 479, 371, 242, 231, + 587, 609, 299, 289, 456, 640, 213, 517, 597, 239, + 483, 0, 0, 648, 247, 504, 215, 594, 503, 393, + 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, + 415, 589, 590, 256, 649, 228, 619, 220, 0, 618, + 408, 584, 595, 394, 383, 219, 593, 392, 382, 334, + 355, 356, 280, 307, 447, 375, 448, 306, 308, 404, + 403, 405, 207, 606, 623, 0, 208, 0, 499, 608, + 650, 452, 212, 234, 235, 237, 0, 279, 283, 291, + 294, 303, 304, 313, 367, 419, 446, 442, 451, 0, + 579, 600, 613, 625, 631, 632, 634, 635, 636, 637, + 638, 641, 639, 407, 311, 495, 333, 373, 0, 0, + 425, 472, 240, 604, 496, 199, 0, 0, 0, 0, + 254, 255, 0, 575, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 651, 652, 653, 654, 655, 656, 657, + 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, + 668, 646, 508, 514, 509, 510, 511, 512, 513, 0, + 515, 0, 0, 0, 0, 0, 398, 0, 591, 592, + 669, 384, 486, 601, 335, 349, 352, 341, 361, 0, + 362, 337, 338, 343, 346, 347, 348, 353, 354, 358, + 364, 249, 210, 390, 399, 578, 312, 216, 217, 218, + 524, 525, 526, 527, 616, 617, 621, 205, 462, 463, + 464, 465, 292, 611, 309, 468, 467, 331, 332, 379, + 449, 540, 542, 553, 557, 559, 561, 567, 570, 541, + 543, 554, 558, 560, 562, 568, 571, 530, 532, 534, + 536, 549, 548, 545, 573, 574, 551, 556, 535, 547, + 552, 565, 572, 569, 529, 533, 537, 546, 564, 563, + 544, 555, 566, 550, 538, 531, 539, 0, 196, 221, + 368, 0, 454, 288, 647, 615, 484, 610, 206, 223, + 0, 262, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 198, 200, 209, 222, 232, 236, 243, + 261, 276, 278, 285, 298, 310, 318, 319, 322, 328, + 380, 386, 387, 388, 389, 409, 410, 411, 414, 417, + 418, 421, 423, 424, 427, 431, 435, 436, 437, 439, + 441, 443, 455, 460, 474, 475, 476, 477, 478, 481, + 482, 488, 489, 490, 491, 492, 500, 501, 516, 586, + 588, 603, 622, 629, 480, 301, 302, 444, 445, 314, + 315, 643, 644, 300, 598, 630, 596, 642, 624, 438, + 378, 0, 0, 381, 281, 305, 320, 0, 614, 502, + 227, 466, 290, 251, 0, 0, 211, 246, 230, 259, + 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, + 459, 241, 485, 519, 520, 521, 523, 395, 266, 433, + 396, 0, 376, 576, 577, 316, 0, 0, 0, 528, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 416, 0, 0, 0, 0, 0, 0, 0, 270, + 0, 0, 0, 0, 366, 267, 0, 0, 204, 505, + 0, 430, 0, 203, 0, 487, 252, 377, 374, 583, + 282, 273, 269, 250, 317, 385, 428, 518, 422, 0, + 370, 0, 0, 497, 401, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 323, 248, 325, 202, 413, 498, 286, + 0, 0, 0, 0, 0, 507, 720, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 238, 0, 0, 245, + 0, 0, 0, 351, 360, 359, 339, 340, 342, 344, + 350, 357, 363, 336, 345, 0, 0, 607, 0, 0, + 0, 265, 321, 272, 264, 580, 0, 0, 0, 0, + 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 297, 0, 402, 257, 0, 453, 0, 0, 0, + 626, 0, 0, 0, 4063, 0, 0, 0, 365, 0, + 330, 197, 225, 0, 0, 412, 461, 473, 0, 0, + 0, 253, 0, 471, 426, 602, 233, 284, 458, 432, + 469, 440, 287, 0, 0, 470, 372, 585, 450, 599, + 627, 628, 263, 406, 612, 522, 620, 645, 226, 260, + 420, 506, 605, 494, 397, 581, 582, 329, 493, 295, + 201, 369, 633, 224, 479, 371, 242, 231, 587, 609, + 299, 289, 456, 640, 213, 517, 597, 239, 483, 0, + 0, 648, 247, 504, 215, 594, 503, 393, 326, 327, + 214, 0, 457, 268, 293, 0, 0, 258, 415, 589, + 590, 256, 649, 228, 619, 220, 0, 618, 408, 584, + 595, 394, 383, 219, 593, 392, 382, 334, 355, 356, + 280, 307, 447, 375, 448, 306, 308, 404, 403, 405, + 207, 606, 623, 0, 208, 0, 499, 608, 650, 452, + 212, 234, 235, 237, 0, 279, 283, 291, 294, 303, + 304, 313, 367, 419, 446, 442, 451, 0, 579, 600, + 613, 625, 631, 632, 634, 635, 636, 637, 638, 641, + 639, 407, 311, 495, 333, 373, 0, 0, 425, 472, + 240, 604, 496, 199, 0, 0, 0, 0, 254, 255, + 0, 575, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 651, 652, 653, 654, 655, 656, 657, 658, 659, + 660, 661, 662, 663, 664, 665, 666, 667, 668, 646, + 508, 514, 509, 510, 511, 512, 513, 0, 515, 0, + 0, 0, 0, 0, 398, 0, 591, 592, 669, 384, + 486, 601, 335, 349, 352, 341, 361, 0, 362, 337, + 338, 343, 346, 347, 348, 353, 354, 358, 364, 249, + 210, 390, 399, 578, 312, 216, 217, 218, 524, 525, + 526, 527, 616, 617, 621, 205, 462, 463, 464, 465, + 292, 611, 309, 468, 467, 331, 332, 379, 449, 540, + 542, 553, 557, 559, 561, 567, 570, 541, 543, 554, + 558, 560, 562, 568, 571, 530, 532, 534, 536, 549, + 548, 545, 573, 574, 551, 556, 535, 547, 552, 565, + 572, 569, 529, 533, 537, 546, 564, 563, 544, 555, + 566, 550, 538, 531, 539, 0, 196, 221, 368, 0, + 454, 288, 647, 615, 484, 610, 206, 223, 0, 262, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 198, 200, 209, 222, 232, 236, 243, 261, 276, + 278, 285, 298, 310, 318, 319, 322, 328, 380, 386, + 387, 388, 389, 409, 410, 411, 414, 417, 418, 421, + 423, 424, 427, 431, 435, 436, 437, 439, 441, 443, + 455, 460, 474, 475, 476, 477, 478, 481, 482, 488, + 489, 490, 491, 492, 500, 501, 516, 586, 588, 603, + 622, 629, 480, 301, 302, 444, 445, 314, 315, 643, + 644, 300, 598, 630, 596, 642, 624, 438, 378, 0, + 0, 381, 281, 305, 320, 0, 614, 502, 227, 466, + 290, 251, 0, 0, 211, 246, 230, 259, 274, 277, + 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, + 485, 519, 520, 521, 523, 395, 266, 433, 396, 0, + 376, 576, 577, 316, 0, 0, 0, 528, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, + 0, 0, 366, 267, 0, 0, 204, 505, 0, 430, + 0, 203, 0, 487, 252, 377, 374, 583, 282, 273, + 269, 250, 317, 385, 428, 518, 422, 0, 370, 0, + 0, 497, 401, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 323, 248, 325, 202, 413, 498, 286, 0, 0, + 0, 0, 1954, 507, 194, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 238, 0, 0, 245, 0, 0, + 0, 351, 360, 359, 339, 340, 342, 344, 350, 357, + 363, 336, 345, 0, 0, 607, 0, 0, 0, 265, + 321, 272, 264, 580, 0, 0, 0, 0, 0, 0, + 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 275, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 297, + 0, 402, 257, 0, 453, 0, 0, 0, 626, 0, + 0, 0, 0, 0, 0, 0, 365, 0, 330, 197, + 225, 0, 0, 412, 461, 473, 0, 0, 0, 253, + 0, 471, 426, 602, 233, 284, 458, 432, 469, 440, + 287, 0, 0, 470, 372, 585, 450, 599, 627, 628, + 263, 406, 612, 522, 620, 645, 226, 260, 420, 506, + 605, 494, 397, 581, 582, 329, 493, 295, 201, 369, + 633, 224, 479, 371, 242, 231, 587, 609, 299, 289, + 456, 640, 213, 517, 597, 239, 483, 0, 0, 648, + 247, 504, 215, 594, 503, 393, 326, 327, 214, 0, + 457, 268, 293, 0, 0, 258, 415, 589, 590, 256, + 649, 228, 619, 220, 0, 618, 408, 584, 595, 394, + 383, 219, 593, 392, 382, 334, 355, 356, 280, 307, + 447, 375, 448, 306, 308, 404, 403, 405, 207, 606, + 623, 0, 208, 0, 499, 608, 650, 452, 212, 234, + 235, 237, 0, 279, 283, 291, 294, 303, 304, 313, + 367, 419, 446, 442, 451, 0, 579, 600, 613, 625, + 631, 632, 634, 635, 636, 637, 638, 641, 639, 407, + 311, 495, 333, 373, 0, 0, 425, 472, 240, 604, + 496, 199, 0, 0, 0, 0, 254, 255, 0, 575, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 651, + 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, + 662, 663, 664, 665, 666, 667, 668, 646, 508, 514, + 509, 510, 511, 512, 513, 0, 515, 0, 0, 0, + 0, 0, 398, 0, 591, 592, 669, 384, 486, 601, + 335, 349, 352, 341, 361, 0, 362, 337, 338, 343, + 346, 347, 348, 353, 354, 358, 364, 249, 210, 390, + 399, 578, 312, 216, 217, 218, 524, 525, 526, 527, + 616, 617, 621, 205, 462, 463, 464, 465, 292, 611, + 309, 468, 467, 331, 332, 379, 449, 540, 542, 553, + 557, 559, 561, 567, 570, 541, 543, 554, 558, 560, + 562, 568, 571, 530, 532, 534, 536, 549, 548, 545, + 573, 574, 551, 556, 535, 547, 552, 565, 572, 569, + 529, 533, 537, 546, 564, 563, 544, 555, 566, 550, + 538, 531, 539, 0, 196, 221, 368, 0, 454, 288, + 647, 615, 484, 610, 206, 223, 0, 262, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, + 200, 209, 222, 232, 236, 243, 261, 276, 278, 285, + 298, 310, 318, 319, 322, 328, 380, 386, 387, 388, + 389, 409, 410, 411, 414, 417, 418, 421, 423, 424, + 427, 431, 435, 436, 437, 439, 441, 443, 455, 460, + 474, 475, 476, 477, 478, 481, 482, 488, 489, 490, + 491, 492, 500, 501, 516, 586, 588, 603, 622, 629, + 480, 301, 302, 444, 445, 314, 315, 643, 644, 300, + 598, 630, 596, 642, 624, 438, 378, 0, 0, 381, + 281, 305, 320, 0, 614, 502, 227, 466, 290, 251, + 0, 0, 211, 246, 230, 259, 274, 277, 324, 391, + 400, 429, 434, 296, 271, 244, 459, 241, 485, 519, + 520, 521, 523, 395, 266, 433, 396, 0, 376, 576, + 577, 316, 0, 0, 0, 528, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, + 0, 0, 0, 0, 0, 270, 0, 0, 0, 0, + 366, 267, 0, 0, 204, 505, 0, 430, 0, 203, + 0, 487, 252, 377, 374, 583, 282, 273, 269, 250, + 317, 385, 428, 518, 422, 0, 370, 0, 0, 497, + 401, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 323, + 248, 325, 202, 413, 498, 286, 0, 0, 0, 0, + 0, 507, 720, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 238, 0, 0, 245, 0, 0, 0, 351, + 360, 359, 339, 340, 342, 344, 350, 357, 363, 336, + 345, 0, 0, 607, 0, 0, 0, 265, 321, 272, + 264, 580, 0, 0, 0, 0, 0, 0, 0, 0, + 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 275, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 297, 0, 402, + 257, 0, 453, 0, 0, 0, 626, 0, 0, 0, + 3719, 0, 0, 0, 365, 0, 330, 197, 225, 0, + 0, 412, 461, 473, 0, 0, 0, 253, 0, 471, + 426, 602, 233, 284, 458, 432, 469, 440, 287, 0, + 0, 470, 372, 585, 450, 599, 627, 628, 263, 406, + 612, 522, 620, 645, 226, 260, 420, 506, 605, 494, + 397, 581, 582, 329, 493, 295, 201, 369, 633, 224, + 479, 371, 242, 231, 587, 609, 299, 289, 456, 640, + 213, 517, 597, 239, 483, 0, 0, 648, 247, 504, + 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, + 293, 0, 0, 258, 415, 589, 590, 256, 649, 228, + 619, 220, 0, 618, 408, 584, 595, 394, 383, 219, + 593, 392, 382, 334, 355, 356, 280, 307, 447, 375, + 448, 306, 308, 404, 403, 405, 207, 606, 623, 0, + 208, 0, 499, 608, 650, 452, 212, 234, 235, 237, + 0, 279, 283, 291, 294, 303, 304, 313, 367, 419, + 446, 442, 451, 0, 579, 600, 613, 625, 631, 632, + 634, 635, 636, 637, 638, 641, 639, 407, 311, 495, + 333, 373, 0, 0, 425, 472, 240, 604, 496, 199, + 0, 0, 0, 0, 254, 255, 0, 575, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 651, 652, 653, + 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, + 664, 665, 666, 667, 668, 646, 508, 514, 509, 510, + 511, 512, 513, 0, 515, 0, 0, 0, 0, 0, + 398, 0, 591, 592, 669, 384, 486, 601, 335, 349, + 352, 341, 361, 0, 362, 337, 338, 343, 346, 347, + 348, 353, 354, 358, 364, 249, 210, 390, 399, 578, + 312, 216, 217, 218, 524, 525, 526, 527, 616, 617, + 621, 205, 462, 463, 464, 465, 292, 611, 309, 468, + 467, 331, 332, 379, 449, 540, 542, 553, 557, 559, + 561, 567, 570, 541, 543, 554, 558, 560, 562, 568, + 571, 530, 532, 534, 536, 549, 548, 545, 573, 574, + 551, 556, 535, 547, 552, 565, 572, 569, 529, 533, + 537, 546, 564, 563, 544, 555, 566, 550, 538, 531, + 539, 0, 196, 221, 368, 0, 454, 288, 647, 615, + 484, 610, 206, 223, 0, 262, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 198, 200, 209, + 222, 232, 236, 243, 261, 276, 278, 285, 298, 310, + 318, 319, 322, 328, 380, 386, 387, 388, 389, 409, + 410, 411, 414, 417, 418, 421, 423, 424, 427, 431, + 435, 436, 437, 439, 441, 443, 455, 460, 474, 475, + 476, 477, 478, 481, 482, 488, 489, 490, 491, 492, + 500, 501, 516, 586, 588, 603, 622, 629, 480, 301, + 302, 444, 445, 314, 315, 643, 644, 300, 598, 630, + 596, 642, 624, 438, 378, 0, 0, 381, 281, 305, + 320, 0, 614, 502, 227, 466, 290, 251, 0, 0, + 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, + 434, 296, 271, 244, 459, 241, 485, 519, 520, 521, + 523, 395, 266, 433, 396, 0, 376, 576, 577, 316, + 0, 0, 0, 528, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, + 0, 0, 0, 270, 0, 0, 0, 0, 366, 267, + 0, 0, 204, 505, 0, 430, 0, 203, 0, 487, + 252, 377, 374, 583, 282, 273, 269, 250, 317, 385, + 428, 518, 422, 0, 370, 0, 0, 497, 401, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 323, 248, 325, + 202, 413, 498, 286, 0, 95, 0, 0, 0, 507, + 720, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 245, 0, 0, 0, 351, 360, 359, + 339, 340, 342, 344, 350, 357, 363, 336, 345, 0, + 0, 607, 0, 0, 0, 265, 321, 272, 264, 580, + 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 297, 0, 402, 257, 0, + 453, 0, 0, 0, 626, 0, 0, 0, 0, 0, + 0, 0, 365, 0, 330, 197, 225, 0, 0, 412, + 461, 473, 0, 0, 0, 253, 0, 471, 426, 602, + 233, 284, 458, 432, 469, 440, 287, 0, 0, 470, + 372, 585, 450, 599, 627, 628, 263, 406, 612, 522, + 620, 645, 226, 260, 420, 506, 605, 494, 397, 581, + 582, 329, 493, 295, 201, 369, 633, 224, 479, 371, + 242, 231, 587, 609, 299, 289, 456, 640, 213, 517, + 597, 239, 483, 0, 0, 648, 247, 504, 215, 594, + 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, + 0, 258, 415, 589, 590, 256, 649, 228, 619, 220, + 0, 618, 408, 584, 595, 394, 383, 219, 593, 392, + 382, 334, 355, 356, 280, 307, 447, 375, 448, 306, + 308, 404, 403, 405, 207, 606, 623, 0, 208, 0, + 499, 608, 650, 452, 212, 234, 235, 237, 0, 279, + 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, + 451, 0, 579, 600, 613, 625, 631, 632, 634, 635, + 636, 637, 638, 641, 639, 407, 311, 495, 333, 373, + 0, 0, 425, 472, 240, 604, 496, 199, 0, 0, + 0, 0, 254, 255, 0, 575, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 651, 652, 653, 654, 655, + 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, + 666, 667, 668, 646, 508, 514, 509, 510, 511, 512, + 513, 0, 515, 0, 0, 0, 0, 0, 398, 0, + 591, 592, 669, 384, 486, 601, 335, 349, 352, 341, + 361, 0, 362, 337, 338, 343, 346, 347, 348, 353, + 354, 358, 364, 249, 210, 390, 399, 578, 312, 216, + 217, 218, 524, 525, 526, 527, 616, 617, 621, 205, + 462, 463, 464, 465, 292, 611, 309, 468, 467, 331, + 332, 379, 449, 540, 542, 553, 557, 559, 561, 567, + 570, 541, 543, 554, 558, 560, 562, 568, 571, 530, + 532, 534, 536, 549, 548, 545, 573, 574, 551, 556, + 535, 547, 552, 565, 572, 569, 529, 533, 537, 546, + 564, 563, 544, 555, 566, 550, 538, 531, 539, 0, + 196, 221, 368, 0, 454, 288, 647, 615, 484, 610, + 206, 223, 0, 262, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 198, 200, 209, 222, 232, + 236, 243, 261, 276, 278, 285, 298, 310, 318, 319, + 322, 328, 380, 386, 387, 388, 389, 409, 410, 411, + 414, 417, 418, 421, 423, 424, 427, 431, 435, 436, + 437, 439, 441, 443, 455, 460, 474, 475, 476, 477, + 478, 481, 482, 488, 489, 490, 491, 492, 500, 501, + 516, 586, 588, 603, 622, 629, 480, 301, 302, 444, + 445, 314, 315, 643, 644, 300, 598, 630, 596, 642, + 624, 438, 378, 0, 0, 381, 281, 305, 320, 0, + 614, 502, 227, 466, 290, 251, 0, 0, 211, 246, + 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, + 271, 244, 459, 241, 485, 519, 520, 521, 523, 395, + 266, 433, 396, 0, 376, 576, 577, 316, 0, 0, + 0, 528, 0, 0, 0, 0, 2419, 0, 0, 0, + 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 270, 0, 0, 0, 0, 366, 267, 0, 0, + 204, 505, 0, 430, 0, 203, 0, 487, 252, 377, + 374, 583, 282, 273, 269, 250, 317, 385, 428, 518, + 422, 0, 370, 0, 0, 497, 401, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 323, 248, 325, 202, 413, + 498, 286, 0, 0, 0, 0, 0, 507, 194, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 238, 0, + 0, 245, 0, 0, 0, 351, 360, 359, 339, 340, + 342, 344, 350, 357, 363, 336, 345, 0, 0, 607, + 0, 0, 0, 265, 321, 272, 264, 580, 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6953,69 +5721,365 @@ 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, 297, 0, 400, 257, 0, 451, 0, - 668, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, + 0, 0, 0, 297, 0, 402, 257, 0, 453, 0, + 0, 0, 626, 0, 0, 0, 0, 0, 0, 0, + 365, 0, 330, 197, 225, 0, 0, 412, 461, 473, + 0, 0, 0, 253, 0, 471, 426, 602, 233, 284, + 458, 432, 469, 440, 287, 0, 0, 470, 372, 585, + 450, 599, 627, 628, 263, 406, 612, 522, 620, 645, + 226, 260, 420, 506, 605, 494, 397, 581, 582, 329, + 493, 295, 201, 369, 633, 224, 479, 371, 242, 231, + 587, 609, 299, 289, 456, 640, 213, 517, 597, 239, + 483, 0, 0, 648, 247, 504, 215, 594, 503, 393, + 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, + 415, 589, 590, 256, 649, 228, 619, 220, 0, 618, + 408, 584, 595, 394, 383, 219, 593, 392, 382, 334, + 355, 356, 280, 307, 447, 375, 448, 306, 308, 404, + 403, 405, 207, 606, 623, 0, 208, 0, 499, 608, + 650, 452, 212, 234, 235, 237, 0, 279, 283, 291, + 294, 303, 304, 313, 367, 419, 446, 442, 451, 0, + 579, 600, 613, 625, 631, 632, 634, 635, 636, 637, + 638, 641, 639, 407, 311, 495, 333, 373, 0, 0, + 425, 472, 240, 604, 496, 199, 0, 0, 0, 0, + 254, 255, 0, 575, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 651, 652, 653, 654, 655, 656, 657, + 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, + 668, 646, 508, 514, 509, 510, 511, 512, 513, 0, + 515, 0, 0, 0, 0, 0, 398, 0, 591, 592, + 669, 384, 486, 601, 335, 349, 352, 341, 361, 0, + 362, 337, 338, 343, 346, 347, 348, 353, 354, 358, + 364, 249, 210, 390, 399, 578, 312, 216, 217, 218, + 524, 525, 526, 527, 616, 617, 621, 205, 462, 463, + 464, 465, 292, 611, 309, 468, 467, 331, 332, 379, + 449, 540, 542, 553, 557, 559, 561, 567, 570, 541, + 543, 554, 558, 560, 562, 568, 571, 530, 532, 534, + 536, 549, 548, 545, 573, 574, 551, 556, 535, 547, + 552, 565, 572, 569, 529, 533, 537, 546, 564, 563, + 544, 555, 566, 550, 538, 531, 539, 0, 196, 221, + 368, 0, 454, 288, 647, 615, 484, 610, 206, 223, + 0, 262, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 198, 200, 209, 222, 232, 236, 243, + 261, 276, 278, 285, 298, 310, 318, 319, 322, 328, + 380, 386, 387, 388, 389, 409, 410, 411, 414, 417, + 418, 421, 423, 424, 427, 431, 435, 436, 437, 439, + 441, 443, 455, 460, 474, 475, 476, 477, 478, 481, + 482, 488, 489, 490, 491, 492, 500, 501, 516, 586, + 588, 603, 622, 629, 480, 301, 302, 444, 445, 314, + 315, 643, 644, 300, 598, 630, 596, 642, 624, 438, + 378, 0, 0, 381, 281, 305, 320, 0, 614, 502, + 227, 466, 290, 251, 0, 0, 211, 246, 230, 259, + 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, + 459, 241, 485, 519, 520, 521, 523, 395, 266, 433, + 396, 0, 376, 576, 577, 316, 0, 0, 0, 528, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 416, 0, 0, 0, 0, 0, 0, 0, 270, + 0, 0, 0, 0, 366, 267, 0, 0, 204, 505, + 0, 430, 0, 203, 0, 487, 252, 377, 374, 583, + 282, 273, 269, 250, 317, 385, 428, 518, 422, 0, + 370, 0, 0, 497, 401, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 323, 248, 325, 202, 413, 498, 286, + 0, 0, 0, 0, 1774, 507, 720, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 238, 0, 0, 245, + 0, 0, 0, 351, 360, 359, 339, 340, 342, 344, + 350, 357, 363, 336, 345, 0, 0, 607, 0, 0, + 0, 265, 321, 272, 264, 580, 0, 0, 0, 0, + 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 297, 0, 402, 257, 0, 453, 0, 0, 0, + 626, 0, 0, 0, 0, 0, 0, 0, 365, 0, + 330, 197, 225, 0, 0, 412, 461, 473, 0, 0, + 0, 253, 0, 471, 426, 602, 233, 284, 458, 432, + 469, 440, 287, 0, 0, 470, 372, 585, 450, 599, + 627, 628, 263, 406, 612, 522, 620, 645, 226, 260, + 420, 506, 605, 494, 397, 581, 582, 329, 493, 295, + 201, 369, 633, 224, 479, 371, 242, 231, 587, 609, + 299, 289, 456, 640, 213, 517, 597, 239, 483, 0, + 0, 648, 247, 504, 215, 594, 503, 393, 326, 327, + 214, 0, 457, 268, 293, 0, 0, 258, 415, 589, + 590, 256, 649, 228, 619, 220, 0, 618, 408, 584, + 595, 394, 383, 219, 593, 392, 382, 334, 355, 356, + 280, 307, 447, 375, 448, 306, 308, 404, 403, 405, + 207, 606, 623, 0, 208, 0, 499, 608, 650, 452, + 212, 234, 235, 237, 0, 279, 283, 291, 294, 303, + 304, 313, 367, 419, 446, 442, 451, 0, 579, 600, + 613, 625, 631, 632, 634, 635, 636, 637, 638, 641, + 639, 407, 311, 495, 333, 373, 0, 0, 425, 472, + 240, 604, 496, 199, 0, 0, 0, 0, 254, 255, + 0, 575, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 651, 652, 653, 654, 655, 656, 657, 658, 659, + 660, 661, 662, 663, 664, 665, 666, 667, 668, 646, + 508, 514, 509, 510, 511, 512, 513, 0, 515, 0, + 0, 0, 0, 0, 398, 0, 591, 592, 669, 384, + 486, 601, 335, 349, 352, 341, 361, 0, 362, 337, + 338, 343, 346, 347, 348, 353, 354, 358, 364, 249, + 210, 390, 399, 578, 312, 216, 217, 218, 524, 525, + 526, 527, 616, 617, 621, 205, 462, 463, 464, 465, + 292, 611, 309, 468, 467, 331, 332, 379, 449, 540, + 542, 553, 557, 559, 561, 567, 570, 541, 543, 554, + 558, 560, 562, 568, 571, 530, 532, 534, 536, 549, + 548, 545, 573, 574, 551, 556, 535, 547, 552, 565, + 572, 569, 529, 533, 537, 546, 564, 563, 544, 555, + 566, 550, 538, 531, 539, 0, 196, 221, 368, 0, + 454, 288, 647, 615, 484, 610, 206, 223, 0, 262, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 198, 200, 209, 222, 232, 236, 243, 261, 276, + 278, 285, 298, 310, 318, 319, 322, 328, 380, 386, + 387, 388, 389, 409, 410, 411, 414, 417, 418, 421, + 423, 424, 427, 431, 435, 436, 437, 439, 441, 443, + 455, 460, 474, 475, 476, 477, 478, 481, 482, 488, + 489, 490, 491, 492, 500, 501, 516, 586, 588, 603, + 622, 629, 480, 301, 302, 444, 445, 314, 315, 643, + 644, 300, 598, 630, 596, 642, 624, 438, 378, 0, + 0, 381, 281, 305, 320, 0, 614, 502, 227, 466, + 290, 251, 0, 0, 211, 246, 230, 259, 274, 277, + 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, + 485, 519, 520, 521, 523, 395, 266, 433, 396, 0, + 376, 576, 577, 316, 0, 0, 0, 528, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, + 0, 0, 366, 267, 0, 0, 204, 505, 0, 430, + 0, 203, 0, 487, 252, 377, 374, 583, 282, 273, + 269, 250, 317, 385, 428, 518, 422, 0, 370, 0, + 0, 497, 401, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 323, 248, 325, 202, 413, 498, 286, 0, 0, + 0, 0, 0, 507, 194, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 238, 0, 0, 245, 0, 0, + 0, 351, 360, 359, 339, 340, 342, 344, 350, 357, + 363, 336, 345, 0, 0, 607, 0, 0, 0, 265, + 321, 272, 264, 580, 0, 0, 0, 0, 0, 0, + 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 275, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 297, + 0, 402, 257, 0, 453, 0, 0, 0, 626, 0, + 0, 0, 0, 0, 0, 0, 365, 0, 330, 197, + 225, 0, 0, 412, 461, 473, 0, 0, 0, 253, + 0, 471, 426, 602, 233, 284, 458, 432, 469, 440, + 287, 0, 0, 470, 372, 585, 450, 599, 627, 628, + 263, 406, 612, 522, 620, 645, 226, 260, 420, 506, + 605, 494, 397, 581, 582, 329, 493, 295, 201, 369, + 633, 224, 479, 371, 242, 231, 587, 609, 299, 289, + 456, 640, 213, 517, 597, 239, 483, 0, 0, 648, + 247, 504, 215, 594, 503, 393, 326, 327, 214, 0, + 457, 268, 293, 0, 0, 258, 415, 589, 590, 256, + 649, 228, 619, 220, 0, 618, 408, 584, 595, 394, + 383, 219, 593, 392, 382, 334, 355, 356, 280, 307, + 447, 375, 448, 306, 308, 404, 403, 405, 207, 606, + 623, 0, 208, 0, 499, 608, 650, 452, 212, 234, + 235, 237, 0, 279, 283, 291, 294, 303, 304, 313, + 367, 419, 446, 442, 451, 0, 579, 600, 613, 625, + 631, 632, 634, 635, 636, 637, 638, 641, 639, 407, + 311, 495, 333, 373, 0, 0, 425, 472, 240, 604, + 496, 199, 0, 0, 0, 0, 254, 255, 0, 575, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 651, + 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, + 662, 663, 664, 665, 666, 667, 668, 646, 508, 514, + 509, 510, 511, 512, 513, 0, 515, 0, 0, 0, + 0, 0, 398, 0, 591, 592, 669, 384, 486, 601, + 335, 349, 352, 341, 361, 0, 362, 337, 338, 343, + 346, 347, 348, 353, 354, 358, 364, 249, 210, 390, + 399, 578, 312, 216, 217, 218, 524, 525, 526, 527, + 616, 617, 621, 205, 462, 463, 464, 465, 292, 611, + 309, 468, 467, 331, 332, 379, 449, 540, 542, 553, + 557, 559, 561, 567, 570, 541, 543, 554, 558, 560, + 562, 568, 571, 530, 532, 534, 536, 549, 548, 545, + 573, 574, 551, 556, 535, 547, 552, 565, 572, 569, + 529, 533, 537, 546, 564, 563, 544, 555, 566, 550, + 538, 531, 539, 0, 196, 221, 368, 2071, 454, 288, + 647, 615, 484, 610, 206, 223, 0, 262, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, + 200, 209, 222, 232, 236, 243, 261, 276, 278, 285, + 298, 310, 318, 319, 322, 328, 380, 386, 387, 388, + 389, 409, 410, 411, 414, 417, 418, 421, 423, 424, + 427, 431, 435, 436, 437, 439, 441, 443, 455, 460, + 474, 475, 476, 477, 478, 481, 482, 488, 489, 490, + 491, 492, 500, 501, 516, 586, 588, 603, 622, 629, + 480, 301, 302, 444, 445, 314, 315, 643, 644, 300, + 598, 630, 596, 642, 624, 438, 378, 0, 0, 381, + 281, 305, 320, 0, 614, 502, 227, 466, 290, 251, + 0, 0, 211, 246, 230, 259, 274, 277, 324, 391, + 400, 429, 434, 296, 271, 244, 459, 241, 485, 519, + 520, 521, 523, 395, 266, 433, 396, 0, 376, 576, + 577, 316, 0, 0, 0, 528, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, + 0, 0, 0, 0, 0, 270, 0, 0, 0, 0, + 366, 267, 0, 0, 204, 505, 0, 430, 0, 203, + 0, 487, 252, 377, 374, 583, 282, 273, 269, 250, + 317, 385, 428, 518, 422, 0, 370, 0, 0, 497, + 401, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 323, + 248, 325, 202, 413, 498, 286, 0, 0, 0, 0, + 2062, 507, 720, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 238, 0, 0, 245, 0, 0, 0, 351, + 360, 359, 339, 340, 342, 344, 350, 357, 363, 336, + 345, 0, 0, 607, 0, 0, 0, 265, 321, 272, + 264, 580, 0, 0, 0, 0, 0, 0, 0, 0, + 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 275, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 297, 0, 402, + 257, 0, 453, 0, 0, 0, 626, 0, 0, 0, + 0, 0, 0, 0, 365, 0, 330, 197, 225, 0, + 0, 412, 461, 473, 0, 0, 0, 253, 0, 471, + 426, 602, 233, 284, 458, 432, 469, 440, 287, 0, + 0, 470, 372, 585, 450, 599, 627, 628, 263, 406, + 612, 522, 620, 645, 226, 260, 420, 506, 605, 494, + 397, 581, 582, 329, 493, 295, 201, 369, 633, 224, + 479, 371, 242, 231, 587, 609, 299, 289, 456, 640, + 213, 517, 597, 239, 483, 0, 0, 648, 247, 504, + 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, + 293, 0, 0, 258, 415, 589, 590, 256, 649, 228, + 619, 220, 0, 618, 408, 584, 595, 394, 383, 219, + 593, 392, 382, 334, 355, 356, 280, 307, 447, 375, + 448, 306, 308, 404, 403, 405, 207, 606, 623, 0, + 208, 0, 499, 608, 650, 452, 212, 234, 235, 237, + 0, 279, 283, 291, 294, 303, 304, 313, 367, 419, + 446, 442, 451, 0, 579, 600, 613, 625, 631, 632, + 634, 635, 636, 637, 638, 641, 639, 407, 311, 495, + 333, 373, 0, 0, 425, 472, 240, 604, 496, 199, + 0, 0, 0, 0, 254, 255, 0, 575, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 651, 652, 653, + 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, + 664, 665, 666, 667, 668, 646, 508, 514, 509, 510, + 511, 512, 513, 0, 515, 0, 0, 0, 0, 0, + 398, 0, 591, 592, 669, 384, 486, 601, 335, 349, + 352, 341, 361, 0, 362, 337, 338, 343, 346, 347, + 348, 353, 354, 358, 364, 249, 210, 390, 399, 578, + 312, 216, 217, 218, 524, 525, 526, 527, 616, 617, + 621, 205, 462, 463, 464, 465, 292, 611, 309, 468, + 467, 331, 332, 379, 449, 540, 542, 553, 557, 559, + 561, 567, 570, 541, 543, 554, 558, 560, 562, 568, + 571, 530, 532, 534, 536, 549, 548, 545, 573, 574, + 551, 556, 535, 547, 552, 565, 572, 569, 529, 533, + 537, 546, 564, 563, 544, 555, 566, 550, 538, 531, + 539, 0, 196, 221, 368, 0, 454, 288, 647, 615, + 484, 610, 206, 223, 0, 262, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 198, 200, 209, + 222, 232, 236, 243, 261, 276, 278, 285, 298, 310, + 318, 319, 322, 328, 380, 386, 387, 388, 389, 409, + 410, 411, 414, 417, 418, 421, 423, 424, 427, 431, + 435, 436, 437, 439, 441, 443, 455, 460, 474, 475, + 476, 477, 478, 481, 482, 488, 489, 490, 491, 492, + 500, 501, 516, 586, 588, 603, 622, 629, 480, 301, + 302, 444, 445, 314, 315, 643, 644, 300, 598, 630, + 596, 642, 624, 438, 378, 0, 0, 381, 281, 305, + 320, 0, 614, 502, 227, 466, 290, 251, 0, 0, + 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, + 434, 296, 271, 244, 459, 241, 485, 519, 520, 521, + 523, 395, 266, 433, 396, 0, 376, 576, 577, 316, + 0, 0, 0, 528, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, + 0, 0, 0, 270, 0, 0, 0, 0, 366, 267, + 0, 1921, 204, 505, 0, 430, 0, 203, 0, 487, + 252, 377, 374, 583, 282, 273, 269, 250, 317, 385, + 428, 518, 422, 0, 370, 0, 0, 497, 401, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 323, 248, 325, + 202, 413, 498, 286, 0, 0, 0, 0, 0, 507, + 720, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 245, 0, 0, 0, 351, 360, 359, + 339, 340, 342, 344, 350, 357, 363, 336, 345, 0, + 0, 607, 0, 0, 0, 265, 321, 272, 264, 580, + 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 297, 0, 402, 257, 0, + 453, 0, 0, 0, 626, 0, 0, 0, 0, 0, + 0, 0, 365, 0, 330, 197, 225, 0, 0, 412, + 461, 473, 0, 0, 0, 253, 0, 471, 426, 602, + 233, 284, 458, 432, 469, 440, 287, 0, 0, 470, + 372, 585, 450, 599, 627, 628, 263, 406, 612, 522, + 620, 645, 226, 260, 420, 506, 605, 494, 397, 581, + 582, 329, 493, 295, 201, 369, 633, 224, 479, 371, + 242, 231, 587, 609, 299, 289, 456, 640, 213, 517, + 597, 239, 483, 0, 0, 648, 247, 504, 215, 594, + 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, + 0, 258, 415, 589, 590, 256, 649, 228, 619, 220, + 0, 618, 408, 584, 595, 394, 383, 219, 593, 392, + 382, 334, 355, 356, 280, 307, 447, 375, 448, 306, + 308, 404, 403, 405, 207, 606, 623, 0, 208, 0, + 499, 608, 650, 452, 212, 234, 235, 237, 0, 279, + 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, + 451, 0, 579, 600, 613, 625, 631, 632, 634, 635, + 636, 637, 638, 641, 639, 407, 311, 495, 333, 373, + 0, 0, 425, 472, 240, 604, 496, 199, 0, 0, + 0, 0, 254, 255, 0, 575, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 651, 652, 653, 654, 655, + 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, + 666, 667, 668, 646, 508, 514, 509, 510, 511, 512, + 513, 0, 515, 0, 0, 0, 0, 0, 398, 0, + 591, 592, 669, 384, 486, 601, 335, 349, 352, 341, + 361, 0, 362, 337, 338, 343, 346, 347, 348, 353, + 354, 358, 364, 249, 210, 390, 399, 578, 312, 216, + 217, 218, 524, 525, 526, 527, 616, 617, 621, 205, + 462, 463, 464, 465, 292, 611, 309, 468, 467, 331, + 332, 379, 449, 540, 542, 553, 557, 559, 561, 567, + 570, 541, 543, 554, 558, 560, 562, 568, 571, 530, + 532, 534, 536, 549, 548, 545, 573, 574, 551, 556, + 535, 547, 552, 565, 572, 569, 529, 533, 537, 546, + 564, 563, 544, 555, 566, 550, 538, 531, 539, 0, + 196, 221, 368, 0, 454, 288, 647, 615, 484, 610, + 206, 223, 0, 262, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 198, 200, 209, 222, 232, + 236, 243, 261, 276, 278, 285, 298, 310, 318, 319, + 322, 328, 380, 386, 387, 388, 389, 409, 410, 411, + 414, 417, 418, 421, 423, 424, 427, 431, 435, 436, + 437, 439, 441, 443, 455, 460, 474, 475, 476, 477, + 478, 481, 482, 488, 489, 490, 491, 492, 500, 501, + 516, 586, 588, 603, 622, 629, 480, 301, 302, 444, + 445, 314, 315, 643, 644, 300, 598, 630, 596, 642, + 624, 438, 378, 0, 0, 381, 281, 305, 320, 0, + 614, 502, 227, 466, 290, 251, 0, 0, 211, 246, + 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, + 271, 244, 459, 241, 485, 519, 520, 521, 523, 395, + 266, 433, 396, 0, 376, 576, 577, 316, 0, 0, + 0, 528, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 270, 0, 0, 0, 0, 366, 267, 0, 1919, + 204, 505, 0, 430, 0, 203, 0, 487, 252, 377, + 374, 583, 282, 273, 269, 250, 317, 385, 428, 518, + 422, 0, 370, 0, 0, 497, 401, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 323, 248, 325, 202, 413, + 498, 286, 0, 0, 0, 0, 0, 507, 720, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 238, 0, + 0, 245, 0, 0, 0, 351, 360, 359, 339, 340, + 342, 344, 350, 357, 363, 336, 345, 0, 0, 607, + 0, 0, 0, 265, 321, 272, 264, 580, 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, @@ -7026,69 +6090,365 @@ 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, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 4095, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, + 0, 0, 0, 297, 0, 402, 257, 0, 453, 0, + 0, 0, 626, 0, 0, 0, 0, 0, 0, 0, + 365, 0, 330, 197, 225, 0, 0, 412, 461, 473, + 0, 0, 0, 253, 0, 471, 426, 602, 233, 284, + 458, 432, 469, 440, 287, 0, 0, 470, 372, 585, + 450, 599, 627, 628, 263, 406, 612, 522, 620, 645, + 226, 260, 420, 506, 605, 494, 397, 581, 582, 329, + 493, 295, 201, 369, 633, 224, 479, 371, 242, 231, + 587, 609, 299, 289, 456, 640, 213, 517, 597, 239, + 483, 0, 0, 648, 247, 504, 215, 594, 503, 393, + 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, + 415, 589, 590, 256, 649, 228, 619, 220, 0, 618, + 408, 584, 595, 394, 383, 219, 593, 392, 382, 334, + 355, 356, 280, 307, 447, 375, 448, 306, 308, 404, + 403, 405, 207, 606, 623, 0, 208, 0, 499, 608, + 650, 452, 212, 234, 235, 237, 0, 279, 283, 291, + 294, 303, 304, 313, 367, 419, 446, 442, 451, 0, + 579, 600, 613, 625, 631, 632, 634, 635, 636, 637, + 638, 641, 639, 407, 311, 495, 333, 373, 0, 0, + 425, 472, 240, 604, 496, 199, 0, 0, 0, 0, + 254, 255, 0, 575, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 651, 652, 653, 654, 655, 656, 657, + 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, + 668, 646, 508, 514, 509, 510, 511, 512, 513, 0, + 515, 0, 0, 0, 0, 0, 398, 0, 591, 592, + 669, 384, 486, 601, 335, 349, 352, 341, 361, 0, + 362, 337, 338, 343, 346, 347, 348, 353, 354, 358, + 364, 249, 210, 390, 399, 578, 312, 216, 217, 218, + 524, 525, 526, 527, 616, 617, 621, 205, 462, 463, + 464, 465, 292, 611, 309, 468, 467, 331, 332, 379, + 449, 540, 542, 553, 557, 559, 561, 567, 570, 541, + 543, 554, 558, 560, 562, 568, 571, 530, 532, 534, + 536, 549, 548, 545, 573, 574, 551, 556, 535, 547, + 552, 565, 572, 569, 529, 533, 537, 546, 564, 563, + 544, 555, 566, 550, 538, 531, 539, 0, 196, 221, + 368, 0, 454, 288, 647, 615, 484, 610, 206, 223, + 0, 262, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 198, 200, 209, 222, 232, 236, 243, + 261, 276, 278, 285, 298, 310, 318, 319, 322, 328, + 380, 386, 387, 388, 389, 409, 410, 411, 414, 417, + 418, 421, 423, 424, 427, 431, 435, 436, 437, 439, + 441, 443, 455, 460, 474, 475, 476, 477, 478, 481, + 482, 488, 489, 490, 491, 492, 500, 501, 516, 586, + 588, 603, 622, 629, 480, 301, 302, 444, 445, 314, + 315, 643, 644, 300, 598, 630, 596, 642, 624, 438, + 378, 0, 0, 381, 281, 305, 320, 0, 614, 502, + 227, 466, 290, 251, 0, 0, 211, 246, 230, 259, + 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, + 459, 241, 485, 519, 520, 521, 523, 395, 266, 433, + 396, 0, 376, 576, 577, 316, 0, 0, 0, 528, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 416, 0, 0, 0, 0, 0, 0, 0, 270, + 0, 0, 0, 0, 366, 267, 0, 1917, 204, 505, + 0, 430, 0, 203, 0, 487, 252, 377, 374, 583, + 282, 273, 269, 250, 317, 385, 428, 518, 422, 0, + 370, 0, 0, 497, 401, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 323, 248, 325, 202, 413, 498, 286, + 0, 0, 0, 0, 0, 507, 720, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 238, 0, 0, 245, + 0, 0, 0, 351, 360, 359, 339, 340, 342, 344, + 350, 357, 363, 336, 345, 0, 0, 607, 0, 0, + 0, 265, 321, 272, 264, 580, 0, 0, 0, 0, + 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 297, 0, 402, 257, 0, 453, 0, 0, 0, + 626, 0, 0, 0, 0, 0, 0, 0, 365, 0, + 330, 197, 225, 0, 0, 412, 461, 473, 0, 0, + 0, 253, 0, 471, 426, 602, 233, 284, 458, 432, + 469, 440, 287, 0, 0, 470, 372, 585, 450, 599, + 627, 628, 263, 406, 612, 522, 620, 645, 226, 260, + 420, 506, 605, 494, 397, 581, 582, 329, 493, 295, + 201, 369, 633, 224, 479, 371, 242, 231, 587, 609, + 299, 289, 456, 640, 213, 517, 597, 239, 483, 0, + 0, 648, 247, 504, 215, 594, 503, 393, 326, 327, + 214, 0, 457, 268, 293, 0, 0, 258, 415, 589, + 590, 256, 649, 228, 619, 220, 0, 618, 408, 584, + 595, 394, 383, 219, 593, 392, 382, 334, 355, 356, + 280, 307, 447, 375, 448, 306, 308, 404, 403, 405, + 207, 606, 623, 0, 208, 0, 499, 608, 650, 452, + 212, 234, 235, 237, 0, 279, 283, 291, 294, 303, + 304, 313, 367, 419, 446, 442, 451, 0, 579, 600, + 613, 625, 631, 632, 634, 635, 636, 637, 638, 641, + 639, 407, 311, 495, 333, 373, 0, 0, 425, 472, + 240, 604, 496, 199, 0, 0, 0, 0, 254, 255, + 0, 575, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 651, 652, 653, 654, 655, 656, 657, 658, 659, + 660, 661, 662, 663, 664, 665, 666, 667, 668, 646, + 508, 514, 509, 510, 511, 512, 513, 0, 515, 0, + 0, 0, 0, 0, 398, 0, 591, 592, 669, 384, + 486, 601, 335, 349, 352, 341, 361, 0, 362, 337, + 338, 343, 346, 347, 348, 353, 354, 358, 364, 249, + 210, 390, 399, 578, 312, 216, 217, 218, 524, 525, + 526, 527, 616, 617, 621, 205, 462, 463, 464, 465, + 292, 611, 309, 468, 467, 331, 332, 379, 449, 540, + 542, 553, 557, 559, 561, 567, 570, 541, 543, 554, + 558, 560, 562, 568, 571, 530, 532, 534, 536, 549, + 548, 545, 573, 574, 551, 556, 535, 547, 552, 565, + 572, 569, 529, 533, 537, 546, 564, 563, 544, 555, + 566, 550, 538, 531, 539, 0, 196, 221, 368, 0, + 454, 288, 647, 615, 484, 610, 206, 223, 0, 262, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 198, 200, 209, 222, 232, 236, 243, 261, 276, + 278, 285, 298, 310, 318, 319, 322, 328, 380, 386, + 387, 388, 389, 409, 410, 411, 414, 417, 418, 421, + 423, 424, 427, 431, 435, 436, 437, 439, 441, 443, + 455, 460, 474, 475, 476, 477, 478, 481, 482, 488, + 489, 490, 491, 492, 500, 501, 516, 586, 588, 603, + 622, 629, 480, 301, 302, 444, 445, 314, 315, 643, + 644, 300, 598, 630, 596, 642, 624, 438, 378, 0, + 0, 381, 281, 305, 320, 0, 614, 502, 227, 466, + 290, 251, 0, 0, 211, 246, 230, 259, 274, 277, + 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, + 485, 519, 520, 521, 523, 395, 266, 433, 396, 0, + 376, 576, 577, 316, 0, 0, 0, 528, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, + 0, 0, 366, 267, 0, 1915, 204, 505, 0, 430, + 0, 203, 0, 487, 252, 377, 374, 583, 282, 273, + 269, 250, 317, 385, 428, 518, 422, 0, 370, 0, + 0, 497, 401, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 323, 248, 325, 202, 413, 498, 286, 0, 0, + 0, 0, 0, 507, 720, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 238, 0, 0, 245, 0, 0, + 0, 351, 360, 359, 339, 340, 342, 344, 350, 357, + 363, 336, 345, 0, 0, 607, 0, 0, 0, 265, + 321, 272, 264, 580, 0, 0, 0, 0, 0, 0, + 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 275, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 297, + 0, 402, 257, 0, 453, 0, 0, 0, 626, 0, + 0, 0, 0, 0, 0, 0, 365, 0, 330, 197, + 225, 0, 0, 412, 461, 473, 0, 0, 0, 253, + 0, 471, 426, 602, 233, 284, 458, 432, 469, 440, + 287, 0, 0, 470, 372, 585, 450, 599, 627, 628, + 263, 406, 612, 522, 620, 645, 226, 260, 420, 506, + 605, 494, 397, 581, 582, 329, 493, 295, 201, 369, + 633, 224, 479, 371, 242, 231, 587, 609, 299, 289, + 456, 640, 213, 517, 597, 239, 483, 0, 0, 648, + 247, 504, 215, 594, 503, 393, 326, 327, 214, 0, + 457, 268, 293, 0, 0, 258, 415, 589, 590, 256, + 649, 228, 619, 220, 0, 618, 408, 584, 595, 394, + 383, 219, 593, 392, 382, 334, 355, 356, 280, 307, + 447, 375, 448, 306, 308, 404, 403, 405, 207, 606, + 623, 0, 208, 0, 499, 608, 650, 452, 212, 234, + 235, 237, 0, 279, 283, 291, 294, 303, 304, 313, + 367, 419, 446, 442, 451, 0, 579, 600, 613, 625, + 631, 632, 634, 635, 636, 637, 638, 641, 639, 407, + 311, 495, 333, 373, 0, 0, 425, 472, 240, 604, + 496, 199, 0, 0, 0, 0, 254, 255, 0, 575, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 651, + 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, + 662, 663, 664, 665, 666, 667, 668, 646, 508, 514, + 509, 510, 511, 512, 513, 0, 515, 0, 0, 0, + 0, 0, 398, 0, 591, 592, 669, 384, 486, 601, + 335, 349, 352, 341, 361, 0, 362, 337, 338, 343, + 346, 347, 348, 353, 354, 358, 364, 249, 210, 390, + 399, 578, 312, 216, 217, 218, 524, 525, 526, 527, + 616, 617, 621, 205, 462, 463, 464, 465, 292, 611, + 309, 468, 467, 331, 332, 379, 449, 540, 542, 553, + 557, 559, 561, 567, 570, 541, 543, 554, 558, 560, + 562, 568, 571, 530, 532, 534, 536, 549, 548, 545, + 573, 574, 551, 556, 535, 547, 552, 565, 572, 569, + 529, 533, 537, 546, 564, 563, 544, 555, 566, 550, + 538, 531, 539, 0, 196, 221, 368, 0, 454, 288, + 647, 615, 484, 610, 206, 223, 0, 262, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, + 200, 209, 222, 232, 236, 243, 261, 276, 278, 285, + 298, 310, 318, 319, 322, 328, 380, 386, 387, 388, + 389, 409, 410, 411, 414, 417, 418, 421, 423, 424, + 427, 431, 435, 436, 437, 439, 441, 443, 455, 460, + 474, 475, 476, 477, 478, 481, 482, 488, 489, 490, + 491, 492, 500, 501, 516, 586, 588, 603, 622, 629, + 480, 301, 302, 444, 445, 314, 315, 643, 644, 300, + 598, 630, 596, 642, 624, 438, 378, 0, 0, 381, + 281, 305, 320, 0, 614, 502, 227, 466, 290, 251, + 0, 0, 211, 246, 230, 259, 274, 277, 324, 391, + 400, 429, 434, 296, 271, 244, 459, 241, 485, 519, + 520, 521, 523, 395, 266, 433, 396, 0, 376, 576, + 577, 316, 0, 0, 0, 528, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, + 0, 0, 0, 0, 0, 270, 0, 0, 0, 0, + 366, 267, 0, 1913, 204, 505, 0, 430, 0, 203, + 0, 487, 252, 377, 374, 583, 282, 273, 269, 250, + 317, 385, 428, 518, 422, 0, 370, 0, 0, 497, + 401, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 323, + 248, 325, 202, 413, 498, 286, 0, 0, 0, 0, + 0, 507, 720, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 238, 0, 0, 245, 0, 0, 0, 351, + 360, 359, 339, 340, 342, 344, 350, 357, 363, 336, + 345, 0, 0, 607, 0, 0, 0, 265, 321, 272, + 264, 580, 0, 0, 0, 0, 0, 0, 0, 0, + 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 275, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 297, 0, 402, + 257, 0, 453, 0, 0, 0, 626, 0, 0, 0, + 0, 0, 0, 0, 365, 0, 330, 197, 225, 0, + 0, 412, 461, 473, 0, 0, 0, 253, 0, 471, + 426, 602, 233, 284, 458, 432, 469, 440, 287, 0, + 0, 470, 372, 585, 450, 599, 627, 628, 263, 406, + 612, 522, 620, 645, 226, 260, 420, 506, 605, 494, + 397, 581, 582, 329, 493, 295, 201, 369, 633, 224, + 479, 371, 242, 231, 587, 609, 299, 289, 456, 640, + 213, 517, 597, 239, 483, 0, 0, 648, 247, 504, + 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, + 293, 0, 0, 258, 415, 589, 590, 256, 649, 228, + 619, 220, 0, 618, 408, 584, 595, 394, 383, 219, + 593, 392, 382, 334, 355, 356, 280, 307, 447, 375, + 448, 306, 308, 404, 403, 405, 207, 606, 623, 0, + 208, 0, 499, 608, 650, 452, 212, 234, 235, 237, + 0, 279, 283, 291, 294, 303, 304, 313, 367, 419, + 446, 442, 451, 0, 579, 600, 613, 625, 631, 632, + 634, 635, 636, 637, 638, 641, 639, 407, 311, 495, + 333, 373, 0, 0, 425, 472, 240, 604, 496, 199, + 0, 0, 0, 0, 254, 255, 0, 575, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 651, 652, 653, + 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, + 664, 665, 666, 667, 668, 646, 508, 514, 509, 510, + 511, 512, 513, 0, 515, 0, 0, 0, 0, 0, + 398, 0, 591, 592, 669, 384, 486, 601, 335, 349, + 352, 341, 361, 0, 362, 337, 338, 343, 346, 347, + 348, 353, 354, 358, 364, 249, 210, 390, 399, 578, + 312, 216, 217, 218, 524, 525, 526, 527, 616, 617, + 621, 205, 462, 463, 464, 465, 292, 611, 309, 468, + 467, 331, 332, 379, 449, 540, 542, 553, 557, 559, + 561, 567, 570, 541, 543, 554, 558, 560, 562, 568, + 571, 530, 532, 534, 536, 549, 548, 545, 573, 574, + 551, 556, 535, 547, 552, 565, 572, 569, 529, 533, + 537, 546, 564, 563, 544, 555, 566, 550, 538, 531, + 539, 0, 196, 221, 368, 0, 454, 288, 647, 615, + 484, 610, 206, 223, 0, 262, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 198, 200, 209, + 222, 232, 236, 243, 261, 276, 278, 285, 298, 310, + 318, 319, 322, 328, 380, 386, 387, 388, 389, 409, + 410, 411, 414, 417, 418, 421, 423, 424, 427, 431, + 435, 436, 437, 439, 441, 443, 455, 460, 474, 475, + 476, 477, 478, 481, 482, 488, 489, 490, 491, 492, + 500, 501, 516, 586, 588, 603, 622, 629, 480, 301, + 302, 444, 445, 314, 315, 643, 644, 300, 598, 630, + 596, 642, 624, 438, 378, 0, 0, 381, 281, 305, + 320, 0, 614, 502, 227, 466, 290, 251, 0, 0, + 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, + 434, 296, 271, 244, 459, 241, 485, 519, 520, 521, + 523, 395, 266, 433, 396, 0, 376, 576, 577, 316, + 0, 0, 0, 528, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, + 0, 0, 0, 270, 0, 0, 0, 0, 366, 267, + 0, 1909, 204, 505, 0, 430, 0, 203, 0, 487, + 252, 377, 374, 583, 282, 273, 269, 250, 317, 385, + 428, 518, 422, 0, 370, 0, 0, 497, 401, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 323, 248, 325, + 202, 413, 498, 286, 0, 0, 0, 0, 0, 507, + 720, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 245, 0, 0, 0, 351, 360, 359, + 339, 340, 342, 344, 350, 357, 363, 336, 345, 0, + 0, 607, 0, 0, 0, 265, 321, 272, 264, 580, + 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 297, 0, 402, 257, 0, + 453, 0, 0, 0, 626, 0, 0, 0, 0, 0, + 0, 0, 365, 0, 330, 197, 225, 0, 0, 412, + 461, 473, 0, 0, 0, 253, 0, 471, 426, 602, + 233, 284, 458, 432, 469, 440, 287, 0, 0, 470, + 372, 585, 450, 599, 627, 628, 263, 406, 612, 522, + 620, 645, 226, 260, 420, 506, 605, 494, 397, 581, + 582, 329, 493, 295, 201, 369, 633, 224, 479, 371, + 242, 231, 587, 609, 299, 289, 456, 640, 213, 517, + 597, 239, 483, 0, 0, 648, 247, 504, 215, 594, + 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, + 0, 258, 415, 589, 590, 256, 649, 228, 619, 220, + 0, 618, 408, 584, 595, 394, 383, 219, 593, 392, + 382, 334, 355, 356, 280, 307, 447, 375, 448, 306, + 308, 404, 403, 405, 207, 606, 623, 0, 208, 0, + 499, 608, 650, 452, 212, 234, 235, 237, 0, 279, + 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, + 451, 0, 579, 600, 613, 625, 631, 632, 634, 635, + 636, 637, 638, 641, 639, 407, 311, 495, 333, 373, + 0, 0, 425, 472, 240, 604, 496, 199, 0, 0, + 0, 0, 254, 255, 0, 575, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 651, 652, 653, 654, 655, + 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, + 666, 667, 668, 646, 508, 514, 509, 510, 511, 512, + 513, 0, 515, 0, 0, 0, 0, 0, 398, 0, + 591, 592, 669, 384, 486, 601, 335, 349, 352, 341, + 361, 0, 362, 337, 338, 343, 346, 347, 348, 353, + 354, 358, 364, 249, 210, 390, 399, 578, 312, 216, + 217, 218, 524, 525, 526, 527, 616, 617, 621, 205, + 462, 463, 464, 465, 292, 611, 309, 468, 467, 331, + 332, 379, 449, 540, 542, 553, 557, 559, 561, 567, + 570, 541, 543, 554, 558, 560, 562, 568, 571, 530, + 532, 534, 536, 549, 548, 545, 573, 574, 551, 556, + 535, 547, 552, 565, 572, 569, 529, 533, 537, 546, + 564, 563, 544, 555, 566, 550, 538, 531, 539, 0, + 196, 221, 368, 0, 454, 288, 647, 615, 484, 610, + 206, 223, 0, 262, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 198, 200, 209, 222, 232, + 236, 243, 261, 276, 278, 285, 298, 310, 318, 319, + 322, 328, 380, 386, 387, 388, 389, 409, 410, 411, + 414, 417, 418, 421, 423, 424, 427, 431, 435, 436, + 437, 439, 441, 443, 455, 460, 474, 475, 476, 477, + 478, 481, 482, 488, 489, 490, 491, 492, 500, 501, + 516, 586, 588, 603, 622, 629, 480, 301, 302, 444, + 445, 314, 315, 643, 644, 300, 598, 630, 596, 642, + 624, 438, 378, 0, 0, 381, 281, 305, 320, 0, + 614, 502, 227, 466, 290, 251, 0, 0, 211, 246, + 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, + 271, 244, 459, 241, 485, 519, 520, 521, 523, 395, + 266, 433, 396, 0, 376, 576, 577, 316, 0, 0, + 0, 528, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 270, 0, 0, 0, 0, 366, 267, 0, 1907, + 204, 505, 0, 430, 0, 203, 0, 487, 252, 377, + 374, 583, 282, 273, 269, 250, 317, 385, 428, 518, + 422, 0, 370, 0, 0, 497, 401, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 323, 248, 325, 202, 413, + 498, 286, 0, 0, 0, 0, 0, 507, 720, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 238, 0, + 0, 245, 0, 0, 0, 351, 360, 359, 339, 340, + 342, 344, 350, 357, 363, 336, 345, 0, 0, 607, + 0, 0, 0, 265, 321, 272, 264, 580, 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, @@ -7099,69 +6459,365 @@ 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, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, + 0, 0, 0, 297, 0, 402, 257, 0, 453, 0, + 0, 0, 626, 0, 0, 0, 0, 0, 0, 0, + 365, 0, 330, 197, 225, 0, 0, 412, 461, 473, + 0, 0, 0, 253, 0, 471, 426, 602, 233, 284, + 458, 432, 469, 440, 287, 0, 0, 470, 372, 585, + 450, 599, 627, 628, 263, 406, 612, 522, 620, 645, + 226, 260, 420, 506, 605, 494, 397, 581, 582, 329, + 493, 295, 201, 369, 633, 224, 479, 371, 242, 231, + 587, 609, 299, 289, 456, 640, 213, 517, 597, 239, + 483, 0, 0, 648, 247, 504, 215, 594, 503, 393, + 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, + 415, 589, 590, 256, 649, 228, 619, 220, 0, 618, + 408, 584, 595, 394, 383, 219, 593, 392, 382, 334, + 355, 356, 280, 307, 447, 375, 448, 306, 308, 404, + 403, 405, 207, 606, 623, 0, 208, 0, 499, 608, + 650, 452, 212, 234, 235, 237, 0, 279, 283, 291, + 294, 303, 304, 313, 367, 419, 446, 442, 451, 0, + 579, 600, 613, 625, 631, 632, 634, 635, 636, 637, + 638, 641, 639, 407, 311, 495, 333, 373, 0, 0, + 425, 472, 240, 604, 496, 199, 0, 0, 0, 0, + 254, 255, 0, 575, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 651, 652, 653, 654, 655, 656, 657, + 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, + 668, 646, 508, 514, 509, 510, 511, 512, 513, 0, + 515, 0, 0, 0, 0, 0, 398, 0, 591, 592, + 669, 384, 486, 601, 335, 349, 352, 341, 361, 0, + 362, 337, 338, 343, 346, 347, 348, 353, 354, 358, + 364, 249, 210, 390, 399, 578, 312, 216, 217, 218, + 524, 525, 526, 527, 616, 617, 621, 205, 462, 463, + 464, 465, 292, 611, 309, 468, 467, 331, 332, 379, + 449, 540, 542, 553, 557, 559, 561, 567, 570, 541, + 543, 554, 558, 560, 562, 568, 571, 530, 532, 534, + 536, 549, 548, 545, 573, 574, 551, 556, 535, 547, + 552, 565, 572, 569, 529, 533, 537, 546, 564, 563, + 544, 555, 566, 550, 538, 531, 539, 0, 196, 221, + 368, 0, 454, 288, 647, 615, 484, 610, 206, 223, + 0, 262, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 198, 200, 209, 222, 232, 236, 243, + 261, 276, 278, 285, 298, 310, 318, 319, 322, 328, + 380, 386, 387, 388, 389, 409, 410, 411, 414, 417, + 418, 421, 423, 424, 427, 431, 435, 436, 437, 439, + 441, 443, 455, 460, 474, 475, 476, 477, 478, 481, + 482, 488, 489, 490, 491, 492, 500, 501, 516, 586, + 588, 603, 622, 629, 480, 301, 302, 444, 445, 314, + 315, 643, 644, 300, 598, 630, 596, 642, 624, 438, + 378, 0, 0, 381, 281, 305, 320, 0, 614, 502, + 227, 466, 290, 251, 0, 0, 211, 246, 230, 259, + 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, + 459, 241, 485, 519, 520, 521, 523, 395, 266, 433, + 396, 0, 376, 576, 577, 316, 0, 0, 0, 528, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 416, 0, 0, 0, 0, 0, 0, 0, 270, + 0, 0, 0, 0, 366, 267, 0, 1905, 204, 505, + 0, 430, 0, 203, 0, 487, 252, 377, 374, 583, + 282, 273, 269, 250, 317, 385, 428, 518, 422, 0, + 370, 0, 0, 497, 401, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 323, 248, 325, 202, 413, 498, 286, + 0, 0, 0, 0, 0, 507, 720, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 238, 0, 0, 245, + 0, 0, 0, 351, 360, 359, 339, 340, 342, 344, + 350, 357, 363, 336, 345, 0, 0, 607, 0, 0, + 0, 265, 321, 272, 264, 580, 0, 0, 0, 0, + 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 297, 0, 402, 257, 0, 453, 0, 0, 0, + 626, 0, 0, 0, 0, 0, 0, 0, 365, 0, + 330, 197, 225, 0, 0, 412, 461, 473, 0, 0, + 0, 253, 0, 471, 426, 602, 233, 284, 458, 432, + 469, 440, 287, 0, 0, 470, 372, 585, 450, 599, + 627, 628, 263, 406, 612, 522, 620, 645, 226, 260, + 420, 506, 605, 494, 397, 581, 582, 329, 493, 295, + 201, 369, 633, 224, 479, 371, 242, 231, 587, 609, + 299, 289, 456, 640, 213, 517, 597, 239, 483, 0, + 0, 648, 247, 504, 215, 594, 503, 393, 326, 327, + 214, 0, 457, 268, 293, 0, 0, 258, 415, 589, + 590, 256, 649, 228, 619, 220, 0, 618, 408, 584, + 595, 394, 383, 219, 593, 392, 382, 334, 355, 356, + 280, 307, 447, 375, 448, 306, 308, 404, 403, 405, + 207, 606, 623, 0, 208, 0, 499, 608, 650, 452, + 212, 234, 235, 237, 0, 279, 283, 291, 294, 303, + 304, 313, 367, 419, 446, 442, 451, 0, 579, 600, + 613, 625, 631, 632, 634, 635, 636, 637, 638, 641, + 639, 407, 311, 495, 333, 373, 0, 0, 425, 472, + 240, 604, 496, 199, 0, 0, 0, 0, 254, 255, + 0, 575, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 651, 652, 653, 654, 655, 656, 657, 658, 659, + 660, 661, 662, 663, 664, 665, 666, 667, 668, 646, + 508, 514, 509, 510, 511, 512, 513, 0, 515, 0, + 0, 0, 0, 0, 398, 0, 591, 592, 669, 384, + 486, 601, 335, 349, 352, 341, 361, 0, 362, 337, + 338, 343, 346, 347, 348, 353, 354, 358, 364, 249, + 210, 390, 399, 578, 312, 216, 217, 218, 524, 525, + 526, 527, 616, 617, 621, 205, 462, 463, 464, 465, + 292, 611, 309, 468, 467, 331, 332, 379, 449, 540, + 542, 553, 557, 559, 561, 567, 570, 541, 543, 554, + 558, 560, 562, 568, 571, 530, 532, 534, 536, 549, + 548, 545, 573, 574, 551, 556, 535, 547, 552, 565, + 572, 569, 529, 533, 537, 546, 564, 563, 544, 555, + 566, 550, 538, 531, 539, 0, 196, 221, 368, 0, + 454, 288, 647, 615, 484, 610, 206, 223, 0, 262, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 198, 200, 209, 222, 232, 236, 243, 261, 276, + 278, 285, 298, 310, 318, 319, 322, 328, 380, 386, + 387, 388, 389, 409, 410, 411, 414, 417, 418, 421, + 423, 424, 427, 431, 435, 436, 437, 439, 441, 443, + 455, 460, 474, 475, 476, 477, 478, 481, 482, 488, + 489, 490, 491, 492, 500, 501, 516, 586, 588, 603, + 622, 629, 480, 301, 302, 444, 445, 314, 315, 643, + 644, 300, 598, 630, 596, 642, 624, 438, 378, 0, + 0, 381, 281, 305, 320, 0, 614, 502, 227, 466, + 290, 251, 0, 0, 211, 246, 230, 259, 274, 277, + 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, + 485, 519, 520, 521, 523, 395, 266, 433, 396, 0, + 376, 576, 577, 316, 0, 0, 0, 528, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 948, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, + 0, 0, 366, 267, 0, 0, 204, 505, 0, 430, + 0, 203, 0, 487, 252, 377, 374, 583, 282, 273, + 269, 250, 317, 385, 428, 518, 422, 0, 370, 0, + 0, 497, 401, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 323, 248, 325, 202, 413, 498, 286, 0, 1880, + 0, 0, 0, 507, 720, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 238, 0, 0, 245, 0, 0, + 0, 351, 360, 359, 339, 340, 342, 344, 350, 357, + 363, 336, 345, 0, 0, 607, 0, 0, 0, 265, + 321, 272, 264, 580, 0, 0, 0, 0, 0, 0, + 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 275, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 297, + 0, 402, 257, 0, 453, 0, 0, 0, 626, 0, + 0, 0, 0, 0, 0, 0, 365, 0, 330, 197, + 225, 0, 0, 412, 461, 473, 0, 0, 0, 253, + 0, 471, 426, 602, 233, 284, 458, 432, 469, 440, + 287, 0, 0, 470, 372, 585, 450, 599, 627, 628, + 263, 406, 612, 522, 620, 645, 226, 260, 420, 506, + 605, 494, 397, 581, 582, 329, 493, 295, 201, 369, + 633, 224, 479, 371, 242, 231, 587, 609, 299, 289, + 456, 640, 213, 517, 597, 239, 483, 0, 0, 648, + 247, 504, 215, 594, 503, 393, 326, 327, 214, 0, + 457, 268, 293, 0, 0, 258, 415, 589, 590, 256, + 649, 228, 619, 220, 0, 618, 408, 584, 595, 394, + 383, 219, 593, 392, 382, 334, 355, 356, 280, 307, + 447, 375, 448, 306, 308, 404, 403, 405, 207, 606, + 623, 0, 208, 0, 499, 608, 650, 452, 212, 234, + 235, 237, 0, 279, 283, 291, 294, 303, 304, 313, + 367, 419, 446, 442, 451, 0, 579, 600, 613, 625, + 631, 632, 634, 635, 636, 637, 638, 641, 639, 407, + 311, 495, 333, 373, 0, 0, 425, 472, 240, 604, + 496, 199, 0, 0, 0, 0, 254, 255, 0, 575, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 651, + 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, + 662, 663, 664, 665, 666, 667, 668, 646, 508, 514, + 509, 510, 511, 512, 513, 0, 515, 0, 0, 0, + 0, 0, 398, 0, 591, 592, 669, 384, 486, 601, + 335, 349, 352, 341, 361, 0, 362, 337, 338, 343, + 346, 347, 348, 353, 354, 358, 364, 249, 210, 390, + 399, 578, 312, 216, 217, 218, 524, 525, 526, 527, + 616, 617, 621, 205, 462, 463, 464, 465, 292, 611, + 309, 468, 467, 331, 332, 379, 449, 540, 542, 553, + 557, 559, 561, 567, 570, 541, 543, 554, 558, 560, + 562, 568, 571, 530, 532, 534, 536, 549, 548, 545, + 573, 574, 551, 556, 535, 547, 552, 565, 572, 569, + 529, 533, 537, 546, 564, 563, 544, 555, 566, 550, + 538, 531, 539, 0, 196, 221, 368, 0, 454, 288, + 647, 615, 484, 610, 206, 223, 0, 262, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, + 200, 209, 222, 232, 236, 243, 261, 276, 278, 285, + 298, 310, 318, 319, 322, 328, 380, 386, 387, 388, + 389, 409, 410, 411, 414, 417, 418, 421, 423, 424, + 427, 431, 435, 436, 437, 439, 441, 443, 455, 460, + 474, 475, 476, 477, 478, 481, 482, 488, 489, 490, + 491, 492, 500, 501, 516, 586, 588, 603, 622, 629, + 480, 301, 302, 444, 445, 314, 315, 643, 644, 300, + 598, 630, 596, 642, 624, 438, 378, 0, 0, 381, + 281, 305, 320, 0, 614, 502, 227, 466, 290, 251, + 0, 0, 211, 246, 230, 259, 274, 277, 324, 391, + 400, 429, 434, 296, 271, 244, 459, 241, 485, 519, + 520, 521, 523, 395, 266, 433, 396, 0, 376, 576, + 577, 316, 0, 0, 0, 528, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, + 0, 0, 0, 0, 1778, 270, 0, 0, 0, 0, + 366, 267, 0, 0, 204, 505, 0, 430, 0, 203, + 0, 487, 252, 377, 374, 583, 282, 273, 269, 250, + 317, 385, 428, 518, 422, 0, 370, 0, 0, 497, + 401, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 323, + 248, 325, 202, 413, 498, 286, 0, 0, 0, 0, + 0, 507, 194, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 238, 0, 0, 245, 0, 0, 0, 351, + 360, 359, 339, 340, 342, 344, 350, 357, 363, 336, + 345, 0, 0, 607, 0, 0, 0, 265, 321, 272, + 264, 580, 0, 0, 0, 0, 0, 0, 0, 0, + 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 275, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 297, 0, 402, + 257, 0, 453, 0, 0, 0, 626, 0, 0, 0, + 0, 0, 0, 0, 365, 0, 330, 197, 225, 0, + 0, 412, 461, 473, 0, 0, 0, 253, 0, 471, + 426, 602, 233, 284, 458, 432, 469, 440, 287, 0, + 0, 470, 372, 585, 450, 599, 627, 628, 263, 406, + 612, 522, 620, 645, 226, 260, 420, 506, 605, 494, + 397, 581, 582, 329, 493, 295, 201, 369, 633, 224, + 479, 371, 242, 231, 587, 609, 299, 289, 456, 640, + 213, 517, 597, 239, 483, 0, 0, 648, 247, 504, + 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, + 293, 0, 0, 258, 415, 589, 590, 256, 649, 228, + 619, 220, 0, 618, 408, 584, 595, 394, 383, 219, + 593, 392, 382, 334, 355, 356, 280, 307, 447, 375, + 448, 306, 308, 404, 403, 405, 207, 606, 623, 0, + 208, 0, 499, 608, 650, 452, 212, 234, 235, 237, + 0, 279, 283, 291, 294, 303, 304, 313, 367, 419, + 446, 442, 451, 0, 579, 600, 613, 625, 631, 632, + 634, 635, 636, 637, 638, 641, 639, 407, 311, 495, + 333, 373, 0, 0, 425, 472, 240, 604, 496, 199, + 0, 0, 0, 0, 254, 255, 0, 575, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 651, 652, 653, + 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, + 664, 665, 666, 667, 668, 646, 508, 514, 509, 510, + 511, 512, 513, 0, 515, 0, 0, 0, 0, 0, + 398, 0, 591, 592, 669, 384, 486, 601, 335, 349, + 352, 341, 361, 0, 362, 337, 338, 343, 346, 347, + 348, 353, 354, 358, 364, 249, 210, 390, 399, 578, + 312, 216, 217, 218, 524, 525, 526, 527, 616, 617, + 621, 205, 462, 463, 464, 465, 292, 611, 309, 468, + 467, 331, 332, 379, 449, 540, 542, 553, 557, 559, + 561, 567, 570, 541, 543, 554, 558, 560, 562, 568, + 571, 530, 532, 534, 536, 549, 548, 545, 573, 574, + 551, 556, 535, 547, 552, 565, 572, 569, 529, 533, + 537, 546, 564, 563, 544, 555, 566, 550, 538, 531, + 539, 0, 196, 221, 368, 0, 454, 288, 647, 615, + 484, 610, 206, 223, 0, 262, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 198, 200, 209, + 222, 232, 236, 243, 261, 276, 278, 285, 298, 310, + 318, 319, 322, 328, 380, 386, 387, 388, 389, 409, + 410, 411, 414, 417, 418, 421, 423, 424, 427, 431, + 435, 436, 437, 439, 441, 443, 455, 460, 474, 475, + 476, 477, 478, 481, 482, 488, 489, 490, 491, 492, + 500, 501, 516, 586, 588, 603, 622, 629, 480, 301, + 302, 444, 445, 314, 315, 643, 644, 300, 598, 630, + 596, 642, 624, 438, 378, 0, 0, 381, 281, 305, + 320, 0, 614, 502, 227, 466, 290, 251, 0, 0, + 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, + 434, 296, 271, 244, 459, 241, 485, 519, 520, 521, + 523, 395, 266, 433, 396, 0, 376, 576, 577, 316, + 0, 0, 0, 528, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, + 0, 0, 0, 270, 0, 0, 0, 0, 366, 267, + 0, 0, 204, 505, 0, 430, 0, 203, 0, 487, + 252, 377, 374, 583, 282, 273, 269, 250, 317, 385, + 428, 518, 422, 0, 370, 0, 0, 497, 401, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 323, 248, 325, + 202, 413, 498, 286, 0, 95, 0, 0, 0, 507, + 955, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 245, 0, 0, 0, 351, 360, 359, + 339, 340, 342, 344, 350, 357, 363, 336, 345, 0, + 0, 607, 0, 0, 0, 265, 321, 272, 264, 580, + 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 297, 0, 402, 257, 0, + 453, 0, 0, 0, 626, 0, 0, 0, 0, 0, + 0, 0, 365, 0, 330, 197, 225, 0, 0, 412, + 461, 473, 0, 0, 0, 253, 0, 471, 426, 602, + 233, 284, 458, 432, 469, 440, 287, 0, 0, 470, + 372, 585, 450, 599, 627, 628, 263, 406, 612, 522, + 620, 645, 226, 260, 420, 506, 605, 494, 397, 581, + 582, 329, 493, 295, 201, 369, 633, 224, 479, 371, + 242, 231, 587, 609, 299, 289, 456, 640, 213, 517, + 597, 239, 483, 0, 0, 648, 247, 504, 215, 594, + 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, + 0, 258, 415, 589, 590, 256, 649, 228, 619, 220, + 0, 618, 408, 584, 595, 394, 383, 219, 593, 392, + 382, 334, 355, 356, 280, 307, 447, 375, 448, 306, + 308, 404, 403, 405, 207, 606, 623, 0, 208, 0, + 499, 608, 650, 452, 212, 234, 235, 237, 0, 279, + 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, + 451, 0, 579, 600, 613, 625, 631, 632, 634, 635, + 636, 637, 638, 641, 639, 407, 311, 495, 333, 373, + 0, 0, 425, 472, 240, 604, 496, 199, 0, 0, + 0, 0, 254, 255, 0, 575, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 651, 652, 653, 654, 655, + 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, + 666, 667, 668, 646, 508, 514, 509, 510, 511, 512, + 513, 0, 515, 0, 0, 0, 0, 0, 398, 0, + 591, 592, 669, 384, 486, 601, 335, 349, 352, 341, + 361, 0, 362, 337, 338, 343, 346, 347, 348, 353, + 354, 358, 364, 249, 210, 390, 399, 578, 312, 216, + 217, 218, 524, 525, 526, 527, 616, 617, 621, 205, + 462, 463, 464, 465, 292, 611, 309, 468, 467, 331, + 332, 379, 449, 540, 542, 553, 557, 559, 561, 567, + 570, 541, 543, 554, 558, 560, 562, 568, 571, 530, + 532, 534, 536, 549, 548, 545, 573, 574, 551, 556, + 535, 547, 552, 565, 572, 569, 529, 533, 537, 546, + 564, 563, 544, 555, 566, 550, 538, 531, 539, 0, + 196, 221, 368, 0, 454, 288, 647, 615, 484, 610, + 206, 223, 0, 262, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 198, 200, 209, 222, 232, + 236, 243, 261, 276, 278, 285, 298, 310, 318, 319, + 322, 328, 380, 386, 387, 388, 389, 409, 410, 411, + 414, 417, 418, 421, 423, 424, 427, 431, 435, 436, + 437, 439, 441, 443, 455, 460, 474, 475, 476, 477, + 478, 481, 482, 488, 489, 490, 491, 492, 500, 501, + 516, 586, 588, 603, 622, 629, 480, 301, 302, 444, + 445, 314, 315, 643, 644, 300, 598, 630, 596, 642, + 624, 438, 378, 0, 0, 381, 281, 305, 320, 0, + 614, 502, 227, 466, 290, 251, 0, 0, 211, 246, + 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, + 271, 244, 459, 241, 485, 519, 520, 521, 523, 395, + 266, 433, 396, 0, 376, 576, 577, 316, 0, 0, + 0, 528, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 270, 0, 0, 0, 0, 366, 267, 0, 0, + 204, 505, 0, 430, 0, 203, 0, 487, 252, 377, + 374, 583, 282, 273, 269, 250, 317, 385, 428, 518, + 422, 0, 370, 0, 0, 497, 401, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 323, 248, 325, 202, 413, + 498, 286, 0, 0, 0, 0, 0, 507, 194, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 238, 0, + 0, 245, 0, 0, 0, 351, 360, 359, 339, 340, + 342, 344, 350, 357, 363, 336, 345, 0, 0, 607, + 0, 0, 0, 265, 321, 272, 264, 580, 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, @@ -7172,69 +6828,365 @@ 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, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 394, - 0, 374, 573, 574, 316, 0, 0, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 414, + 0, 1451, 0, 297, 0, 402, 257, 0, 453, 0, + 0, 0, 626, 0, 0, 0, 0, 0, 0, 0, + 365, 0, 330, 197, 225, 0, 0, 412, 461, 473, + 0, 0, 0, 253, 0, 471, 426, 602, 233, 284, + 458, 432, 469, 440, 287, 0, 0, 470, 372, 585, + 450, 599, 627, 628, 263, 406, 612, 522, 620, 645, + 226, 260, 420, 506, 605, 494, 397, 581, 582, 329, + 493, 295, 201, 369, 633, 224, 479, 371, 242, 231, + 587, 609, 299, 289, 456, 640, 213, 517, 597, 239, + 483, 0, 0, 648, 247, 504, 215, 594, 503, 393, + 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, + 415, 589, 590, 256, 649, 228, 619, 220, 0, 618, + 408, 584, 595, 394, 383, 219, 593, 392, 382, 334, + 355, 356, 280, 307, 447, 375, 448, 306, 308, 404, + 403, 405, 207, 606, 623, 0, 208, 0, 499, 608, + 650, 452, 212, 234, 235, 237, 0, 279, 283, 291, + 294, 303, 304, 313, 367, 419, 446, 442, 451, 0, + 579, 600, 613, 625, 631, 632, 634, 635, 636, 637, + 638, 641, 639, 407, 311, 495, 333, 373, 0, 0, + 425, 472, 240, 604, 496, 199, 0, 0, 0, 0, + 254, 255, 0, 575, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 651, 652, 653, 654, 655, 656, 657, + 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, + 668, 646, 508, 514, 509, 510, 511, 512, 513, 0, + 515, 0, 0, 0, 0, 0, 398, 0, 591, 592, + 669, 384, 486, 601, 335, 349, 352, 341, 361, 0, + 362, 337, 338, 343, 346, 347, 348, 353, 354, 358, + 364, 249, 210, 390, 399, 578, 312, 216, 217, 218, + 524, 525, 526, 527, 616, 617, 621, 205, 462, 463, + 464, 465, 292, 611, 309, 468, 467, 331, 332, 379, + 449, 540, 542, 553, 557, 559, 561, 567, 570, 541, + 543, 554, 558, 560, 562, 568, 571, 530, 532, 534, + 536, 549, 548, 545, 573, 574, 551, 556, 535, 547, + 552, 565, 572, 569, 529, 533, 537, 546, 564, 563, + 544, 555, 566, 550, 538, 531, 539, 0, 196, 221, + 368, 0, 454, 288, 647, 615, 484, 610, 206, 223, + 0, 262, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 198, 200, 209, 222, 232, 236, 243, + 261, 276, 278, 285, 298, 310, 318, 319, 322, 328, + 380, 386, 387, 388, 389, 409, 410, 411, 414, 417, + 418, 421, 423, 424, 427, 431, 435, 436, 437, 439, + 441, 443, 455, 460, 474, 475, 476, 477, 478, 481, + 482, 488, 489, 490, 491, 492, 500, 501, 516, 586, + 588, 603, 622, 629, 480, 301, 302, 444, 445, 314, + 315, 643, 644, 1450, 598, 630, 596, 642, 624, 438, + 378, 0, 0, 381, 281, 305, 320, 0, 614, 502, + 227, 466, 290, 251, 0, 0, 211, 246, 230, 259, + 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, + 459, 241, 485, 519, 520, 521, 523, 395, 266, 433, + 396, 0, 376, 576, 577, 316, 0, 0, 0, 528, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 416, 0, 0, 0, 0, 0, 0, 0, 270, + 0, 0, 0, 0, 366, 267, 0, 0, 204, 505, + 0, 430, 0, 203, 0, 487, 252, 377, 374, 583, + 282, 273, 269, 250, 317, 385, 428, 518, 422, 0, + 370, 0, 0, 497, 401, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 323, 248, 325, 202, 413, 498, 286, + 0, 0, 0, 0, 0, 507, 194, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 238, 0, 0, 245, + 0, 0, 0, 351, 360, 359, 339, 340, 342, 344, + 350, 357, 363, 336, 345, 0, 0, 607, 0, 0, + 0, 265, 321, 272, 264, 580, 0, 0, 0, 0, + 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 297, 0, 402, 257, 0, 453, 0, 0, 0, + 626, 0, 0, 0, 0, 0, 0, 0, 365, 0, + 330, 197, 225, 0, 0, 412, 461, 473, 0, 0, + 0, 253, 0, 471, 426, 602, 233, 284, 458, 432, + 469, 440, 287, 0, 0, 470, 372, 585, 450, 599, + 627, 628, 263, 406, 612, 522, 620, 645, 226, 260, + 420, 506, 605, 494, 397, 581, 582, 329, 493, 295, + 201, 369, 633, 224, 479, 371, 242, 231, 587, 609, + 299, 289, 456, 640, 213, 517, 597, 239, 483, 0, + 0, 648, 247, 504, 215, 594, 503, 393, 326, 327, + 214, 0, 457, 268, 293, 0, 0, 258, 415, 589, + 590, 256, 649, 228, 619, 220, 0, 618, 408, 584, + 595, 394, 383, 219, 593, 392, 382, 334, 355, 356, + 280, 307, 447, 375, 448, 306, 308, 404, 403, 405, + 207, 606, 623, 0, 208, 0, 499, 608, 650, 452, + 212, 234, 235, 237, 0, 279, 283, 291, 294, 303, + 304, 313, 367, 419, 446, 442, 451, 0, 579, 600, + 613, 625, 631, 632, 634, 635, 636, 637, 638, 641, + 639, 407, 311, 495, 333, 373, 0, 0, 425, 472, + 240, 604, 496, 199, 0, 0, 0, 0, 254, 255, + 0, 575, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 651, 652, 653, 654, 655, 656, 657, 658, 659, + 660, 661, 662, 663, 664, 665, 666, 667, 668, 646, + 508, 514, 509, 510, 511, 512, 513, 0, 515, 0, + 0, 0, 0, 0, 398, 0, 591, 592, 669, 384, + 486, 601, 335, 349, 352, 341, 361, 0, 362, 337, + 338, 343, 346, 347, 348, 353, 354, 358, 364, 249, + 210, 390, 399, 578, 312, 216, 217, 218, 524, 525, + 526, 527, 616, 617, 621, 205, 462, 463, 464, 465, + 292, 611, 309, 468, 467, 331, 332, 379, 449, 540, + 542, 553, 557, 559, 561, 567, 570, 541, 543, 554, + 558, 560, 562, 568, 571, 530, 532, 534, 536, 549, + 548, 545, 573, 574, 551, 556, 535, 547, 552, 565, + 572, 569, 529, 533, 537, 546, 564, 563, 544, 555, + 566, 550, 538, 531, 539, 0, 196, 221, 368, 0, + 454, 288, 647, 615, 484, 610, 206, 223, 0, 262, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1045, 0, 0, + 0, 198, 200, 209, 222, 232, 236, 243, 261, 276, + 278, 285, 298, 310, 318, 319, 322, 328, 380, 386, + 387, 388, 389, 409, 410, 411, 414, 417, 418, 421, + 423, 424, 427, 431, 435, 436, 437, 439, 441, 443, + 455, 460, 474, 475, 476, 477, 478, 481, 482, 488, + 489, 490, 491, 492, 500, 501, 516, 586, 588, 603, + 622, 629, 480, 301, 302, 444, 445, 314, 315, 643, + 644, 300, 598, 630, 596, 642, 624, 438, 378, 0, + 0, 381, 281, 305, 320, 0, 614, 502, 227, 466, + 290, 251, 0, 0, 211, 246, 230, 259, 274, 277, + 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, + 485, 519, 520, 521, 523, 395, 266, 433, 396, 0, + 376, 576, 577, 316, 0, 0, 0, 528, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, - 0, 0, 364, 267, 0, 0, 204, 503, 0, 428, - 0, 203, 0, 485, 252, 375, 372, 580, 282, 273, - 269, 250, 317, 383, 426, 515, 420, 0, 368, 0, - 0, 495, 399, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 323, 248, - 325, 202, 411, 496, 286, 0, 0, 0, 0, 0, - 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 238, 0, 0, 245, 0, 0, 0, 349, 358, 357, - 338, 339, 341, 343, 348, 355, 361, 0, 0, 604, - 0, 0, 0, 265, 321, 272, 264, 577, 0, 0, + 0, 0, 366, 267, 0, 0, 204, 505, 0, 430, + 0, 203, 0, 487, 252, 377, 374, 583, 282, 273, + 269, 250, 317, 385, 428, 518, 422, 0, 370, 0, + 0, 497, 401, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 323, 248, 325, 202, 413, 498, 286, 0, 0, + 0, 0, 0, 507, 194, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 238, 0, 0, 245, 0, 0, + 0, 351, 360, 359, 339, 340, 342, 344, 350, 357, + 363, 336, 345, 0, 0, 607, 0, 0, 0, 265, + 321, 272, 264, 580, 0, 0, 0, 0, 0, 0, + 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 275, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 297, + 0, 402, 257, 0, 453, 0, 672, 0, 626, 0, + 0, 0, 0, 0, 0, 0, 365, 0, 330, 197, + 225, 0, 0, 412, 461, 473, 0, 0, 0, 253, + 0, 471, 426, 602, 233, 284, 458, 432, 469, 440, + 287, 0, 0, 470, 372, 585, 450, 599, 627, 628, + 263, 406, 612, 522, 620, 645, 226, 260, 420, 506, + 605, 494, 397, 581, 582, 329, 493, 295, 201, 369, + 633, 224, 479, 371, 242, 231, 587, 609, 299, 289, + 456, 640, 213, 517, 597, 239, 483, 0, 0, 648, + 247, 504, 215, 594, 503, 393, 326, 327, 214, 0, + 457, 268, 293, 0, 0, 258, 415, 589, 590, 256, + 649, 228, 619, 220, 0, 618, 408, 584, 595, 394, + 383, 219, 593, 392, 382, 334, 355, 356, 280, 307, + 447, 375, 448, 306, 308, 404, 403, 405, 207, 606, + 623, 0, 208, 0, 499, 608, 650, 452, 212, 234, + 235, 237, 0, 279, 283, 291, 294, 303, 304, 313, + 367, 419, 446, 442, 451, 0, 579, 600, 613, 625, + 631, 632, 634, 635, 636, 637, 638, 641, 639, 407, + 311, 495, 333, 373, 0, 0, 425, 472, 240, 604, + 496, 199, 0, 0, 0, 0, 254, 255, 0, 575, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 651, + 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, + 662, 663, 664, 665, 666, 667, 668, 646, 508, 514, + 509, 510, 511, 512, 513, 0, 515, 0, 0, 0, + 0, 0, 398, 0, 591, 592, 669, 384, 486, 601, + 335, 349, 352, 341, 361, 0, 362, 337, 338, 343, + 346, 347, 348, 353, 354, 358, 364, 249, 210, 390, + 399, 578, 312, 216, 217, 218, 524, 525, 526, 527, + 616, 617, 621, 205, 462, 463, 464, 465, 292, 611, + 309, 468, 467, 331, 332, 379, 449, 540, 542, 553, + 557, 559, 561, 567, 570, 541, 543, 554, 558, 560, + 562, 568, 571, 530, 532, 534, 536, 549, 548, 545, + 573, 574, 551, 556, 535, 547, 552, 565, 572, 569, + 529, 533, 537, 546, 564, 563, 544, 555, 566, 550, + 538, 531, 539, 0, 196, 221, 368, 0, 454, 288, + 647, 615, 484, 610, 206, 223, 0, 262, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, + 200, 209, 222, 232, 236, 243, 261, 276, 278, 285, + 298, 310, 318, 319, 322, 328, 380, 386, 387, 388, + 389, 409, 410, 411, 414, 417, 418, 421, 423, 424, + 427, 431, 435, 436, 437, 439, 441, 443, 455, 460, + 474, 475, 476, 477, 478, 481, 482, 488, 489, 490, + 491, 492, 500, 501, 516, 586, 588, 603, 622, 629, + 480, 301, 302, 444, 445, 314, 315, 643, 644, 300, + 598, 630, 596, 642, 624, 438, 378, 0, 0, 381, + 281, 305, 320, 0, 614, 502, 227, 466, 290, 251, + 0, 0, 211, 246, 230, 259, 274, 277, 324, 391, + 400, 429, 434, 296, 271, 244, 459, 241, 485, 519, + 520, 521, 523, 395, 266, 433, 396, 0, 376, 576, + 577, 316, 0, 0, 0, 528, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, + 0, 0, 0, 0, 0, 270, 0, 0, 0, 0, + 366, 267, 0, 0, 204, 505, 0, 430, 0, 203, + 0, 487, 252, 377, 374, 583, 282, 273, 269, 250, + 317, 385, 428, 518, 422, 0, 370, 0, 0, 497, + 401, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 323, + 248, 325, 202, 413, 498, 286, 0, 0, 0, 0, + 0, 507, 720, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 238, 0, 0, 245, 0, 0, 0, 351, + 360, 359, 339, 340, 342, 344, 350, 357, 363, 336, + 345, 0, 0, 607, 0, 0, 0, 265, 321, 272, + 264, 580, 0, 0, 0, 0, 0, 0, 0, 0, + 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 275, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 297, 0, 402, + 257, 0, 453, 0, 0, 0, 626, 0, 0, 0, + 0, 0, 0, 0, 365, 0, 330, 197, 225, 0, + 0, 412, 461, 473, 0, 0, 0, 253, 0, 471, + 426, 602, 233, 284, 458, 432, 469, 440, 287, 0, + 0, 470, 372, 585, 450, 599, 627, 628, 263, 406, + 612, 522, 620, 645, 226, 260, 420, 506, 605, 494, + 397, 581, 582, 329, 493, 295, 201, 369, 633, 224, + 479, 371, 242, 231, 587, 609, 299, 289, 456, 640, + 213, 517, 597, 239, 483, 0, 0, 648, 247, 504, + 215, 594, 503, 393, 326, 327, 214, 0, 457, 268, + 293, 0, 0, 258, 415, 589, 590, 256, 649, 228, + 619, 220, 0, 618, 408, 584, 595, 394, 383, 219, + 593, 392, 382, 334, 355, 356, 280, 307, 447, 375, + 448, 306, 308, 404, 403, 405, 207, 606, 623, 0, + 208, 0, 499, 608, 650, 452, 212, 234, 235, 237, + 0, 279, 283, 291, 294, 303, 304, 313, 367, 419, + 446, 442, 451, 0, 579, 600, 613, 625, 631, 632, + 634, 635, 636, 637, 638, 641, 639, 407, 311, 495, + 333, 373, 0, 0, 425, 472, 240, 604, 496, 199, + 0, 0, 0, 0, 254, 255, 0, 575, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 651, 652, 653, + 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, + 664, 665, 666, 667, 668, 646, 508, 514, 509, 510, + 511, 512, 513, 0, 515, 0, 0, 0, 0, 0, + 398, 0, 591, 592, 669, 384, 486, 601, 335, 349, + 352, 341, 361, 0, 362, 337, 338, 343, 346, 347, + 348, 353, 354, 358, 364, 249, 210, 390, 399, 578, + 312, 216, 217, 218, 524, 525, 526, 527, 616, 617, + 621, 205, 462, 463, 464, 465, 292, 611, 309, 468, + 467, 331, 332, 379, 449, 540, 542, 553, 557, 559, + 561, 567, 570, 541, 543, 554, 558, 560, 562, 568, + 571, 530, 532, 534, 536, 549, 548, 545, 573, 574, + 551, 556, 535, 547, 552, 565, 572, 569, 529, 533, + 537, 546, 564, 563, 544, 555, 566, 550, 538, 531, + 539, 0, 196, 221, 368, 0, 454, 288, 647, 615, + 484, 610, 206, 223, 0, 262, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 198, 200, 209, + 222, 232, 236, 243, 261, 276, 278, 285, 298, 310, + 318, 319, 322, 328, 380, 386, 387, 388, 389, 4129, + 410, 411, 414, 417, 418, 421, 423, 424, 427, 431, + 435, 436, 437, 439, 441, 443, 455, 460, 474, 475, + 476, 477, 478, 481, 482, 488, 489, 490, 491, 492, + 500, 501, 516, 586, 588, 603, 622, 629, 480, 301, + 302, 444, 445, 314, 315, 643, 644, 300, 598, 630, + 596, 642, 624, 438, 378, 0, 0, 381, 281, 305, + 320, 0, 614, 502, 227, 466, 290, 251, 0, 0, + 211, 246, 230, 259, 274, 277, 324, 391, 400, 429, + 434, 296, 271, 244, 459, 241, 485, 519, 520, 521, + 523, 395, 266, 433, 396, 0, 376, 576, 577, 316, + 0, 0, 0, 528, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, + 0, 0, 0, 270, 0, 0, 0, 0, 366, 267, + 0, 0, 204, 505, 0, 430, 0, 203, 0, 487, + 252, 377, 374, 583, 282, 273, 269, 250, 317, 385, + 428, 518, 422, 0, 370, 0, 0, 497, 401, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 323, 248, 325, + 202, 413, 498, 286, 0, 0, 0, 0, 0, 507, + 720, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 245, 0, 0, 0, 351, 360, 359, + 339, 340, 342, 344, 350, 357, 363, 336, 345, 0, + 0, 607, 0, 0, 0, 265, 321, 272, 264, 580, + 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 297, 0, 402, 257, 0, + 453, 0, 0, 0, 626, 0, 0, 0, 0, 0, + 0, 0, 365, 0, 330, 197, 225, 0, 0, 412, + 461, 473, 0, 0, 0, 253, 0, 471, 426, 602, + 233, 284, 458, 432, 469, 440, 287, 0, 0, 470, + 372, 585, 450, 599, 627, 628, 263, 406, 612, 522, + 620, 645, 226, 260, 420, 506, 605, 494, 397, 581, + 582, 329, 493, 295, 201, 369, 633, 224, 479, 371, + 242, 231, 587, 609, 299, 289, 456, 640, 213, 517, + 597, 239, 483, 0, 0, 648, 247, 504, 215, 594, + 503, 393, 326, 327, 214, 0, 457, 268, 293, 0, + 0, 258, 415, 589, 590, 256, 649, 228, 619, 220, + 0, 618, 408, 584, 595, 394, 383, 219, 593, 392, + 382, 334, 355, 356, 280, 307, 447, 375, 448, 306, + 308, 404, 403, 405, 207, 606, 623, 0, 208, 0, + 499, 608, 650, 452, 212, 234, 235, 237, 0, 279, + 283, 291, 294, 303, 304, 313, 367, 419, 446, 442, + 451, 0, 579, 600, 613, 625, 631, 632, 634, 635, + 636, 637, 638, 641, 639, 407, 311, 495, 333, 373, + 0, 0, 425, 472, 240, 604, 496, 199, 0, 0, + 0, 0, 254, 255, 0, 575, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 651, 652, 653, 654, 655, + 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, + 666, 667, 668, 646, 508, 514, 509, 510, 511, 512, + 513, 0, 515, 0, 0, 0, 0, 0, 398, 0, + 591, 592, 669, 384, 486, 601, 335, 349, 352, 341, + 361, 0, 362, 337, 338, 343, 346, 347, 348, 353, + 354, 358, 364, 249, 210, 390, 399, 578, 312, 216, + 217, 218, 524, 525, 526, 527, 616, 617, 621, 205, + 462, 463, 464, 465, 292, 611, 309, 468, 467, 331, + 332, 379, 449, 540, 542, 553, 557, 559, 561, 567, + 570, 541, 543, 554, 558, 560, 562, 568, 571, 530, + 532, 534, 536, 549, 548, 545, 573, 574, 551, 556, + 535, 547, 552, 565, 572, 569, 529, 533, 537, 546, + 564, 563, 544, 555, 566, 550, 538, 531, 539, 0, + 196, 221, 368, 0, 454, 288, 647, 615, 484, 610, + 206, 223, 0, 262, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 198, 200, 209, 222, 232, + 236, 243, 261, 276, 278, 285, 298, 310, 318, 319, + 322, 328, 380, 386, 387, 388, 389, 409, 410, 411, + 414, 417, 418, 421, 423, 424, 427, 431, 435, 436, + 437, 439, 441, 443, 455, 460, 474, 475, 476, 477, + 478, 481, 482, 488, 489, 490, 491, 492, 500, 501, + 516, 586, 588, 603, 622, 629, 480, 301, 302, 444, + 445, 314, 315, 643, 644, 300, 598, 630, 596, 642, + 624, 438, 378, 0, 0, 381, 281, 305, 320, 0, + 614, 502, 227, 466, 290, 251, 0, 0, 211, 246, + 230, 259, 274, 277, 324, 391, 400, 429, 434, 296, + 271, 244, 459, 241, 485, 519, 520, 521, 523, 395, + 266, 433, 396, 0, 376, 576, 577, 316, 0, 0, + 0, 528, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, + 0, 270, 0, 0, 0, 0, 366, 267, 0, 0, + 204, 505, 0, 430, 0, 203, 0, 487, 252, 377, + 374, 583, 282, 273, 269, 250, 317, 385, 428, 518, + 422, 0, 370, 0, 0, 497, 401, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 323, 248, 325, 202, 413, + 498, 286, 0, 0, 0, 0, 0, 507, 955, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 238, 0, + 0, 245, 0, 0, 0, 351, 360, 359, 339, 340, + 342, 344, 350, 357, 363, 336, 345, 0, 0, 607, + 0, 0, 0, 265, 321, 272, 264, 580, 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, @@ -7245,80 +7197,156 @@ 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, 297, 0, 400, 257, 0, 451, 0, - 0, 0, 622, 0, 0, 0, 0, 0, 0, 0, - 363, 0, 330, 197, 225, 0, 0, 410, 459, 471, - 0, 0, 0, 253, 0, 469, 424, 599, 233, 284, - 456, 430, 467, 438, 287, 0, 0, 468, 370, 582, - 448, 596, 623, 624, 263, 404, 609, 519, 617, 641, - 226, 260, 418, 504, 602, 492, 395, 578, 579, 329, - 491, 295, 201, 367, 629, 224, 477, 369, 242, 231, - 584, 606, 299, 289, 454, 636, 213, 514, 594, 239, - 481, 0, 0, 644, 247, 502, 215, 591, 501, 391, - 326, 327, 214, 0, 455, 268, 293, 0, 0, 258, - 413, 586, 587, 256, 645, 228, 616, 220, 0, 615, - 406, 581, 592, 392, 381, 219, 590, 390, 380, 334, - 353, 354, 280, 307, 445, 373, 446, 306, 308, 402, - 401, 403, 207, 603, 0, 208, 0, 497, 605, 646, - 450, 212, 234, 235, 237, 0, 279, 283, 291, 294, - 303, 304, 313, 365, 417, 444, 440, 449, 0, 576, - 597, 610, 621, 627, 628, 630, 631, 632, 633, 634, - 637, 635, 405, 311, 493, 333, 371, 0, 0, 423, - 470, 240, 601, 494, 199, 0, 0, 0, 0, 254, - 255, 0, 572, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 642, 505, 511, 506, 507, 508, 509, 510, 0, 512, - 0, 0, 0, 0, 0, 396, 0, 588, 589, 665, - 382, 484, 598, 335, 347, 350, 340, 359, 0, 360, - 336, 337, 342, 344, 345, 346, 351, 352, 356, 362, - 249, 210, 388, 397, 575, 312, 216, 217, 218, 521, - 522, 523, 524, 613, 614, 618, 205, 460, 461, 462, - 463, 292, 608, 309, 466, 465, 331, 332, 377, 447, - 537, 539, 550, 554, 556, 558, 564, 567, 538, 540, - 551, 555, 557, 559, 565, 568, 527, 529, 531, 533, - 546, 545, 542, 570, 571, 548, 553, 532, 544, 549, - 562, 569, 566, 526, 530, 534, 543, 561, 560, 541, - 552, 563, 547, 535, 528, 536, 0, 196, 221, 366, - 0, 452, 288, 643, 612, 482, 607, 206, 223, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 198, 200, 209, 222, 232, 236, 243, 261, - 276, 278, 285, 298, 310, 318, 319, 322, 328, 378, - 384, 385, 386, 387, 407, 408, 409, 412, 415, 416, - 419, 421, 422, 425, 429, 433, 434, 435, 437, 439, - 441, 453, 458, 472, 473, 474, 475, 476, 479, 480, - 486, 487, 488, 489, 490, 498, 499, 513, 583, 585, - 600, 619, 625, 478, 301, 302, 442, 443, 314, 315, - 639, 640, 300, 595, 626, 593, 638, 620, 436, 376, - 0, 0, 379, 281, 305, 320, 0, 611, 500, 227, - 464, 290, 251, 0, 0, 211, 246, 230, 259, 274, - 277, 324, 389, 398, 427, 432, 296, 271, 244, 457, - 241, 483, 516, 517, 518, 520, 393, 266, 431, 0, - 0, 374, 573, 574, 316, + 0, 0, 0, 297, 0, 402, 257, 0, 453, 0, + 0, 0, 626, 0, 0, 0, 0, 0, 0, 0, + 365, 0, 330, 197, 225, 0, 0, 412, 461, 473, + 0, 0, 0, 253, 0, 471, 426, 602, 233, 284, + 458, 432, 469, 440, 287, 0, 0, 470, 372, 585, + 450, 599, 627, 628, 263, 406, 612, 522, 620, 645, + 226, 260, 420, 506, 605, 494, 397, 581, 582, 329, + 493, 295, 201, 369, 633, 224, 479, 371, 242, 231, + 587, 609, 299, 289, 456, 640, 213, 517, 597, 239, + 483, 0, 0, 648, 247, 504, 215, 594, 503, 393, + 326, 327, 214, 0, 457, 268, 293, 0, 0, 258, + 415, 589, 590, 256, 649, 228, 619, 220, 0, 618, + 408, 584, 595, 394, 383, 219, 593, 392, 382, 334, + 355, 356, 280, 307, 447, 375, 448, 306, 308, 404, + 403, 405, 207, 606, 623, 0, 208, 0, 499, 608, + 650, 452, 212, 234, 235, 237, 0, 279, 283, 291, + 294, 303, 304, 313, 367, 419, 446, 442, 451, 0, + 579, 600, 613, 625, 631, 632, 634, 635, 636, 637, + 638, 641, 639, 407, 311, 495, 333, 373, 0, 0, + 425, 472, 240, 604, 496, 199, 0, 0, 0, 0, + 254, 255, 0, 575, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 651, 652, 653, 654, 655, 656, 657, + 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, + 668, 646, 508, 514, 509, 510, 511, 512, 513, 0, + 515, 0, 0, 0, 0, 0, 398, 0, 591, 592, + 669, 384, 486, 601, 335, 349, 352, 341, 361, 0, + 362, 337, 338, 343, 346, 347, 348, 353, 354, 358, + 364, 249, 210, 390, 399, 578, 312, 216, 217, 218, + 524, 525, 526, 527, 616, 617, 621, 205, 462, 463, + 464, 465, 292, 611, 309, 468, 467, 331, 332, 379, + 449, 540, 542, 553, 557, 559, 561, 567, 570, 541, + 543, 554, 558, 560, 562, 568, 571, 530, 532, 534, + 536, 549, 548, 545, 573, 574, 551, 556, 535, 547, + 552, 565, 572, 569, 529, 533, 537, 546, 564, 563, + 544, 555, 566, 550, 538, 531, 539, 0, 196, 221, + 368, 0, 454, 288, 647, 615, 484, 610, 206, 223, + 0, 262, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 198, 200, 209, 222, 232, 236, 243, + 261, 276, 278, 285, 298, 310, 318, 319, 322, 328, + 380, 386, 387, 388, 389, 409, 410, 411, 414, 417, + 418, 421, 423, 424, 427, 431, 435, 436, 437, 439, + 441, 443, 455, 460, 474, 475, 476, 477, 478, 481, + 482, 488, 489, 490, 491, 492, 500, 501, 516, 586, + 588, 603, 622, 629, 480, 301, 302, 444, 445, 314, + 315, 643, 644, 300, 598, 630, 596, 642, 624, 438, + 378, 0, 0, 381, 281, 305, 320, 0, 614, 502, + 227, 466, 290, 251, 0, 0, 211, 246, 230, 259, + 274, 277, 324, 391, 400, 429, 434, 296, 271, 244, + 459, 241, 485, 519, 520, 521, 523, 395, 266, 433, + 396, 0, 376, 576, 577, 316, 0, 0, 0, 528, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 416, 0, 0, 0, 0, 0, 0, 0, 270, + 0, 0, 0, 0, 366, 267, 0, 0, 204, 505, + 0, 430, 0, 203, 0, 487, 252, 377, 374, 583, + 282, 273, 269, 250, 317, 385, 428, 518, 422, 0, + 370, 0, 0, 497, 401, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 323, 248, 325, 202, 413, 498, 286, + 0, 0, 0, 0, 0, 507, 194, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 238, 0, 0, 245, + 0, 0, 0, 351, 360, 359, 339, 340, 342, 344, + 350, 357, 363, 336, 345, 0, 0, 607, 0, 0, + 0, 265, 321, 272, 264, 580, 0, 0, 0, 0, + 0, 0, 0, 0, 229, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 297, 0, 402, 257, 0, 453, 0, 0, 0, + 626, 0, 0, 0, 0, 0, 0, 0, 365, 0, + 330, 197, 225, 0, 0, 412, 461, 473, 0, 0, + 0, 253, 0, 471, 426, 602, 233, 284, 458, 432, + 469, 440, 287, 0, 0, 470, 372, 585, 450, 599, + 627, 628, 263, 406, 612, 522, 620, 645, 226, 260, + 420, 506, 605, 494, 397, 581, 582, 329, 493, 295, + 201, 369, 633, 224, 479, 371, 242, 231, 587, 609, + 299, 289, 456, 640, 213, 517, 597, 239, 483, 0, + 0, 648, 247, 504, 215, 594, 503, 393, 326, 327, + 214, 0, 457, 268, 293, 0, 0, 258, 415, 589, + 590, 256, 649, 228, 619, 220, 0, 618, 408, 584, + 595, 394, 383, 219, 593, 392, 382, 334, 355, 356, + 280, 307, 447, 375, 448, 306, 308, 404, 403, 405, + 207, 606, 623, 0, 208, 0, 499, 608, 650, 452, + 212, 234, 235, 237, 0, 279, 283, 291, 294, 303, + 304, 313, 367, 419, 446, 442, 451, 0, 579, 600, + 613, 625, 631, 632, 634, 635, 636, 637, 638, 641, + 639, 407, 311, 495, 333, 373, 0, 0, 425, 472, + 240, 604, 496, 199, 0, 0, 0, 0, 254, 255, + 0, 575, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 651, 652, 653, 654, 655, 656, 657, 658, 659, + 660, 661, 662, 663, 664, 665, 666, 667, 668, 646, + 508, 514, 509, 510, 511, 512, 513, 0, 515, 0, + 0, 0, 0, 0, 398, 0, 591, 592, 669, 384, + 486, 601, 335, 349, 352, 341, 361, 0, 362, 337, + 338, 343, 346, 347, 348, 353, 354, 358, 364, 249, + 210, 390, 399, 578, 312, 216, 217, 218, 524, 525, + 526, 527, 616, 617, 621, 205, 462, 463, 464, 465, + 292, 611, 309, 468, 467, 331, 332, 379, 449, 540, + 542, 553, 557, 559, 561, 567, 570, 541, 543, 554, + 558, 560, 562, 568, 571, 530, 532, 534, 536, 549, + 548, 545, 573, 574, 551, 556, 535, 547, 552, 565, + 572, 569, 529, 533, 537, 546, 564, 563, 544, 555, + 566, 550, 538, 531, 539, 0, 196, 221, 368, 0, + 454, 288, 647, 615, 484, 610, 206, 223, 0, 262, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 198, 200, 209, 222, 232, 236, 243, 261, 276, + 278, 285, 298, 310, 318, 319, 322, 328, 380, 386, + 387, 388, 389, 409, 410, 411, 414, 417, 418, 421, + 423, 424, 427, 431, 435, 436, 437, 439, 441, 443, + 455, 460, 474, 475, 476, 477, 478, 481, 482, 488, + 489, 490, 491, 492, 500, 501, 516, 586, 588, 603, + 622, 629, 480, 301, 302, 444, 445, 314, 315, 643, + 644, 300, 598, 630, 596, 642, 624, 438, 378, 0, + 0, 381, 281, 305, 320, 0, 614, 502, 227, 466, + 290, 251, 0, 0, 211, 246, 230, 259, 274, 277, + 324, 391, 400, 429, 434, 296, 271, 244, 459, 241, + 485, 519, 520, 521, 523, 395, 266, 433, 0, 0, + 376, 576, 577, 316, } var yyPact = [...]int{ - -1000, -1000, 5004, -1000, -538, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 1040, -1000, -551, -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, 2388, 2423, -1000, -1000, -1000, -1000, 2569, -1000, 999, + 2023, -1000, 2374, 5134, -1000, 55556, 520, -1000, 52604, -455, + 871, 259, 36368, -1000, 193, -1000, 166, 54080, 184, -1000, + -1000, -1000, -1000, -455, 21608, 2249, 12, 8, 55556, -1000, + -1000, -1000, -1000, -372, 2516, 2011, -1000, 398, -1000, -1000, + -1000, -1000, -1000, -1000, 51866, -1000, 1127, -1000, -1000, 2384, + 2395, 2244, 915, 2297, -1000, 2451, 2011, -1000, 21608, 2503, + 2334, 20870, 20870, 467, -1000, -1000, 281, -1000, -1000, 31202, + 55556, 39320, 306, -1000, 2374, -1000, -1000, -1000, 186, -1000, + 352, 1909, -1000, 1901, -1000, 936, 1134, 385, 855, 854, + 383, 368, 366, 365, 364, 361, 360, 359, 401, -1000, + 933, 933, -247, -260, 1742, 446, 460, 460, 1041, 487, + 2343, 2339, -1000, -1000, 933, 933, 933, 362, 933, 933, + 933, 933, 339, 337, 933, 933, 933, 933, 933, 933, + 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, + 933, 321, 2374, 273, -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, 2687, 2535, -1000, -1000, -1000, -1000, 2740, -1000, 1030, - 2183, -1000, 2515, 5017, -1000, 55465, 510, -1000, 52545, -445, - 881, 268, 36485, -1000, 200, -1000, 193, 54005, 204, -1000, - -1000, -1000, -1000, -445, 21885, 2408, 51, 43, 55465, -1000, - -1000, -1000, -1000, -364, 2671, 2153, -1000, 408, -1000, -1000, - -1000, -1000, -1000, -1000, 51815, -1000, 1184, -1000, -1000, 2520, - 2504, 2384, 928, 2400, -1000, 2576, 2153, -1000, 21885, 2673, - 2458, 21155, 21155, 478, -1000, -1000, 271, -1000, -1000, 31375, - 55465, 39405, 317, -1000, 2515, -1000, -1000, -1000, 202, -1000, - 346, 2073, -1000, 2065, -1000, 1014, 1053, 413, 846, 829, - 411, 410, 393, 391, 384, 381, 379, 376, 421, -1000, - 952, 952, -201, -205, 362, 479, 468, 468, 1044, 490, - 2493, 2479, -1000, -1000, 952, 952, 952, 343, 952, 952, - 952, 952, 323, 320, 952, 952, 952, 952, 952, 952, - 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, - 952, 909, 2515, 310, -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, @@ -7364,68 +7392,68 @@ 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, + 55556, 279, 55556, -1000, 814, 507, -1000, -1000, -460, 1100, + 1100, 112, 1100, 1100, 1100, 1100, 147, 986, 7, -1000, + 134, 284, 122, 307, 1070, 135, -1000, -1000, 285, 1070, + 1755, -1000, 920, 288, 128, -1000, 1100, 1100, -1000, 14204, + 226, 14204, 14204, 264, -1000, 2369, -1000, -1000, -1000, -1000, + -1000, 1330, -1000, -1000, -1000, -1000, -72, 475, -1000, -1000, + -1000, -1000, 54080, 51128, 268, -1000, -1000, 28, 1839, 1168, + 21608, 1194, 909, -1000, -1000, 1314, 874, -1000, -1000, -1000, + -1000, -1000, 798, -1000, 23822, 23822, 23822, 23822, -1000, -1000, + 1914, 50390, 1914, 1914, 23822, 1914, 23822, 1914, 1914, 1914, + 1914, 21608, 1914, 1914, 1914, 1914, -1000, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, -1000, -1000, -1000, -1000, + 1914, 813, 1914, 1914, 1914, 1914, 1914, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 1914, 1914, 1914, 1914, 1914, 1914, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, -1000, -1000, -1000, 1584, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 26774, 1491, 1489, 1487, -1000, 18656, + 1914, -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, 55465, 262, 55465, -1000, - 821, 509, -1000, -1000, -449, 1113, 1113, 77, 1113, 1113, - 1113, 1113, 185, 1006, 41, -1000, 182, 305, 168, 303, - 1087, 197, -1000, -1000, 292, 1087, 1945, -1000, 933, 287, - 169, -1000, 1113, 1113, -1000, 14561, 251, 14561, 14561, -1000, - 2503, -1000, -1000, -1000, -1000, -1000, 1426, -1000, -1000, -1000, - -1000, -26, 489, -1000, -1000, -1000, -1000, 54005, 51085, 289, - -1000, -1000, 771, 1967, 1182, 21885, 1367, 926, -1000, -1000, - 1487, 902, -1000, -1000, -1000, -1000, -1000, 802, -1000, 24075, - 24075, 24075, 24075, -1000, -1000, 2081, 50355, 2081, 2081, 24075, - 2081, 24075, 2081, 2081, 2081, 2081, 21885, 2081, 2081, 2081, - 2081, -1000, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, -1000, - -1000, -1000, -1000, 2081, 820, 2081, 2081, 2081, 2081, 2081, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2081, 2081, 2081, - 2081, 2081, 2081, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, -1000, -1000, -1000, 1800, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 26995, 1695, 1693, - 1692, -1000, 18965, 2081, -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, 55556, -1000, 1914, 222, 54080, 54080, 374, 1321, + -1000, -1000, 2451, 2011, -1000, 2516, 2490, 398, -1000, 4440, + 1549, 1669, 1380, 2011, 1882, 55556, -1000, 1940, -1000, -1000, + -1000, -394, -395, 2179, 1420, 1738, -1000, -1000, -1000, -1000, + 2205, 21608, -1000, -1000, 2537, -1000, 28250, 812, 2534, 49652, + -1000, 467, 467, 1893, 420, -22, -1000, -1000, -1000, -1000, + 976, 35630, -1000, -1000, -1000, -1000, -1000, 1800, 55556, -1000, + -1000, 4986, 54080, -1000, 2015, -1000, 1762, -1000, 1982, 21608, + 2033, 506, 54080, 500, 496, 495, -1000, -99, -1000, -1000, + -1000, -1000, -1000, -1000, 933, 933, 933, -1000, 391, 2502, + 5134, 6342, -1000, -1000, -1000, 48914, 2014, 54080, -1000, 2012, + -1000, 1063, 825, 879, 879, 54080, -1000, -1000, 54818, 54080, + 1061, 1059, 54080, 54080, 54080, 54080, -1000, 48176, -1000, 47438, + 46700, 1316, 54080, 45962, 45224, 44486, 43748, 43010, -1000, 2220, + -1000, 1988, -1000, -1000, -1000, 54818, 54080, 54080, 54818, 54080, + 54818, 55556, 54080, -1000, -1000, 342, -1000, -1000, 1315, 1313, + 1302, 933, 933, 1299, 1722, 1707, 1704, 933, 933, 1295, + 1702, 37844, 1649, 292, 1294, 1291, 1289, 1303, 1641, 233, + 1639, 1301, 1206, 1279, 54080, 2010, 55556, -1000, 267, 971, + 947, 970, 2374, 2240, 1892, 474, 505, 54080, 463, 463, + 54080, -1000, 14948, 55556, 188, -1000, 1637, 21608, -1000, 1078, + 1070, 1070, -1000, -1000, -1000, -1000, -1000, -1000, 1100, 55556, + 1078, -1000, -1000, -1000, 1070, 1100, 55556, 1100, 1100, 1100, + 1100, 1070, 1070, 1070, 1100, 55556, 55556, 55556, 55556, 55556, + 55556, 55556, 55556, 55556, 14204, 920, 1100, -461, -1000, 1629, + -1000, -1000, -1000, 2147, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 55465, -1000, 2081, 225, 54005, - 54005, 348, 1414, -1000, -1000, 2576, 2153, -1000, 2671, 2705, - 408, -1000, 2509, 1753, 1798, 1625, 2153, 2030, 55465, -1000, - 2102, -1000, -1000, -1000, -307, -329, 2258, 1574, 1934, -1000, - -1000, -1000, -1000, 2482, 21885, -1000, -1000, 2720, -1000, 28455, - 818, 2718, 49625, -1000, 478, 478, 2064, 424, 5, -1000, - -1000, -1000, -1000, 992, 35755, -1000, -1000, -1000, -1000, -1000, - 1953, 55465, -1000, -1000, 1216, 54005, -1000, 2181, -1000, 1949, - -1000, 2138, 21885, 2191, 508, 54005, 499, 498, 497, -1000, - -53, -1000, -1000, -1000, -1000, -1000, -1000, 952, 952, 952, - -1000, 399, 2660, 5017, 7766, -1000, -1000, -1000, 48895, 2178, - 54005, -1000, 2174, -1000, 1073, 872, 851, 851, 54005, -1000, - -1000, 54735, 54005, 1067, 1064, 54005, 54005, 54005, 54005, -1000, - 48165, -1000, 47435, 46705, 1413, 54005, 45975, 45245, 44515, 43785, - 43055, -1000, 2255, -1000, 2137, -1000, -1000, -1000, 54735, 54005, - 54005, 54735, 54005, 54735, 55465, 54005, -1000, -1000, 357, -1000, - -1000, 1411, 1397, 1396, 952, 952, 1395, 1929, 1927, 1926, - 952, 952, 1390, 1925, 37945, 1923, 276, 1383, 1381, 1349, - 1380, 1906, 299, 1895, 1379, 1310, 1348, 54005, 2171, 55465, - -1000, 290, 934, 907, 989, 2515, 2405, 2060, 488, 507, - 54005, 472, 472, 54005, -1000, 15297, 55465, 232, -1000, 1893, - 21885, -1000, 1089, 1087, 1087, -1000, -1000, -1000, -1000, -1000, - -1000, 1113, 55465, 1089, -1000, -1000, -1000, 1087, 1113, 55465, - 1113, 1113, 1113, 1113, 1087, 1087, 1087, 1113, 55465, 55465, - 55465, 55465, 55465, 55465, 55465, 55465, 55465, 14561, 933, 1113, - -450, -1000, 1881, -1000, -1000, -1000, 2283, -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, @@ -7440,335 +7468,336 @@ 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, 14204, 14204, -1000, -1000, 2448, -1000, + -1000, -1000, 1888, -1000, 167, -14, 182, -1000, 42272, 485, + 967, -1000, 485, -1000, -1000, -1000, 1886, 41534, -1000, -462, + -463, -464, -465, -1000, -1000, -1000, -469, -470, -1000, -1000, + -1000, 21608, 21608, 21608, 21608, -295, -1000, 1032, 23822, 2307, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 21608, 223, 964, + 23822, 23822, 23822, 23822, 23822, 23822, 23822, 25298, 24560, 23822, + 23822, 23822, 23822, 23822, 23822, -1000, -1000, 33416, 8224, 8224, + 874, 874, 874, 874, -1000, -221, 1884, 54818, -1000, -1000, + -1000, 811, 21608, 21608, 874, -1000, 1337, 2215, 18656, 21608, + 21608, 21608, 21608, 939, 1168, 54818, 21608, -1000, 1380, -1000, + -1000, -1000, -1000, 1210, -1000, -1000, 1045, 2319, 2319, 2319, + 2319, 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, + 21608, 2319, 21608, 148, 148, 1596, 21608, 21608, 21608, 21608, + 21608, 21608, 21608, 21608, 17180, 21608, 21608, 23822, 21608, 21608, + 21608, 1380, 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, + 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, + 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, + 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, + 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, + 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, + 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, + 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, 21608, + 21608, 1380, 21608, 1338, 21608, 21608, 21608, 21608, 21608, 21608, + 21608, 16436, 21608, 21608, 21608, 21608, 21608, -1000, -1000, -1000, + -1000, -1000, -1000, 21608, 21608, 21608, 21608, 21608, 21608, 21608, + 21608, 1380, 21608, 21608, 21608, 21608, 21608, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1633, 1592, + 1458, 21608, -1000, 1883, -1000, -198, 30464, 21608, 1617, 2532, + 2056, 54080, -1000, -1000, -1000, -1000, 2451, -1000, 2451, 1633, + 4400, 2182, 20870, -1000, -1000, 4400, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1647, + -1000, 55556, 1882, 2443, 54080, -1000, -355, -1000, -361, 2156, + 1605, 340, -1000, 21608, 21608, 1878, -1000, 1687, 55556, -1000, + -295, -1000, 40796, -1000, -1000, 13460, 55556, 355, 55556, -1000, + 29726, 40058, 290, -1000, -22, 1867, -1000, -26, -16, 17918, + 873, -1000, -1000, -1000, 1742, 26036, 1836, 873, 66, -1000, + -1000, -1000, 1982, -1000, 1982, 1982, 1982, 1982, 340, 340, + 340, 340, -1000, -1000, -1000, -1000, -1000, 2009, 1982, 2008, + -1000, 1982, 1982, 1982, 1982, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 14561, 14561, -1000, -1000, -1000, -1000, - -1000, 2058, -1000, 187, 13, 199, -1000, 42325, 501, 985, - -1000, 501, -1000, -1000, -1000, 2050, 41595, -1000, -452, -456, - -459, -460, -1000, -1000, -1000, -461, -462, -1000, -1000, -1000, - 21885, 21885, 21885, 21885, -255, -1000, 1471, 24075, 2473, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 21885, 216, 948, 24075, - 24075, 24075, 24075, 24075, 24075, 24075, 25535, 24805, 24075, 24075, - 24075, 24075, 24075, 24075, -1000, -1000, 33565, 5149, 5149, 902, - 902, 902, 902, -1000, -164, 2044, 54735, -1000, -1000, -1000, - 817, 21885, 21885, 902, -1000, 1221, 2197, 18965, 21885, 21885, - 21885, 21885, 964, 1182, 54735, 21885, -1000, 1625, -1000, -1000, - -1000, -1000, 1331, -1000, -1000, 1104, 2469, 2469, 2469, 2469, - 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, - 2469, 21885, 173, 173, 910, 21885, 21885, 21885, 21885, 21885, - 21885, 17505, 21885, 21885, 24075, 21885, 21885, 21885, 1625, 21885, - 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, - 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, - 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, - 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, - 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, - 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, - 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, - 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, 1625, 21885, - 1656, 21885, 21885, 21885, 21885, 21885, 21885, 21885, 16769, 21885, - 21885, 21885, 21885, 21885, -1000, -1000, -1000, -1000, -1000, -1000, - 21885, 21885, 21885, 21885, 21885, 21885, 21885, 21885, 1625, 21885, - 21885, 21885, 21885, 21885, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 1917, 1563, 1616, 21885, -1000, - 2036, -1000, -190, 30645, 21885, 1857, 2717, 2213, 54005, -1000, - -1000, -1000, -1000, 2576, -1000, 2576, 1917, 2451, 2339, 21155, - -1000, -1000, 2451, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 1937, -1000, 55465, 2030, 2581, 54005, -1000, -355, - -1000, -367, 2330, 1848, 351, -1000, 21885, 21885, 2027, -1000, - 1597, 55465, -1000, -255, -1000, 40865, -1000, -1000, 13825, 55465, - 372, 55465, -1000, 29915, 40135, 283, -1000, 5, 2013, -1000, - 20, 11, 18235, 901, -1000, -1000, -1000, 362, 26265, 1970, - 901, 108, -1000, -1000, -1000, 2138, -1000, 2138, 2138, 2138, - 2138, 351, 351, 351, 351, -1000, -1000, -1000, -1000, -1000, - 2162, 2157, -1000, 2138, 2138, 2138, 2138, -1000, -1000, -1000, + -1000, -1000, 2003, 2003, 2003, 2002, 2002, 1983, 1983, 448, + -1000, 21608, 426, 39320, 2381, 1277, 2617, 267, 464, 2053, + 54080, 54080, 54080, 464, -1000, 1359, 1356, 1351, -1000, -531, + 1872, -1000, -1000, 2501, -1000, -1000, 1156, 1082, 1080, 916, + 54080, 231, 351, -1000, 435, -1000, 39320, 54080, 1058, 879, + 54080, -1000, 54080, -1000, -1000, -1000, -1000, -1000, 54080, -1000, + -1000, 1871, -1000, 1900, 1122, 1077, 1086, 1051, 1871, -1000, + -1000, -228, 1871, -1000, 1871, -1000, 1871, -1000, 1871, -1000, + 1871, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 1002, 119, -365, 54080, 231, 473, -1000, 472, 33416, -1000, + -1000, -1000, 33416, 33416, -1000, -1000, -1000, -1000, 1602, 1600, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 2151, 2151, 2151, 2150, 2150, 2142, - 2142, 451, -1000, 21885, 517, 39405, 2558, 1337, 1773, 290, - 474, 2211, 54005, 54005, 54005, 474, -1000, 1518, 1510, 1508, - -1000, -527, 2026, -1000, -1000, 2654, -1000, -1000, 1065, 1141, - 1119, 1090, 54005, 231, 356, -1000, 442, -1000, 39405, 54005, - 1063, 851, 54005, -1000, 54005, -1000, -1000, -1000, -1000, -1000, - 54005, -1000, -1000, 2020, -1000, 2049, 1180, 1103, 1162, 1094, - 2020, -1000, -1000, -169, 2020, -1000, 2020, -1000, 2020, -1000, - 2020, -1000, 2020, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 977, 301, -375, 54005, 231, 486, -1000, 485, - 33565, -1000, -1000, -1000, 33565, 33565, -1000, -1000, -1000, -1000, - 1841, 1825, -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, -520, + 55556, -1000, 251, 956, 344, 357, 303, 55556, 372, 2337, + 2333, 2330, 2325, 2321, 2314, 2313, 271, 336, 55556, 55556, + 463, 2096, 55556, 2407, 55556, -1000, -1000, -1000, -1000, -1000, + 1598, 1595, -1000, 1168, 55556, -1000, -1000, 1100, 1100, -1000, + -1000, 55556, 1100, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 1100, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 55556, -1000, -1000, + -1000, -1000, 1588, -1000, -72, 154, -1000, -1000, 54080, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -120, -1000, + 305, -30, 406, -1000, -1000, -1000, -1000, -1000, 2447, -1000, + 1168, 1026, 993, -1000, 1914, -1000, -1000, 1213, -1000, -1000, + -1000, -1000, -1000, 1914, 1914, 1914, -1000, -1000, -1000, -1000, + -1000, 223, 23822, 23822, 23822, 1429, 819, 1413, 1578, 1604, + 923, 923, 930, 23822, 930, 23822, 881, 881, 881, 881, + 881, -1000, -1000, -1000, -1000, -1000, -1000, 1584, -1000, 1562, + -1000, 1914, 54818, 1760, 16436, 1382, 2139, 1380, 902, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -509, 55465, -1000, 258, 983, 319, 313, 331, 55465, - 401, 2465, 2463, 2452, 2450, 2447, 2439, 349, 318, 55465, - 55465, 472, 2266, 55465, 2537, 55465, -1000, -1000, -1000, -1000, - -1000, 1811, 1806, -1000, 1182, 55465, -1000, -1000, 1113, 1113, - -1000, -1000, 55465, 1113, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 1113, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 55465, -1000, - -1000, -1000, -1000, -26, 181, -1000, -1000, 54005, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -110, -1000, 718, - 18, 383, -1000, -1000, -1000, -1000, -1000, 2588, -1000, 1182, - 1050, 1034, -1000, 2081, -1000, -1000, 1321, -1000, -1000, -1000, - -1000, -1000, 2081, 2081, 2081, -1000, -1000, -1000, -1000, -1000, - 216, 24075, 24075, 24075, 1469, 797, 1558, 1283, 1219, 1228, - 1228, 1013, 24075, 1013, 24075, 912, 912, 912, 912, 912, - -1000, -1000, -1000, -1000, -1000, -1000, 1800, -1000, 1786, -1000, - 2081, 54735, 1903, 16769, 2591, 1340, 1625, 921, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 4309, + 1380, 1839, 1380, 1196, 4305, 996, -1000, 21608, 1380, 4301, + -1000, -1000, 1380, 1380, 21608, -1000, -1000, 21608, 21608, 21608, + 21608, 2617, 2617, 2617, 2617, 2617, 2617, 2617, 2617, 2617, + 2617, 21608, 2617, 1870, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 3856, 1625, - 1967, 1625, 2021, 3538, 1024, -1000, 21885, 1625, 3502, -1000, - -1000, 1625, 1625, 21885, -1000, -1000, 21885, 21885, 21885, 21885, - 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, - 21885, 1773, 2018, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 1869, 2530, 1293, 2617, 2617, 2617, 2617, 4293, + 2617, 2617, 21608, 1306, -1000, -1000, -1000, 1379, 4288, 1366, + 4284, 2617, 2617, -1000, 2617, 4280, 4276, 1380, 3273, 3265, + 2617, 2617, 2617, 2617, 2617, 3037, 3011, 2617, 2617, 2975, + 2617, 4266, 2617, 2963, 2951, 2876, 2849, 2807, 2773, 2763, + 2727, 2723, 2703, 2642, 2609, 2603, 2558, 2539, 2495, 2479, + 2450, 2617, 2617, 2617, 4257, 2617, 4248, 2617, 4244, 2617, + 2617, 4239, 2435, 2406, 1380, 1868, -1000, 4233, 2617, 4227, + 4223, 4216, 2399, 4203, 3957, 3948, 2617, 2617, 2617, 2385, + 3938, 3930, 3925, 3907, 3896, 3888, 3573, 3566, 3555, 2617, + 1458, 1458, 1458, 1458, 1458, 3551, -323, 2617, 1380, -1000, + -1000, -1000, -1000, -1000, 3540, 2361, 3513, 3480, 3470, 3456, + 1380, 1914, 808, -1000, -1000, 1458, 1380, 1380, 1458, 1458, + 3447, 3442, 3417, 3387, 3381, 3377, 2617, 2617, -1000, 2617, + 3370, 3360, 2354, 2336, 1380, -1000, 1458, 55556, -1000, -452, + -1000, -43, 937, 1914, -1000, 37844, 1380, -1000, 7664, -1000, + 1269, -1000, -1000, -1000, -1000, -1000, 34892, 1656, -1000, -1000, + -1000, -1000, 1914, 1753, -1000, -1000, -1000, -1000, 340, 52, + 34154, 867, 867, 85, 1168, 1168, 21608, -1000, -1000, -1000, + -1000, -1000, -1000, 807, 2515, 331, 1914, -1000, 1877, 2665, + -1000, -1000, -1000, 2431, 27512, -1000, -1000, 1914, 1914, 55556, + 1798, 1779, -1000, 806, -1000, 1340, 1867, -22, -32, -1000, + -1000, -1000, -1000, 1168, -1000, 1346, 356, 1492, -1000, 434, + -1000, -1000, -1000, -1000, 2270, 42, -1000, -1000, -1000, 371, + 340, -1000, -1000, -1000, -1000, -1000, -1000, 1554, -1000, 1554, + -1000, -1000, -1000, -1000, -1000, 1276, -1000, -1000, -1000, -1000, + 1262, -1000, -1000, 1250, -1000, -1000, 3344, 2086, 426, -1000, + -1000, 933, 1547, -1000, -1000, 2289, 933, 933, 54080, -1000, + -1000, 1785, 2381, 251, 55556, 944, 2094, -1000, 2053, 2053, + 2053, 55556, -1000, -1000, -1000, -1000, -1000, -1000, -533, 165, + 335, -1000, -1000, -1000, 5507, 54080, 1751, -1000, 234, -1000, + 1782, -1000, 54080, -1000, 1749, 1995, 54080, 54080, -1000, -1000, + -1000, 54080, 1914, -1000, -1000, -1000, -1000, 502, 2371, 338, + -1000, -1000, -344, -1000, -1000, 231, 234, 54818, 54080, 873, + -1000, -1000, -1000, -1000, -1000, -523, 1734, 489, 242, 297, + 55556, 55556, 55556, 55556, 55556, 55556, 789, -1000, -1000, -8, + -1000, -1000, 201, -1000, -1000, -1000, -1000, -1000, -1000, 201, + -1000, -1000, -1000, -1000, -1000, 294, 471, -1000, 55556, 55556, + 935, -1000, -1000, -1000, -1000, -1000, 1070, -1000, -1000, 1070, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 2017, 2716, 2175, 1773, 1773, 1773, 1773, 1773, 21885, - 1461, -1000, -1000, -1000, 1628, 3490, 1366, 3473, 1773, 1773, - -1000, 1773, 3458, 3453, 1625, 2670, 2659, 1773, 1773, 1773, - 1773, 1773, 2601, 2572, 1773, 1773, 2543, 1773, 3448, 1773, - 2539, 2532, 2492, 2467, 2462, 2449, 2435, 2425, 2377, 2352, - 2333, 2327, 2314, 2301, 2287, 2269, 2257, 2253, 1773, 1773, - 1773, 3443, 1773, 3432, 1773, 3427, 1773, 1773, 3422, 2243, - 2206, 1625, 2016, -1000, 3415, 1773, 3399, 3386, 3382, 2167, - 3356, 3352, 3348, 1773, 1773, 1773, 2163, 3341, 3328, 3323, - 3313, 3308, 3236, 3224, 3043, 3030, 1773, 1616, 1616, 1616, - 1616, 1616, 3023, -269, 1773, 1625, -1000, -1000, -1000, -1000, - -1000, 3019, 2159, 3009, 3001, 2994, 2981, 1625, 2081, 814, - -1000, -1000, 1616, 1625, 1625, 1616, 1616, 2976, 2932, 2922, - 2918, 2912, 2908, 1773, 1773, -1000, 1773, 2895, 2846, 2139, - 2123, 1625, -1000, 1616, 55465, -1000, -441, -1000, 9, 960, - 2081, -1000, 37945, 1625, -1000, 4388, -1000, 1287, -1000, -1000, - -1000, -1000, -1000, 35025, 2023, -1000, -1000, -1000, -1000, 2081, - 1891, -1000, -1000, -1000, -1000, 351, 74, 34295, 878, 878, - 126, 1182, 1182, 21885, -1000, -1000, -1000, -1000, -1000, -1000, - 813, 2679, 394, 2081, -1000, 2066, 2723, -1000, -1000, -1000, - 2579, 27725, -1000, -1000, 2081, 2081, 55465, 1989, 1922, -1000, - 810, -1000, 1476, 2013, 5, 1, -1000, -1000, -1000, -1000, - 1182, -1000, 1438, 374, 341, -1000, 463, -1000, -1000, -1000, - -1000, 2420, 94, -1000, -1000, -1000, 373, 351, -1000, -1000, - -1000, -1000, -1000, -1000, 1736, 1736, -1000, -1000, -1000, -1000, - -1000, 1336, -1000, -1000, -1000, -1000, 1334, -1000, -1000, 1328, - -1000, -1000, 2712, 2195, 517, -1000, -1000, 952, 1734, -1000, - -1000, 2438, 952, 952, 54005, -1000, -1000, 1823, 2558, 258, - 55465, 1003, 2263, -1000, 2211, 2211, 2211, 55465, -1000, -1000, - -1000, -1000, -1000, -1000, -513, 172, 378, -1000, -1000, -1000, - 6167, 54005, 1889, -1000, 253, -1000, 1797, -1000, 54005, -1000, - 1865, 2149, 54005, 54005, -1000, -1000, -1000, 54005, 2081, -1000, - -1000, -1000, -1000, 504, 2511, 336, -1000, -1000, -311, -1000, - -1000, 231, 253, 54735, 54005, 901, -1000, -1000, -1000, -1000, - -1000, -514, 1856, 494, 263, 516, 55465, 55465, 55465, 55465, - 55465, 55465, 782, -1000, -1000, 31, -1000, -1000, 218, -1000, - -1000, -1000, -1000, -1000, 218, -1000, -1000, -1000, -1000, -1000, - 312, 484, -1000, 55465, 55465, 917, -1000, -1000, -1000, -1000, - -1000, 1087, -1000, -1000, 1087, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 2499, 55465, 17, -479, -1000, - -476, 21885, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1329, - 471, 1558, 24075, 24075, 2197, 2197, 24075, -1000, -1000, -1000, - 819, 819, 33565, -1000, 24075, 21885, -1000, -1000, 21885, 21885, - 21885, 949, -1000, 21885, 1137, -1000, 21885, -1000, -269, 1616, - 1773, 1773, 1773, 1773, -269, -269, -269, -269, -269, -269, - -269, -269, -269, -269, 2063, -1000, 21885, 21885, 21885, 1625, - 345, -1000, -1000, -1000, -1000, -1000, 2710, -1000, 21885, -1000, - 33565, 21885, 21885, 21885, -1000, -1000, -1000, 21885, 21885, -1000, - -1000, 21885, -1000, 21885, -1000, -1000, -1000, -1000, -1000, -1000, - 21885, -1000, 21885, -1000, -1000, -1000, 21885, -1000, 21885, -1000, - -1000, 21885, -1000, 21885, -1000, 21885, -1000, 21885, -1000, 21885, - -1000, 21885, -1000, 21885, -1000, 21885, -1000, 21885, -1000, 21885, - -1000, 21885, -1000, 21885, -1000, 21885, -1000, 21885, -1000, 21885, - -1000, 21885, -1000, 21885, -1000, 21885, -1000, -1000, -1000, 21885, - -1000, 21885, -1000, 21885, -1000, -1000, 21885, -1000, 21885, -1000, - 21885, -1000, 21885, 21885, -1000, 21885, 21885, 21885, -1000, 21885, - 21885, 21885, 21885, -1000, -1000, -1000, -1000, 21885, 21885, 21885, - 21885, 21885, 21885, 21885, 21885, 21885, 21885, -1000, -1000, -1000, - -1000, -1000, -1000, 21885, -1000, 39405, 10, -269, 1656, 10, - 1656, 23345, 823, 798, 22615, -1000, 21885, 16033, -1000, -1000, - -1000, -1000, -1000, 21885, 21885, 21885, 21885, 21885, 21885, -1000, - -1000, -1000, 21885, 21885, -1000, 21885, -1000, 21885, -1000, -1000, - -1000, -1000, -1000, 960, -1000, 883, 874, 851, 54005, -1000, - -1000, -1000, -1000, 2005, -1000, 2616, -1000, 2361, 2359, 2704, - 2679, 21155, -1000, 29915, -1000, -1000, 54005, -432, -1000, 2391, - 2399, 878, 878, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 13089, 2576, 21885, 2261, 54735, 249, -1000, 29185, 54005, 54735, - 29915, 29915, 29915, 29915, 29915, -1000, 2307, 2288, -1000, 2342, - 2311, 2338, 55465, -1000, 1917, 1838, -1000, 21885, 32105, 1975, - 29915, -1000, -1000, 29915, 55465, 12353, -1000, -1000, 16, 4, - -1000, -1000, -1000, -1000, 362, -1000, -1000, 1002, 2575, 2417, - -1000, -1000, -1000, -1000, -1000, 1758, -1000, 1749, 1995, 1745, - 1742, 301, -1000, 2190, 2497, 952, 952, -1000, 1327, -1000, - 1221, 1733, 1731, -1000, -1000, -1000, 492, -1000, 2536, 55465, - 2252, 2251, 2249, -1000, -524, 1314, 2148, 2172, 21885, 2145, - 2653, 1980, 54005, -1000, -1000, 54735, -1000, 282, -1000, 517, - 54005, -1000, -1000, -1000, 356, 55465, -1000, 8424, -1000, -1000, - -1000, 253, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 55465, - 270, -1000, 2143, 1425, -1000, -1000, 2196, -1000, -1000, -1000, - -1000, -1000, 210, 201, 1730, 214, 1716, 214, -1000, 55465, - 914, 2195, 55465, -1000, -1000, -1000, 1113, 1113, -1000, -1000, - 2475, -1000, 1221, 1773, 24075, 24075, -1000, 902, -1000, -1000, - 371, -254, 2138, 2138, -1000, 2138, 2142, -1000, 2138, 171, - 2138, 165, 2138, -1000, -1000, 1625, 1625, -1000, 1616, 2119, - 1200, 2841, -1000, 1182, 21885, 2831, -1000, -1000, -269, -269, - -269, -269, -269, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -60, 2787, 2750, 1773, -1000, 2132, 2128, - 21885, 1773, 1625, 2098, 1773, 1773, 1773, 1773, 1773, 1773, - 1773, 1773, 1773, 1773, 1773, 1773, 2090, 2061, 2056, 2047, - 2033, 2028, 2014, 1999, 1990, 1986, 1969, 1956, 1951, 1941, - 1905, 1879, 1773, 1773, 1860, 1773, 1854, 1822, -1000, 1182, - 1616, 2746, 1616, 1773, 1773, 2721, 306, 1773, 1727, 1727, - 1727, 1727, 1727, 1616, 1616, 1616, 1616, 1773, 54005, -1000, - -269, -1000, -1000, -374, -376, -1000, 1625, -269, 1993, 24075, - 1773, 24075, 24075, 24075, 1773, 1625, -1000, 1818, 1814, 2707, - 1796, 1773, 2681, 1773, 1773, 1773, 1789, -1000, 2586, 2081, - 2586, 2081, 2586, 1714, 1287, 55465, -1000, -1000, -1000, -1000, - 2679, 2677, -1000, 1984, -1000, 74, 629, -1000, 2376, 2399, - -1000, 2651, 2383, 2650, -1000, -1000, -1000, -1000, -1000, 1182, - -1000, 2518, 1966, -1000, 982, 1820, -1000, -1000, 20425, 1720, - 2353, 808, 1714, 2037, 2723, 2208, 2240, 3626, -1000, -1000, - -1000, -1000, 2281, -1000, 2221, -1000, -1000, 2102, -1000, 2638, - 372, 29915, 1998, 1998, -1000, 800, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 1160, 8424, 2727, -1000, 1710, -1000, 1372, - 191, 1309, -1000, -1000, 952, 952, -1000, 1057, 1056, -1000, - 55465, 2127, -1000, 351, 1697, 351, 1280, -1000, -1000, 1276, - -1000, -1000, -1000, -1000, 2099, 2242, -1000, -1000, -1000, -1000, - 55465, -1000, -1000, 55465, 55465, 55465, 2122, 2649, -1000, 21885, - 2116, 954, 2596, 54005, 54005, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 447, 952, -492, 316, - 302, 952, 952, 952, -526, -1000, -1000, 1709, 1705, -1000, - -202, -1000, 21885, -1000, -1000, -1000, -1000, -1000, 1201, 1201, - 1695, 1693, 1692, -1000, 2102, -1000, -1000, -1000, 1759, -1000, - -1000, -179, 54005, 54005, 54005, 54005, -1000, -1000, -1000, 1277, + -1000, 2351, 55556, -34, -491, -1000, -488, 21608, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 1328, 805, 1413, 23822, 23822, + 2215, 2215, 23822, -1000, -1000, -1000, 985, 985, 33416, -1000, + 23822, 21608, -1000, -1000, 21608, 21608, 21608, 982, -1000, 21608, + 1273, -1000, 21608, -1000, -323, 1458, 2617, 2617, 2617, 2617, + -323, -323, -323, -323, -323, -323, -323, -323, -323, -323, + 1854, -1000, 21608, 21608, 21608, 1380, 304, -1000, -1000, -1000, + -323, 21608, -1000, -1000, 2526, -1000, 21608, -1000, 33416, 21608, + 21608, 21608, -1000, -1000, -1000, 21608, 21608, -1000, -1000, 21608, + -1000, 21608, -1000, -1000, -1000, -1000, -1000, -1000, 21608, -1000, + 21608, -1000, -1000, -1000, 21608, -1000, 21608, -1000, -1000, 21608, + -1000, 21608, -1000, 21608, -1000, 21608, -1000, 21608, -1000, 21608, + -1000, 21608, -1000, 21608, -1000, 21608, -1000, 21608, -1000, 21608, + -1000, 21608, -1000, 21608, -1000, 21608, -1000, 21608, -1000, 21608, + -1000, 21608, -1000, 21608, -1000, -1000, -1000, 21608, -1000, 21608, + -1000, 21608, -1000, -1000, 21608, -1000, 21608, -1000, 21608, -1000, + 21608, 21608, -1000, 21608, 21608, 21608, -1000, 21608, 21608, 21608, + 21608, -1000, -1000, -1000, -1000, 21608, 21608, 21608, 21608, 21608, + 21608, 21608, 21608, 21608, 21608, -1000, -1000, -1000, -1000, -1000, + -1000, 21608, -1000, 39320, 1, -323, 1338, 1, 1338, 23084, + 823, 816, 22346, -1000, 21608, 15692, -1000, -1000, -1000, -1000, + -1000, 21608, 21608, 21608, 21608, 21608, 21608, -1000, -1000, -1000, + 21608, 21608, -1000, 21608, -1000, 21608, -1000, -1000, -1000, -1000, + -1000, 937, -1000, 834, 831, 879, 54080, -1000, -1000, -1000, + -1000, 1862, -1000, 2454, -1000, 2213, 2211, 2524, 2515, 20870, + -1000, 29726, -1000, -1000, 54080, -443, -1000, 2231, 2277, 867, + 867, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 12716, 2451, + 21608, 2093, 54818, 238, -1000, 28988, 54080, 54818, 29726, 29726, + 29726, 29726, 29726, -1000, 2127, 2115, -1000, 2163, 2117, 2192, + 55556, -1000, 1633, 1729, -1000, 21608, 31940, 1802, 29726, -1000, + -1000, 29726, 55556, 11972, -1000, -1000, -37, -49, -1000, -1000, + -1000, -1000, 1742, -1000, -1000, 1017, 2428, 2266, -1000, -1000, + -1000, -1000, -1000, 1727, -1000, 1718, 1861, 1716, 1699, 119, + -1000, 2031, 2350, 933, 933, -1000, 1249, -1000, 1337, 1545, + 1536, -1000, -1000, -1000, 486, -1000, 2400, 55556, 2088, 2081, + 2079, -1000, -541, 1244, 1992, 2030, 21608, 1991, 2497, 1852, + 54080, -1000, -1000, 54818, -1000, 260, -1000, 426, 54080, -1000, + -1000, -1000, 351, 55556, -1000, 7359, -1000, -1000, -1000, 234, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 55556, 247, -1000, + 1989, 1297, -1000, -1000, 2013, -1000, -1000, -1000, -1000, -1000, + 159, 153, 1531, 199, 1521, 199, -1000, 55556, 921, 2086, + 55556, -1000, -1000, -1000, 1100, 1100, -1000, -1000, 2346, -1000, + 1337, 2617, 23822, 23822, -1000, 874, -1000, -1000, 415, -275, + 1982, 1982, -1000, 1982, 1983, -1000, 1982, 151, 1982, 121, + 1982, -1000, -1000, 1380, 1380, -1000, 1458, 2288, 2020, 3339, + -1000, 1168, 21608, 3261, -1000, -1000, -323, -323, -323, -323, + -323, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -109, 3097, 3052, 2617, -1000, 1977, 1975, -1000, 2617, + 21608, 2617, 1380, 2283, 2617, 2617, 2617, 2617, 2617, 2617, + 2617, 2617, 2617, 2617, 2617, 2617, 2218, 2189, 2181, 2165, + 2148, 2111, 2104, 2098, 2044, 2032, 2028, 2016, 2004, 1996, + 1979, 1919, 2617, 2617, 1889, 2617, 1879, 1859, -1000, 1168, + 1458, 2814, 1458, 2617, 2617, 2660, 287, 2617, 1675, 1675, + 1675, 1675, 1675, 1458, 1458, 1458, 1458, 2617, 54080, -1000, + -323, -1000, -1000, -370, -377, -1000, 1380, -323, 1858, 23822, + 2617, 23822, 23822, 23822, 2617, 1380, -1000, 1807, 1789, 2513, + 1765, 2617, 2271, 2617, 2617, 2617, 1747, -1000, 2387, 1914, + 2387, 1914, 2387, 1646, 1269, 55556, -1000, -1000, -1000, -1000, + 2515, 2521, -1000, 1853, -1000, 52, 402, -1000, 2257, 2277, + -1000, 2496, 2226, 2484, -1000, -1000, -1000, -1000, -1000, 1168, + -1000, 2376, 1826, -1000, 954, 1804, -1000, -1000, 20132, 1671, + 2201, 804, 1646, 1855, 2665, 2051, 2078, 2488, -1000, -1000, + -1000, -1000, 2114, -1000, 2113, -1000, -1000, 1940, -1000, 2143, + 355, 29726, 1832, 1832, -1000, 797, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 1096, 7359, 2572, -1000, 1519, -1000, 1332, + 192, 1236, -1000, -1000, 933, 933, -1000, 1052, 1044, -1000, + 55556, 1947, -1000, 340, 1503, 340, 1234, -1000, -1000, 1229, + -1000, -1000, -1000, -1000, 1926, 2057, -1000, -1000, -1000, -1000, + 55556, -1000, -1000, 55556, 55556, 55556, 1945, 2481, -1000, 21608, + 1944, 934, 3017, 54080, 54080, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 456, 933, -503, 324, + 318, 933, 933, 933, -544, -1000, -1000, 1628, 1616, -1000, + -248, -1000, 21608, -1000, -1000, -1000, -1000, -1000, 1272, 1272, + 1491, 1489, 1487, -1000, 1940, -1000, -1000, -1000, 1763, -1000, + -1000, -237, 54080, 54080, 54080, 54080, -1000, -1000, -1000, 1223, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 902, 1625, 387, -183, 1625, -1000, -1000, 351, + -1000, -1000, 874, 1380, 332, -240, 1380, -1000, -1000, 340, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 21885, -1000, 21885, -1000, 21885, 1182, 21885, -1000, -1000, -1000, - -1000, -1000, 2576, 1689, 21885, 21885, -1000, 1256, 1238, 1773, - -1000, -1000, -1000, 21885, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 21885, -1000, 21885, - -1000, 21885, -1000, 21885, -1000, 21885, -1000, 21885, -1000, 21885, - -1000, 21885, -1000, 21885, -1000, 21885, -1000, 21885, -1000, 21885, - -1000, 21885, -1000, 21885, -1000, 21885, -1000, 21885, -1000, -1000, - 21885, -1000, -1000, -1000, 21885, -1000, 21885, -1000, 21885, -1000, - -1000, -1000, 21885, 227, 819, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 1625, 368, -1000, -1000, - -1000, 2693, -1000, 1625, 21885, 2197, -1000, 2197, 2197, 2197, - -1000, -1000, -1000, 21885, -1000, 21885, 21885, -1000, 21885, -1000, - 21885, -1000, -1000, -1000, -1000, 21885, 2081, 2437, 38675, 2081, - 38675, 2081, 32105, -1000, -1000, 2677, 2618, 2646, 2372, 2374, - 2374, 2376, -1000, 2645, 2621, -1000, 1688, 2606, 1630, 1019, - -1000, 54735, 21885, -1000, 249, 37945, -1000, 402, 54005, 249, - 54005, -1000, 2602, -1000, -1000, 21885, 2107, -1000, 21885, -1000, - -1000, -1000, -1000, 5149, 2679, 1998, -1000, -1000, 918, -1000, - 21885, -1000, 10275, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 1584, 1582, -1000, -1000, 2105, 21885, -1000, -1000, -1000, - 1746, 1728, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 2102, -1000, -1000, -1000, -1000, 356, -520, 2293, 54005, 1237, - -1000, 1680, 1980, 330, 249, 1540, 952, 952, 952, 1232, - 1220, 37945, 1676, -1000, 54005, 369, -1000, 356, -1000, -213, - -214, 1773, -1000, -1000, 2574, -1000, -1000, 16033, -1000, -1000, - 2094, 2198, -1000, -1000, -1000, -1000, 2322, -167, -196, -1000, - -1000, 1773, 1773, 1773, 1293, 1625, -1000, 1773, 1773, 1655, - 1648, -1000, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, - 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773, - 1773, 1773, 1616, 1781, -1000, 227, 1625, 2238, -1000, -1000, - 5149, -1000, -1000, 2602, 2604, 10, -1000, -1000, 246, 10, - 1182, 1007, 1625, 1625, 1007, 1756, 1773, 1751, 1739, 1773, - 1773, 32835, -1000, 2595, 2594, 1657, -1000, -1000, 38675, 1657, - 38675, 960, 2618, -294, 21885, 21885, 2365, 1254, -1000, -1000, - -1000, -1000, 1536, 1529, -1000, 1527, -1000, 2725, -1000, 1182, - -1000, 2081, 249, -1000, 532, 1820, -1000, 2576, 1182, 54005, - 1182, 83, 2602, -1000, 1773, -1000, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, 2081, - 2081, 2081, 2081, 2081, 2081, -1000, -1000, 54005, 2210, -1000, - -1000, 2563, 1665, 166, -1000, 1629, 1980, -1000, -1000, 209, - -1000, 21885, -1000, 37945, 1513, 1506, -1000, -1000, -1000, -1000, - -526, -1000, -1000, -1000, -1000, -1000, -1000, 408, 1976, -1000, - 944, 54005, 55465, -1000, 2267, -1000, -1000, -1000, -1000, 21885, + 21608, -1000, 21608, -1000, 21608, 1168, 21608, -1000, -1000, -1000, + -1000, -1000, 2451, 1480, 21608, 21608, -1000, 1222, 1211, -323, + 2617, -1000, -1000, -1000, 21608, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 21608, -1000, + 21608, -1000, 21608, -1000, 21608, -1000, 21608, -1000, 21608, -1000, + 21608, -1000, 21608, -1000, 21608, -1000, 21608, -1000, 21608, -1000, + 21608, -1000, 21608, -1000, 21608, -1000, 21608, -1000, 21608, -1000, + -1000, 21608, -1000, -1000, -1000, 21608, -1000, 21608, -1000, 21608, + -1000, -1000, -1000, 21608, 227, 985, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1380, 354, -1000, + -1000, -1000, 2518, -1000, 1380, 21608, 2215, -1000, 2215, 2215, + 2215, -1000, -1000, -1000, 21608, -1000, 21608, 21608, -1000, 21608, + -1000, 21608, -1000, -1000, -1000, -1000, 21608, 1914, 2229, 38582, + 1914, 38582, 1914, 31940, -1000, -1000, 2521, 2514, 2475, 2209, + 2221, 2221, 2257, -1000, 2474, 2471, -1000, 1477, 2470, 1474, + 1009, -1000, 54818, 21608, -1000, 238, 37844, -1000, 397, 54080, + 238, 54080, -1000, 2508, -1000, -1000, 21608, 1943, -1000, 21608, + -1000, -1000, -1000, -1000, 8224, 2515, 1832, -1000, -1000, 888, + -1000, 21608, -1000, 9940, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 1461, 1437, -1000, -1000, 1942, 21608, -1000, -1000, + -1000, 1713, 1624, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 1940, -1000, -1000, -1000, -1000, 351, -535, 2922, 54080, + 1203, -1000, 1581, 1852, 343, 238, 1422, 933, 933, 933, + 1197, 1186, 37844, 1542, -1000, 54080, 375, -1000, 351, -1000, + -262, -265, 2617, -1000, -1000, 2420, -1000, -1000, 15692, -1000, + -1000, 1934, 2041, -1000, -1000, -1000, -1000, 2155, -225, -243, + -1000, -1000, 2617, 2617, 2617, 1817, 1380, -1000, 2617, 2617, + 1543, 1430, -1000, -1000, 2617, 2617, 2617, 2617, 2617, 2617, + 2617, 2617, 2617, 2617, 2617, 2617, 2617, 2617, 2617, 2617, + 2617, 2617, 2617, 2617, 1458, 1737, -1000, 227, 1380, 2076, + -1000, -1000, 8224, -1000, -1000, 2508, 2469, 1, -1000, -1000, + 230, 1, 1168, 977, 1380, 1380, 977, 1712, 2617, 1683, + 1652, 2617, 2617, 32678, -1000, 2466, 2462, 1526, -1000, -1000, + 38582, 1526, 38582, 937, 2514, -332, 21608, 21608, 2195, 1218, + -1000, -1000, -1000, -1000, 1419, 1418, -1000, 1406, -1000, 2561, + -1000, 1168, -1000, 1914, 238, -1000, 787, 1804, -1000, 2451, + 1168, 54080, 1168, 34, 2508, -1000, 2617, -1000, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, + 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, 1914, -1000, + -1000, 54080, 2890, -1000, -1000, 2416, 1540, 162, -1000, 1383, + 1852, -1000, -1000, 221, -1000, 21608, -1000, 37844, 1404, 1392, + -1000, -1000, -1000, -1000, -544, -1000, -1000, -1000, -1000, -1000, + -1000, 398, 1850, -1000, 929, 54080, 55556, -1000, 2135, -1000, + -1000, -1000, -1000, 21608, -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, 21885, -1000, 1625, - 2236, -1000, -363, -1000, -493, 21885, -269, -1000, -1000, -269, - -1000, -1000, -1000, -1000, -1000, 21885, -1000, -1000, 21885, -1000, - 21885, -1000, -1000, 1657, -1000, -1000, -1000, 37215, -1000, 1657, - -1000, 1657, -1000, -294, -1000, 1974, -1000, 54005, 1182, 315, - -1000, 1196, -1000, -1000, -1000, -1000, -1000, 54735, 54005, 1820, - 54005, -1000, -1000, 1654, 1625, 2081, 2576, -1000, 1624, -1000, - 408, -1000, 2093, 2172, -1000, -1000, -1000, 19695, -1000, -1000, - -1000, -1000, -1000, 272, -175, 16033, 11617, 1619, -1000, -170, - 1773, 1616, -1000, -469, -1000, -1000, -1000, -1000, 297, -1000, - -1000, 1967, -1000, -1000, 1723, 1647, 1633, -1000, -1000, -1000, - -1000, -1000, -1000, -294, -1000, -1000, 2544, -1000, -235, -1000, - -1000, 1711, 1580, -1000, -1000, -1000, 32105, 53275, -1000, -161, - 353, -175, 21885, 2086, 1625, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -43, -1000, -1000, 518, -1000, -1000, -1000, - 2196, -194, -1000, -1000, -1000, 300, -483, -271, -272, 24075, - -1000, 21885, -1000, 21885, -1000, 21885, -1000, 54005, 2081, -1000, - -1000, -1000, 1578, -1000, 3903, -386, 2235, -1000, -139, -1000, - -1000, -1000, 1153, 1499, -1000, -1000, -1000, -1000, -1000, -1000, - 2052, 54005, -1000, 449, -1000, -1000, 15297, -179, -198, 1008, - -1000, -1000, -1000, -1000, -1000, 2197, 1614, 1606, 1773, -1000, - 54005, -1000, 53275, -381, 901, 5149, -1000, 2232, 2220, 2683, - -1000, -1000, -1000, -1000, -1000, -1000, -535, 1489, 286, -1000, - -1000, -1000, 300, -283, -1000, 21885, -1000, 21885, -1000, 1625, - -1000, -1000, 2533, 83, -1000, 2714, -1000, 2708, 1069, 1069, - -1000, 1215, -535, -1000, -1000, -1000, -1000, 1773, 1773, -1000, - -388, -1000, -1000, -1000, -1000, -1000, 441, 1265, -1000, -1000, - -1000, -1000, -1000, 5149, -1000, -1000, -1000, 230, 230, -1000, - -1000, + -1000, 21608, -1000, 1380, 2075, -1000, -375, -1000, -512, 21608, + -323, -1000, -1000, -323, -1000, -1000, -1000, -1000, -1000, 21608, + -1000, -1000, 21608, -1000, 21608, -1000, -1000, 1526, -1000, -1000, + -1000, 37106, -1000, 1526, -1000, 1526, -1000, -332, -1000, 1846, + -1000, 54080, 1168, 403, -1000, 1144, -1000, -1000, -1000, -1000, + -1000, 54818, 54080, 1804, 54080, -1000, -1000, 1507, 1380, 1914, + 2451, -1000, 1467, -1000, 398, -1000, 1917, 2030, -1000, -1000, + -1000, 19394, -1000, -1000, -1000, -1000, -1000, 263, -230, 15692, + 11228, 1465, -1000, -229, 2617, 1458, -1000, -477, -1000, -1000, + -1000, -1000, 255, -1000, -1000, 1839, -1000, -1000, 1623, 1579, + 1552, -1000, -1000, -1000, -1000, -1000, -1000, -332, -1000, -1000, + 2413, -1000, -270, -1000, -1000, 1838, 1442, -1000, -1000, -1000, + 31940, 53342, -1000, -218, 295, -230, 21608, 1915, 1380, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -56, -1000, -1000, + 542, -1000, -1000, -1000, 2013, -241, -1000, -1000, -1000, 272, + -495, -367, -371, 23822, -1000, 21608, -1000, 21608, -1000, 21608, + -1000, 54080, 1914, -1000, -1000, -1000, 1428, -1000, 4937, -387, + 2072, -1000, -150, -1000, -1000, -1000, 1093, 1368, -1000, -1000, + -1000, -1000, -1000, -1000, 2881, 54080, -1000, 441, -1000, -1000, + 14948, -237, -246, 991, -1000, -1000, -1000, -1000, -1000, 2215, + 1529, 1425, 2617, -1000, 54080, -1000, 53342, -391, 873, 8224, + -1000, 2070, 2064, 2565, -1000, -1000, -1000, -1000, -1000, -1000, + -548, 1377, 265, -1000, -1000, -1000, 272, -378, -1000, 21608, + -1000, 21608, -1000, 1380, -1000, -1000, 2398, 34, -1000, 2556, + -1000, 2551, 1024, 1024, -1000, 1171, -548, -1000, -1000, -1000, + -1000, 2617, 2617, -1000, -392, -1000, -1000, -1000, -1000, -1000, + 422, 1265, -1000, -1000, -1000, -1000, -1000, 8224, -1000, -1000, + -1000, 214, 214, -1000, -1000, } var yyPgo = [...]int{ - 0, 3389, 3388, 25, 9, 41, 38, 3387, 3385, 3382, - 174, 3380, 3379, 3377, 3376, 3375, 3374, 2765, 2758, 2757, - 3373, 3367, 3363, 3362, 3357, 3355, 3354, 3353, 3346, 50, - 103, 81, 101, 212, 204, 3344, 172, 157, 198, 3343, - 3336, 3320, 113, 186, 80, 82, 194, 3318, 3313, 69, - 3245, 3242, 3238, 183, 181, 180, 1047, 3237, 178, 112, - 45, 3236, 3227, 3224, 3223, 3222, 3220, 3216, 3215, 3214, - 3213, 3211, 3210, 3209, 3208, 3207, 3194, 3193, 3192, 278, - 3189, 3185, 21, 3184, 73, 3183, 3181, 3180, 3179, 3173, - 6, 3172, 3169, 26, 34, 65, 3165, 3163, 44, 3161, - 3160, 3159, 3158, 3153, 76, 3145, 13, 3144, 33, 3143, - 3140, 124, 3138, 3137, 3133, 40, 3132, 3131, 3127, 14, - 165, 3125, 3120, 139, 3119, 3118, 3117, 163, 219, 3116, - 2348, 3114, 97, 3113, 3112, 3110, 162, 195, 3109, 119, - 3103, 3102, 3100, 145, 3099, 3301, 3098, 3097, 72, 63, - 201, 3096, 3095, 199, 77, 5, 3091, 19, 20, 3089, - 3088, 74, 67, 3082, 104, 3081, 3078, 100, 91, 3076, - 96, 90, 3075, 3074, 8, 10, 3071, 1, 4, 2, - 108, 3062, 3054, 114, 3052, 3051, 3049, 98, 3048, 3046, - 7060, 3044, 83, 132, 99, 68, 3041, 166, 125, 3039, - 3038, 3033, 3026, 3025, 3020, 49, 3019, 3018, 3017, 136, - 1264, 109, 3016, 149, 362, 51, 147, 3015, 190, 75, - 197, 170, 3012, 3011, 134, 129, 3009, 3008, 59, 164, - 192, 3007, 94, 128, 117, 179, 92, 130, 3006, 3003, - 56, 60, 3002, 3001, 2999, 2992, 171, 2990, 2983, 64, - 2982, 54, 2981, 168, 2977, 339, 55, 2971, 182, 156, - 2966, 62, 2964, 2951, 87, 95, 58, 30, 2950, 155, - 159, 126, 184, 2949, 2947, 52, 2941, 2940, 2937, 196, - 319, 2931, 2921, 250, 176, 142, 146, 85, 2917, 337, - 2906, 2905, 16, 4449, 6490, 185, 37, 161, 2904, 2901, - 7709, 46, 42, 24, 2900, 205, 2892, 187, 2889, 2887, - 2886, 226, 206, 110, 158, 57, 2882, 2880, 2872, 2871, - 39, 2870, 2867, 2848, 2847, 2846, 2844, 36, 35, 32, - 71, 215, 61, 27, 131, 152, 151, 66, 2840, 2839, - 2836, 121, 93, 2833, 154, 153, 123, 102, 2832, 177, - 141, 118, 2830, 105, 31, 2823, 2822, 2821, 2820, 89, - 2819, 2814, 2811, 2810, 150, 143, 120, 78, 2809, 79, - 116, 148, 144, 48, 2802, 43, 2793, 2792, 29, 193, - 28, 2790, 18, 106, 115, 2789, 6331, 2788, 12, 328, - 160, 2787, 2784, 7, 15, 22, 2781, 2779, 2778, 2775, - 133, 2774, 2772, 2770, 2769, 23, 47, 11, 17, 111, - 138, 70, 2766, 2764, 140, 2759, 2753, 2747, 0, 1034, - 127, 2745, 200, + 0, 3161, 3157, 29, 6, 37, 36, 3156, 3154, 3152, + 167, 3150, 3147, 3145, 3137, 3136, 3135, 2600, 2595, 2594, + 3132, 3131, 3128, 3121, 3120, 3119, 3116, 3111, 3104, 40, + 91, 200, 103, 193, 186, 3100, 171, 154, 187, 3099, + 3096, 3095, 113, 183, 75, 81, 184, 3084, 3083, 68, + 3082, 3081, 3079, 178, 177, 176, 1061, 3078, 175, 112, + 48, 3075, 3073, 3067, 3061, 3054, 3051, 3049, 3040, 3039, + 3038, 3037, 3034, 3032, 3029, 3027, 3026, 3025, 3022, 259, + 3020, 3017, 15, 3014, 66, 3013, 3012, 3010, 3009, 3008, + 8, 3007, 3005, 12, 39, 55, 3002, 2999, 41, 2998, + 2996, 2993, 2991, 2990, 78, 2975, 13, 2974, 38, 2971, + 2970, 120, 2963, 2960, 2958, 44, 2957, 2954, 2952, 10, + 161, 2951, 2950, 134, 2949, 2944, 2939, 160, 192, 2938, + 2206, 2937, 96, 2936, 2935, 2934, 159, 185, 2931, 116, + 2930, 2929, 2924, 144, 2923, 3292, 2921, 2920, 64, 67, + 168, 2919, 2916, 202, 80, 7, 2908, 21, 22, 2907, + 2905, 71, 61, 2896, 104, 2895, 2888, 95, 85, 2887, + 93, 90, 2883, 2874, 9, 5, 2872, 1, 4, 2, + 114, 2867, 2864, 108, 2863, 2861, 2856, 84, 2854, 2851, + 3901, 2850, 87, 126, 98, 62, 2848, 169, 165, 2840, + 2839, 2838, 2837, 2836, 2835, 47, 2833, 2831, 2830, 131, + 1482, 99, 2829, 150, 351, 49, 146, 2828, 214, 73, + 196, 162, 2827, 2826, 130, 129, 2825, 2822, 53, 166, + 194, 2821, 92, 125, 115, 189, 89, 127, 2816, 2813, + 58, 70, 2808, 2806, 2805, 2803, 164, 2802, 2793, 63, + 2792, 52, 2791, 163, 2789, 336, 79, 2788, 182, 155, + 2787, 59, 2786, 2785, 100, 101, 57, 34, 2781, 152, + 157, 121, 153, 2780, 2779, 50, 2776, 2775, 2774, 190, + 274, 2773, 2770, 319, 172, 137, 143, 76, 2768, 262, + 2766, 2765, 2760, 18, 5110, 7071, 181, 27, 158, 2759, + 2754, 1065, 42, 56, 26, 2753, 210, 2752, 188, 2749, + 2748, 2735, 195, 206, 106, 156, 54, 2734, 2733, 2730, + 2729, 69, 2728, 2726, 2715, 2711, 2709, 2708, 35, 33, + 32, 102, 225, 60, 30, 94, 148, 147, 65, 2704, + 2703, 2701, 118, 72, 2698, 151, 149, 119, 97, 2696, + 173, 138, 110, 2695, 296, 31, 2669, 2666, 2663, 2662, + 83, 2661, 2660, 2659, 2657, 145, 139, 117, 77, 2656, + 74, 124, 142, 140, 51, 2653, 46, 2652, 2651, 28, + 180, 16, 2648, 20, 105, 111, 2645, 6183, 2644, 11, + 260, 141, 2643, 2640, 14, 17, 24, 2639, 2632, 2630, + 2629, 128, 2627, 2626, 2619, 2617, 25, 45, 23, 19, + 109, 133, 82, 2616, 2614, 136, 2612, 2611, 2599, 0, + 1040, 123, 2593, 199, } -//line sql.y:8680 +//line sql.y:8739 type yySymType struct { union any empty struct{} @@ -8468,122 +8497,123 @@ func (st *yySymType) withUnion() *With { } var yyR1 = [...]int{ - 0, 416, 417, 417, 7, 7, 7, 7, 7, 7, + 0, 417, 418, 418, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 261, 386, 259, 259, 28, 74, 36, 36, 35, + 7, 261, 387, 259, 259, 28, 74, 36, 36, 35, 35, 38, 38, 37, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 29, 29, 29, 29, 30, 30, 30, 30, 30, 15, 16, 34, 34, 17, 17, 109, 109, 18, 19, 19, - 19, 19, 420, 420, 185, 185, 183, 183, 184, 184, + 19, 19, 421, 421, 185, 185, 183, 183, 184, 184, 264, 264, 20, 268, 268, 270, 270, 270, 270, 260, 260, 260, 21, 21, 269, 269, 271, 271, 271, 274, - 274, 274, 274, 314, 314, 314, 22, 22, 22, 22, - 22, 129, 129, 388, 388, 387, 382, 382, 381, 381, - 380, 385, 385, 384, 384, 383, 40, 41, 50, 50, - 50, 50, 51, 52, 389, 389, 355, 57, 57, 56, + 274, 274, 274, 315, 315, 315, 22, 22, 22, 22, + 22, 129, 129, 389, 389, 388, 383, 383, 382, 382, + 381, 386, 386, 385, 385, 384, 40, 41, 50, 50, + 50, 50, 51, 52, 390, 390, 356, 57, 57, 56, 56, 56, 56, 56, 56, 58, 58, 54, 54, 53, - 53, 55, 55, 357, 357, 343, 343, 356, 356, 356, - 356, 356, 356, 356, 342, 342, 140, 140, 238, 238, + 53, 55, 55, 358, 358, 344, 344, 357, 357, 357, + 357, 357, 357, 357, 343, 343, 140, 140, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, - 238, 238, 238, 238, 238, 404, 404, 404, 403, 403, + 238, 238, 238, 238, 238, 405, 405, 405, 404, 404, 239, 239, 239, 239, 239, 239, 239, 239, 149, 149, 161, 161, 161, 161, 161, 161, 147, 147, 148, 146, 146, 146, 154, 154, 154, 154, 154, 154, 154, 154, - 154, 154, 154, 154, 154, 154, 154, 154, 154, 408, - 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, - 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, - 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, - 408, 408, 408, 408, 408, 408, 408, 408, 408, 408, - 408, 160, 160, 155, 155, 155, 157, 157, 156, 156, - 156, 158, 158, 405, 405, 405, 405, 320, 320, 320, - 320, 323, 323, 321, 321, 321, 321, 321, 321, 321, - 321, 321, 322, 322, 322, 322, 322, 322, 322, 324, - 324, 324, 324, 324, 325, 325, 325, 325, 325, 325, - 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, - 326, 326, 326, 326, 326, 326, 326, 326, 341, 341, - 330, 330, 335, 335, 336, 336, 337, 337, 337, 338, - 338, 338, 339, 339, 332, 332, 332, 332, 332, 332, - 332, 332, 332, 334, 334, 333, 333, 333, 344, 369, - 369, 368, 368, 366, 366, 366, 366, 366, 366, 366, - 366, 353, 353, 363, 363, 363, 363, 363, 352, 352, - 348, 348, 348, 349, 349, 350, 350, 347, 347, 351, - 351, 365, 365, 364, 364, 345, 345, 346, 346, 371, - 406, 406, 406, 406, 406, 407, 407, 372, 396, 398, - 398, 398, 397, 397, 394, 395, 393, 393, 393, 393, - 393, 84, 84, 84, 287, 287, 288, 288, 361, 361, - 360, 360, 360, 362, 362, 359, 359, 359, 359, 359, - 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, - 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, - 359, 359, 359, 359, 359, 359, 282, 282, 282, 392, - 392, 392, 392, 392, 392, 391, 391, 391, 358, 358, - 358, 358, 390, 390, 59, 59, 219, 219, 409, 409, - 411, 411, 411, 47, 47, 47, 47, 47, 47, 46, - 46, 46, 42, 42, 42, 42, 42, 42, 42, 42, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 409, + 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, + 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, + 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, + 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, + 409, 160, 160, 155, 155, 155, 157, 157, 156, 156, + 156, 158, 158, 406, 406, 406, 406, 321, 321, 321, + 321, 324, 324, 322, 322, 322, 322, 322, 322, 322, + 322, 322, 323, 323, 323, 323, 323, 323, 323, 325, + 325, 325, 325, 325, 326, 326, 326, 326, 326, 326, + 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, + 326, 327, 327, 327, 327, 327, 327, 327, 327, 342, + 342, 331, 331, 336, 336, 337, 337, 338, 338, 338, + 339, 339, 339, 340, 340, 333, 333, 333, 333, 333, + 333, 333, 333, 333, 335, 335, 334, 334, 334, 345, + 370, 370, 369, 369, 367, 367, 367, 367, 367, 367, + 367, 367, 354, 354, 364, 364, 364, 364, 364, 353, + 353, 349, 349, 349, 350, 350, 351, 351, 348, 348, + 352, 352, 366, 366, 365, 365, 346, 346, 347, 347, + 372, 407, 407, 407, 407, 407, 408, 408, 373, 397, + 399, 399, 399, 398, 398, 395, 396, 394, 394, 394, + 394, 394, 84, 84, 84, 287, 287, 288, 288, 362, + 362, 361, 361, 361, 363, 363, 360, 360, 360, 360, + 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, + 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, + 360, 360, 360, 360, 360, 360, 360, 282, 282, 282, + 393, 393, 393, 393, 393, 393, 392, 392, 392, 359, + 359, 359, 359, 391, 391, 59, 59, 219, 219, 410, + 410, 412, 412, 412, 47, 47, 47, 47, 47, 47, + 46, 46, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 48, 48, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 43, 23, 23, 23, 23, 23, + 42, 42, 42, 42, 48, 48, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 111, 111, 112, - 112, 112, 112, 114, 114, 114, 374, 374, 60, 60, - 3, 3, 173, 175, 176, 176, 174, 174, 174, 174, - 174, 174, 62, 62, 61, 61, 178, 177, 179, 179, - 179, 1, 1, 2, 2, 4, 4, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 340, - 340, 340, 373, 373, 375, 113, 113, 113, 113, 113, - 113, 113, 113, 113, 113, 117, 116, 116, 115, 118, - 118, 118, 118, 118, 118, 118, 118, 377, 377, 377, - 63, 63, 378, 327, 328, 329, 5, 6, 354, 376, - 125, 125, 24, 39, 39, 25, 25, 25, 25, 26, - 26, 64, 67, 67, 65, 65, 65, 65, 65, 65, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 111, + 111, 112, 112, 112, 112, 114, 114, 114, 375, 375, + 60, 60, 3, 3, 173, 175, 176, 176, 174, 174, + 174, 174, 174, 174, 62, 62, 61, 61, 178, 177, + 179, 179, 179, 1, 1, 2, 2, 4, 4, 380, + 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, + 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, + 380, 341, 341, 341, 374, 374, 376, 113, 113, 113, + 113, 113, 113, 113, 113, 113, 113, 117, 116, 116, + 115, 118, 118, 118, 118, 118, 118, 118, 118, 378, + 378, 378, 63, 63, 379, 328, 329, 330, 5, 6, + 355, 377, 125, 125, 24, 39, 39, 25, 25, 25, + 25, 26, 26, 64, 67, 67, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 281, 281, 290, - 290, 280, 280, 305, 305, 305, 283, 283, 283, 284, - 284, 402, 402, 402, 277, 277, 66, 66, 66, 306, - 306, 306, 306, 69, 69, 412, 412, 413, 413, 414, - 414, 414, 70, 71, 71, 309, 309, 310, 310, 72, - 73, 85, 85, 85, 85, 85, 86, 86, 86, 86, - 110, 110, 110, 10, 10, 10, 10, 81, 81, 81, - 9, 9, 11, 68, 68, 75, 399, 399, 400, 401, - 401, 401, 401, 76, 78, 27, 27, 27, 27, 27, - 27, 135, 135, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 130, 130, 130, 124, 124, - 421, 79, 80, 80, 128, 128, 128, 121, 121, 121, - 127, 127, 127, 12, 12, 13, 263, 263, 14, 14, - 134, 134, 133, 133, 136, 136, 136, 136, 136, 136, - 136, 131, 131, 132, 132, 132, 132, 298, 298, 298, - 297, 297, 167, 167, 169, 168, 168, 170, 170, 171, - 171, 171, 171, 217, 217, 193, 193, 256, 256, 257, - 257, 255, 255, 262, 262, 258, 258, 258, 258, 265, - 265, 172, 172, 172, 172, 180, 180, 181, 181, 182, - 182, 308, 308, 303, 303, 303, 302, 302, 186, 186, - 186, 188, 187, 187, 187, 187, 189, 189, 191, 191, - 190, 190, 192, 197, 197, 196, 196, 194, 194, 194, - 194, 194, 194, 195, 195, 195, 195, 198, 198, 145, - 145, 145, 145, 145, 145, 145, 145, 410, 410, 159, - 159, 159, 159, 159, 159, 159, 162, 162, 162, 162, - 162, 162, 162, 162, 162, 162, 162, 246, 246, 150, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 292, 292, 281, 281, 290, 290, 280, 280, 306, 306, + 306, 283, 283, 283, 284, 284, 403, 403, 403, 277, + 277, 66, 66, 66, 307, 307, 307, 307, 69, 69, + 413, 413, 414, 414, 415, 415, 415, 70, 71, 71, + 310, 310, 311, 311, 72, 73, 85, 85, 85, 85, + 85, 86, 86, 86, 86, 110, 110, 110, 10, 10, + 10, 10, 81, 81, 81, 9, 9, 11, 68, 68, + 75, 400, 400, 401, 402, 402, 402, 402, 76, 78, + 27, 27, 27, 27, 27, 27, 135, 135, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 130, 130, 130, 124, 124, 422, 79, 80, 80, 128, + 128, 128, 121, 121, 121, 127, 127, 127, 12, 12, + 13, 263, 263, 14, 14, 134, 134, 133, 133, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 131, 131, 132, 132, 132, 132, 299, 299, 299, 298, + 298, 167, 167, 169, 168, 168, 170, 170, 171, 171, + 171, 171, 217, 217, 193, 193, 256, 256, 257, 257, + 255, 255, 262, 262, 258, 258, 258, 258, 265, 265, + 172, 172, 172, 172, 180, 180, 181, 181, 182, 182, + 309, 309, 304, 304, 304, 303, 303, 186, 186, 186, + 188, 187, 187, 187, 187, 189, 189, 191, 191, 190, + 190, 192, 197, 197, 196, 196, 194, 194, 194, 194, + 194, 194, 195, 195, 195, 195, 198, 198, 145, 145, + 145, 145, 145, 145, 145, 145, 411, 411, 159, 159, + 159, 159, 159, 159, 159, 162, 162, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 246, 246, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, - 150, 150, 150, 150, 153, 153, 153, 153, 153, 153, + 150, 150, 150, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, - 153, 153, 153, 153, 153, 153, 153, 153, 153, 222, - 222, 221, 221, 87, 87, 87, 88, 88, 89, 89, - 89, 89, 89, 90, 90, 90, 90, 90, 90, 90, - 92, 92, 91, 91, 212, 212, 295, 295, 93, 94, - 94, 95, 95, 98, 98, 97, 96, 96, 102, 102, - 99, 99, 101, 101, 100, 103, 103, 104, 105, 105, - 278, 278, 199, 199, 208, 208, 208, 208, 200, 200, - 201, 201, 201, 201, 201, 201, 209, 209, 209, 216, - 210, 210, 206, 206, 204, 204, 204, 204, 204, 204, - 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, + 153, 153, 153, 153, 153, 153, 153, 153, 222, 222, + 221, 221, 87, 87, 87, 88, 88, 89, 89, 89, + 89, 89, 90, 90, 90, 90, 90, 90, 90, 92, + 92, 91, 91, 212, 212, 296, 296, 93, 94, 94, + 95, 95, 98, 98, 97, 96, 96, 102, 102, 99, + 99, 101, 101, 100, 103, 103, 104, 105, 105, 278, + 278, 199, 199, 208, 208, 208, 208, 200, 200, 201, + 201, 201, 201, 201, 201, 209, 209, 209, 216, 210, + 210, 206, 206, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, @@ -8602,82 +8632,36 @@ var yyR1 = [...]int{ 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, - 205, 205, 205, 205, 205, 205, 164, 164, 164, 164, - 227, 227, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 152, 152, 165, - 165, 165, 165, 166, 166, 166, 166, 166, 166, 166, - 316, 316, 119, 119, 119, 119, 119, 119, 119, 119, + 205, 205, 205, 205, 205, 205, 205, 164, 164, 164, + 164, 227, 227, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 152, 152, + 165, 165, 165, 165, 166, 166, 166, 166, 166, 166, + 166, 317, 317, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 120, 120, 120, 120, 120, 120, 120, 120, + 119, 119, 119, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 422, 422, 331, 331, 331, 207, 207, 207, 207, 207, - 126, 126, 126, 126, 126, 313, 313, 313, 317, 317, - 317, 315, 315, 315, 315, 315, 315, 315, 315, 315, - 315, 315, 315, 315, 315, 315, 318, 318, 225, 225, - 122, 122, 223, 223, 224, 226, 226, 218, 218, 218, - 218, 220, 220, 203, 203, 203, 228, 228, 319, 319, - 229, 229, 106, 107, 107, 108, 108, 230, 230, 232, - 231, 231, 233, 234, 234, 234, 235, 235, 236, 236, - 236, 49, 49, 49, 49, 49, 44, 44, 44, 44, - 45, 45, 45, 45, 137, 137, 137, 137, 139, 139, - 138, 138, 82, 82, 83, 83, 83, 143, 143, 144, - 144, 144, 141, 141, 142, 142, 253, 253, 253, 253, - 253, 253, 253, 237, 237, 237, 244, 244, 244, 240, - 240, 242, 242, 242, 243, 243, 243, 241, 250, 250, - 252, 252, 251, 251, 247, 247, 248, 248, 249, 249, - 249, 245, 245, 202, 202, 202, 202, 202, 254, 254, - 254, 254, 307, 307, 307, 266, 266, 213, 213, 215, - 215, 214, 214, 163, 267, 267, 275, 272, 272, 273, - 273, 299, 299, 299, 276, 276, 289, 289, 285, 285, - 286, 286, 279, 279, 291, 291, 291, 77, 211, 211, - 370, 370, 367, 294, 294, 296, 296, 300, 300, 304, - 304, 301, 301, 8, 415, 415, 415, 292, 292, 292, - 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, - 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, - 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, - 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, - 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, - 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, - 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, - 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, - 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, - 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, - 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, - 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, - 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, - 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, - 292, 292, 292, 292, 292, 292, 292, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, + 120, 423, 423, 332, 332, 332, 207, 207, 207, 207, + 207, 126, 126, 126, 126, 126, 314, 314, 314, 318, + 318, 318, 316, 316, 316, 316, 316, 316, 316, 316, + 316, 316, 316, 316, 316, 316, 316, 319, 319, 225, + 225, 122, 122, 223, 223, 224, 226, 226, 218, 218, + 218, 218, 220, 220, 203, 203, 203, 228, 228, 320, + 320, 229, 229, 106, 107, 107, 108, 108, 230, 230, + 232, 231, 231, 233, 234, 234, 234, 235, 235, 236, + 236, 236, 49, 49, 49, 49, 49, 44, 44, 44, + 44, 45, 45, 45, 45, 137, 137, 137, 137, 139, + 139, 138, 138, 82, 82, 83, 83, 83, 143, 143, + 144, 144, 144, 141, 141, 142, 142, 253, 253, 253, + 253, 253, 253, 253, 237, 237, 237, 244, 244, 244, + 240, 240, 242, 242, 242, 243, 243, 243, 241, 250, + 250, 252, 252, 251, 251, 247, 247, 248, 248, 249, + 249, 249, 245, 245, 202, 202, 202, 202, 202, 254, + 254, 254, 254, 308, 308, 308, 266, 266, 213, 213, + 215, 215, 214, 214, 163, 267, 267, 275, 272, 272, + 273, 273, 300, 300, 300, 276, 276, 289, 289, 285, + 285, 286, 286, 279, 279, 291, 291, 291, 77, 211, + 211, 371, 371, 368, 295, 295, 297, 297, 301, 301, + 305, 305, 302, 302, 8, 416, 416, 416, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, @@ -8693,8 +8677,55 @@ var yyR1 = [...]int{ 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 418, 419, 311, - 312, 312, 312, + 293, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, + 294, 294, 294, 294, 294, 419, 420, 312, 313, 313, + 313, } var yyR2 = [...]int{ @@ -8732,136 +8763,137 @@ var yyR2 = [...]int{ 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, 2, - 2, 2, 2, 1, 1, 1, 1, 1, 5, 5, + 2, 2, 2, 1, 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, 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, + 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, 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, - 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, 7, 5, 5, 5, 5, - 5, 7, 7, 5, 5, 5, 5, 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, 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, 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, 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, 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, + 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, 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, + 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, 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, - 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, 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, + 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, 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, 1, 1, 1, 1, 1, 1, + 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, 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, 3, 3, 3, 0, 3, - 1, 1, 0, 4, 0, 1, 1, 0, 3, 1, - 3, 2, 1, 1, 0, 1, 2, 3, 4, 2, - 3, 4, 4, 9, 3, 5, 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, - 2, 3, 4, 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, 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, 3, 3, 3, 0, + 3, 1, 1, 0, 4, 0, 1, 1, 0, 3, + 1, 3, 2, 1, 1, 0, 1, 2, 3, 4, + 2, 3, 4, 4, 9, 3, 5, 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, 2, 3, 4, 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, @@ -8923,872 +8955,879 @@ var yyR2 = [...]int{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, - 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, + 1, } var yyChk = [...]int{ - -1000, -416, -79, -421, -7, -29, -15, -16, -17, -18, + -1000, -417, -79, -422, -7, -29, -15, -16, -17, -18, -19, -20, -21, -22, -23, -24, -25, -26, -64, -67, -65, -66, -69, -70, -71, -72, -73, -9, -11, -68, -27, -28, -74, -75, -76, -77, -78, -12, -13, -14, - -8, -32, -31, -30, 12, 13, -109, -35, 34, -40, - -50, 232, -51, -41, 233, -52, 235, 234, 272, 236, - 385, 265, 79, 321, 322, 324, 325, 326, 327, -110, - 692, 270, 271, 238, 38, 50, 35, 36, 39, 242, - 278, 279, 241, 138, -33, -36, 11, -418, 14, 475, - 267, 266, 30, -34, 585, 91, -80, -417, 740, -253, - -237, 25, 35, 31, -236, -232, -128, -237, 23, 21, - 10, -79, -79, -79, 15, 16, -79, -355, -357, 91, - 165, 91, -79, -57, -56, -54, -53, -55, -58, 33, - -47, -48, -379, -46, -43, 237, 234, 282, 128, 129, - 272, 273, 274, 236, 256, 271, 275, 270, 291, -42, - 86, 35, 585, 588, -362, 233, 239, 240, 235, 476, - 131, 130, 80, -359, 380, 619, 710, -58, 712, 105, - 108, 711, 49, 246, 713, 714, 715, 626, 716, 255, - 717, 718, 719, 720, 726, 667, 727, 728, 729, 132, - 10, -79, -304, -300, 95, -293, 582, 258, 617, 429, - 618, 307, 86, 46, 41, 521, 592, 377, 380, 619, - 506, 710, 386, 321, 337, 331, 511, 512, 513, 360, - 352, 583, 620, 593, 310, 259, 295, 704, 350, 141, - 712, 314, 621, 273, 387, 388, 622, 389, 105, 324, - 426, 725, 313, 623, 723, 108, 711, 329, 84, 505, - 56, 707, 49, 268, 434, 435, 348, 241, 344, 713, - 296, 624, 595, 289, 131, 128, 732, 38, 340, 55, - 32, 722, 130, 54, 714, 156, 625, 715, 626, 391, - 367, 698, 53, 392, 274, 627, 89, 279, 587, 318, - 706, 393, 526, 341, 394, 306, 721, 238, 628, 317, - 687, 679, 680, 395, 396, 699, 372, 368, 373, 528, - 629, 418, 510, 397, 683, 684, 739, 57, 630, 631, - 700, 129, 632, 83, 716, 85, 335, 336, 633, 304, - 257, 531, 532, 420, 364, 488, 495, 496, 115, 116, - 491, 117, 497, 118, 498, 499, 500, 489, 119, 112, - 490, 501, 502, 365, 366, 120, 503, 114, 113, 492, - 494, 121, 504, 255, 37, 398, 584, 308, 63, 312, - 283, 421, 51, 370, 736, 50, 694, 533, 634, 697, - 363, 359, 485, 58, 635, 636, 637, 638, 507, 717, - 362, 334, 358, 731, 4, 301, 480, 508, 718, 67, - 240, 375, 374, 376, 290, 417, 355, 639, 640, 641, - 262, 87, 642, 345, 24, 643, 644, 399, 297, 645, - 61, 646, 647, 424, 271, 648, 59, 719, 44, 649, - 276, 733, 720, 650, 651, 652, 693, 653, 278, 654, - 401, 655, 681, 682, 400, 369, 371, 534, 285, 402, - 385, 243, 586, 656, 319, 339, 275, 724, 657, 263, - 522, 523, 524, 525, 705, 530, 529, 277, 282, 270, - 425, 264, 658, 659, 660, 661, 662, 311, 678, 663, - 664, 325, 590, 726, 486, 48, 665, 666, 667, 668, - 669, 305, 300, 419, 428, 66, 88, 382, 670, 671, - 703, 333, 330, 42, 298, 466, 468, 469, 470, 471, - 472, 467, 474, 672, 322, 60, 727, 728, 729, 292, - 730, 514, 515, 516, 517, 12, 568, 551, 579, 552, - 569, 553, 562, 554, 570, 578, 580, 535, 543, 536, - 544, 574, 557, 571, 563, 556, 555, 577, 560, 564, - 537, 545, 575, 561, 538, 546, 539, 547, 540, 548, - 573, 572, 565, 576, 541, 549, 567, 542, 550, 566, - 558, 559, 437, 737, 738, 509, 404, 132, 302, 303, - 52, 356, 284, 673, 315, 674, 346, 347, 482, 483, - 361, 332, 357, 690, 323, 688, 286, 405, 487, 272, - 675, 427, 299, 378, 124, 383, 316, 591, 527, 291, - 406, 702, 589, 518, 519, 354, 351, 293, 520, 676, - 692, 407, 247, 287, 288, 677, 689, 408, 409, 309, - 410, 411, 412, 413, 414, 416, 320, 415, 691, 685, - 686, 294, 465, 588, 328, 349, 384, 447, 448, 449, - 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, - 460, 461, 462, 463, 464, 484, 245, -79, 245, -190, - -300, -130, 694, 696, 184, -272, 388, -290, 390, 403, - 398, 408, 396, -281, 399, 401, 285, -402, 418, 245, - 405, 232, 391, 400, 409, 410, 309, 416, 411, 320, - 415, 294, 412, 413, 414, -386, 184, 715, 730, 141, - 353, 395, 393, 419, 694, 95, -306, 95, 96, 97, - -293, 323, -309, 328, -294, -386, -293, 326, -79, -79, - -311, -311, -130, -210, -145, 149, -159, -261, -162, 96, - -150, -153, -204, -205, -206, -207, -160, -220, -259, 173, - 174, 181, 150, -216, -163, 28, 581, 477, 476, 184, - 33, 227, 73, 74, 479, 480, 152, 62, 14, 442, - 443, -161, 432, 433, 444, 438, 439, 505, 507, 508, - 509, 506, 511, 512, 513, 514, 515, 516, 517, 518, - 519, 520, 510, 521, 482, 483, 122, 484, 112, 114, - 113, 485, 486, 487, 350, 533, 534, 528, 531, 532, - 530, 529, 365, 366, 488, 551, 552, 556, 555, 553, - 554, 557, 560, 561, 562, 563, 564, 565, 567, 566, - 558, 559, 536, 535, 537, 538, 539, 540, 541, 542, - 544, 543, 545, 546, 547, 548, 549, 550, 568, 569, - 570, 571, 572, 574, 573, 578, 577, 575, 576, 580, - 579, 489, 490, 115, 116, 117, 118, 119, 120, 121, - 491, 494, 492, 493, 495, 496, 497, 502, 503, 498, - 499, 500, 501, 504, 376, 374, 375, 371, 370, 369, - -89, -102, 608, 607, -103, 429, 434, 435, 437, -151, - -152, -165, -166, -294, -300, 250, 431, 244, 179, 475, - -154, -148, -218, 111, 97, -31, -214, 430, 440, 441, - 445, 436, 446, 594, 596, 611, 612, 614, 599, 604, - 603, 606, 522, 523, 524, 525, 526, 527, 679, 680, - 681, 682, 683, 684, 685, 686, -386, -293, 95, -157, - -155, -199, 98, 103, 106, 107, 109, -408, 268, 346, - 347, 123, -418, 708, -156, 100, 101, 102, 125, 126, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + -8, -32, -31, -30, 13, 14, -109, -35, 35, -40, + -50, 239, -51, -41, 240, -52, 242, 241, 279, 243, + 393, 272, 83, 328, 329, 331, 332, 333, 334, -110, + 700, 277, 278, 245, 39, 51, 36, 37, 40, 249, + 285, 286, 248, 145, -33, -36, 12, -419, 15, 483, + 274, 273, 31, -34, 593, 95, -80, -418, 748, -253, + -237, 26, 36, 32, -236, -232, -128, -237, 24, 22, + 11, -79, -79, -79, 16, 17, -79, -356, -358, 95, + 172, 95, -79, -57, -56, -54, -53, -55, -58, 34, + -47, -48, -380, -46, -43, 244, 241, 289, 135, 136, + 279, 280, 281, 243, 263, 278, 282, 277, 298, -42, + 90, 36, 593, 596, -363, 240, 246, 247, 242, 484, + 138, 137, 84, -360, 388, 627, 718, -58, 720, 110, + 113, 719, 50, 253, 721, 722, 723, 634, 724, 262, + 725, 726, 727, 728, 734, 675, 735, 736, 737, 139, + 11, -79, -305, -301, 100, -294, 590, 265, 625, 437, + 626, 314, 90, 47, 42, 529, 600, 384, 388, 627, + 514, 718, 394, 328, 344, 338, 519, 520, 521, 367, + 359, 591, 628, 601, 317, 266, 302, 712, 357, 148, + 720, 321, 629, 280, 395, 396, 630, 397, 110, 331, + 434, 733, 320, 631, 731, 113, 719, 336, 88, 513, + 57, 715, 50, 275, 442, 443, 355, 248, 351, 721, + 303, 632, 603, 296, 138, 135, 740, 39, 347, 56, + 33, 730, 137, 55, 722, 163, 633, 723, 634, 399, + 374, 706, 54, 400, 281, 635, 93, 286, 595, 325, + 714, 401, 534, 348, 402, 313, 729, 245, 636, 324, + 695, 687, 688, 403, 404, 707, 379, 375, 380, 536, + 637, 426, 518, 405, 691, 692, 747, 58, 638, 639, + 708, 136, 640, 87, 724, 89, 342, 343, 641, 311, + 264, 539, 540, 428, 371, 496, 127, 503, 504, 120, + 121, 499, 122, 505, 123, 128, 506, 507, 508, 497, + 124, 117, 498, 509, 510, 372, 373, 125, 511, 119, + 118, 500, 502, 126, 512, 262, 38, 406, 592, 315, + 64, 319, 290, 429, 52, 377, 744, 51, 702, 541, + 642, 705, 370, 366, 493, 59, 643, 644, 645, 646, + 515, 725, 369, 341, 365, 739, 4, 308, 488, 516, + 726, 68, 247, 382, 381, 383, 297, 425, 362, 647, + 648, 649, 269, 91, 650, 352, 25, 651, 652, 407, + 304, 653, 62, 654, 655, 432, 278, 656, 60, 727, + 45, 657, 283, 741, 728, 658, 659, 660, 701, 661, + 285, 662, 409, 663, 689, 690, 408, 376, 378, 542, + 292, 410, 393, 250, 594, 664, 326, 346, 282, 732, + 665, 270, 530, 531, 532, 533, 713, 538, 537, 284, + 289, 277, 433, 271, 666, 667, 668, 669, 670, 318, + 686, 671, 672, 332, 598, 734, 494, 49, 673, 674, + 675, 676, 677, 312, 307, 427, 436, 67, 92, 390, + 678, 679, 711, 340, 337, 43, 305, 99, 474, 476, + 477, 478, 479, 480, 475, 482, 680, 329, 61, 735, + 736, 737, 299, 738, 522, 523, 524, 525, 13, 576, + 559, 587, 560, 577, 561, 570, 562, 578, 586, 588, + 543, 551, 544, 552, 582, 565, 579, 571, 564, 563, + 585, 568, 572, 545, 553, 583, 569, 546, 554, 547, + 555, 548, 556, 581, 580, 573, 584, 549, 557, 575, + 550, 558, 574, 566, 567, 445, 745, 746, 517, 412, + 139, 309, 310, 53, 363, 291, 681, 322, 682, 353, + 354, 490, 491, 368, 339, 364, 698, 330, 696, 293, + 413, 495, 279, 683, 435, 306, 385, 131, 391, 323, + 599, 535, 298, 414, 710, 597, 526, 527, 361, 358, + 300, 528, 684, 386, 700, 415, 254, 294, 295, 685, + 697, 416, 417, 316, 418, 419, 420, 421, 422, 424, + 327, 423, 699, 693, 694, 301, 473, 596, 335, 356, + 392, 455, 456, 457, 458, 459, 460, 461, 462, 463, + 464, 465, 466, 467, 468, 469, 470, 471, 472, 492, + 252, -79, 252, -190, -301, -130, 702, 704, 191, -272, + 396, -290, 398, 411, 406, 416, 404, -281, 407, 409, + 292, -403, 426, 252, 413, 239, 399, 408, 417, 418, + 316, 424, 419, 327, 423, 301, 420, 421, 422, -387, + 191, 723, 738, 330, 148, 360, 403, 401, 427, 702, + 100, -307, 100, 101, 102, -294, 330, -310, 335, -295, + -387, -294, 333, -79, -79, -312, -312, -130, -210, -145, + 156, -159, -261, -162, 101, -150, -153, -204, -205, -206, + -207, -160, -220, -259, 180, 181, 188, 157, -216, -163, + 29, 589, 485, 484, 191, 34, 234, 77, 78, 487, + 488, 159, 63, 15, 450, 451, -161, 440, 441, 452, + 446, 447, 513, 515, 516, 517, 514, 519, 520, 521, + 522, 523, 524, 525, 526, 527, 528, 518, 529, 490, + 491, 129, 492, 117, 119, 118, 127, 128, 493, 494, + 495, 357, 541, 542, 536, 539, 540, 538, 537, 372, + 373, 496, 559, 560, 564, 563, 561, 562, 565, 568, + 569, 570, 571, 572, 573, 575, 574, 566, 567, 544, + 543, 545, 546, 547, 548, 549, 550, 552, 551, 553, + 554, 555, 556, 557, 558, 576, 577, 578, 579, 580, + 582, 581, 586, 585, 583, 584, 588, 587, 497, 498, + 120, 121, 122, 123, 124, 125, 126, 499, 502, 500, + 501, 503, 504, 505, 510, 511, 506, 507, 508, 509, + 512, 383, 381, 382, 378, 377, 376, -89, -102, 616, + 615, -103, 437, 442, 443, 445, -151, -152, -165, -166, + -295, -301, 257, 439, 251, 186, 483, -154, -148, -218, + 116, 102, -31, -214, 438, 448, 449, 453, 444, 454, + 602, 604, 619, 620, 622, 607, 612, 611, 614, 530, + 531, 532, 533, 534, 535, 687, 688, 689, 690, 691, + 692, 693, 694, -387, -294, 100, -157, -155, -199, 103, + 108, 111, 112, 114, -409, 275, 353, 354, 130, -419, + 716, -156, 105, 106, 107, 132, 133, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 94, 99, 49, 404, 404, -190, -79, -79, - -79, -79, -415, 711, 586, -230, -128, -232, -33, -31, - -418, 11, -79, -31, -32, -30, -36, -38, 613, -37, - -300, 104, -237, -253, 15, 66, 168, 47, 55, -235, - -236, -34, -31, -145, 22, 40, 26, -132, 175, -145, - -300, -132, -279, 249, -79, -79, -268, -314, 323, -270, - 419, 694, 418, -260, -273, 95, -259, -272, 417, 96, - -356, 165, -342, -346, -294, 260, -372, 256, -190, -365, - -364, -294, -418, -129, -289, 246, 254, 253, 142, -389, - 145, 302, 431, 244, -53, -54, -55, -272, 183, 714, - -111, 277, 281, 92, 92, -346, -345, -344, -390, 281, - 260, -371, -363, 252, 261, -352, 253, 254, -347, 246, - 143, -390, -347, 251, 261, 256, 260, 281, 281, 132, - 281, 132, 281, 281, 281, 281, 281, 281, 281, 281, - 281, 276, -353, 157, -353, 589, 589, -359, -390, 256, - 246, -390, -390, 252, -291, -347, 248, 27, 248, 37, - 37, -353, -353, -353, -272, 183, -353, -353, -353, -353, - 289, 289, -353, -353, -353, -353, -353, -353, -353, -353, - -353, -353, -353, -353, -353, -353, -353, -353, -353, 245, - -389, -137, 415, 309, 86, -56, 291, -39, -190, -289, - 246, 247, -389, 278, -190, 228, 245, 697, -283, 165, - 18, -283, -280, 404, 402, 389, 394, -283, -283, -283, - -283, 292, 387, -348, 246, 37, 257, 404, 292, 387, - 292, 293, 292, 293, 397, 407, 292, -305, 17, 168, - 431, 392, 396, 285, 245, 286, 247, 406, 293, -305, - 94, -284, 165, 292, 404, 398, 288, -283, -283, -312, - -418, -296, -294, -292, 237, 40, 148, 27, 29, 151, - 184, 135, 22, 152, 39, 239, 353, 256, 183, 252, - 476, 232, 77, 594, 432, 439, 430, 438, 442, 478, - 479, 431, 390, 33, 16, 596, 30, 266, 26, 43, - 177, 234, 155, 597, 269, 28, 267, 122, 126, 599, - 25, 80, 261, 17, 254, 45, 19, 600, 601, 20, - 250, 249, 168, 246, 75, 14, 227, 31, 164, 71, - 602, 143, 138, 603, 604, 605, 606, 136, 73, 165, - 23, 734, 440, 441, 35, 695, 581, 280, 179, 78, - 64, 696, 149, 436, 607, 608, 123, 609, 127, 81, - 701, 145, 21, 76, 47, 610, 281, 611, 251, 735, - 612, 422, 613, 166, 235, 475, 74, 167, 708, 614, - 709, 244, 403, 11, 481, 34, 265, 253, 134, 72, - 446, 615, 245, 154, 248, 137, 125, 10, 142, 36, - 15, 79, 82, 443, 444, 445, 62, 133, 585, 153, - 18, 616, 423, 147, -386, 697, -312, -312, 34, 96, - -412, -413, -414, 585, 422, 248, -294, -190, -85, 687, - 236, -86, 693, 40, 243, -135, 404, -123, 184, 715, - 698, 699, 700, 697, 401, 705, 703, 701, 292, 702, - 92, 145, 147, 148, 4, -145, 164, -200, -201, 163, - 157, 158, 159, 160, 161, 162, 169, 168, 149, 151, - 165, -246, 146, 170, 171, 172, 173, 174, 175, 176, - 178, 177, 179, 180, 166, 167, 183, 230, 231, -153, - -153, -153, -153, -216, -222, -221, -418, -218, -386, -293, - -300, -418, -418, -153, -278, -418, -150, -418, -418, -418, - -418, -418, -225, -145, -418, -418, -422, -418, -422, -422, - -422, -331, -418, -331, -331, -418, -418, -418, -418, -418, - -418, -418, -418, -418, -418, -418, -418, -418, -418, -418, - -418, -418, -418, -418, -418, -418, -418, -418, -418, -418, - -418, -418, -418, -418, -418, -418, -418, -418, -418, -418, - -418, -418, -418, -418, -418, -418, -418, -418, -418, -418, - -418, -418, -418, -418, -418, -418, -418, -418, -418, -418, - -418, -418, -418, -418, -418, -418, -418, -418, -418, -418, - -418, -418, -418, -418, -418, -418, -418, -418, -418, -418, - -418, -418, -418, -418, -418, -418, -418, -418, -418, -418, - -418, -418, -418, -418, -418, -418, -418, -418, -418, -418, - -418, -418, -418, -418, -418, -418, -418, -418, -418, -418, - -418, -418, -418, -418, -418, -418, -418, -418, -418, -418, - -418, -418, -418, -418, -418, -418, -418, -418, 228, -418, - -418, -418, -418, -418, -331, -331, -331, -331, -331, -331, - -418, -418, -418, -418, -418, -418, -418, -418, -418, -418, - -418, -418, -418, -418, 94, 107, 103, 106, 98, -220, - 109, 94, 94, 94, 94, -31, -32, -210, -418, -311, - -399, -400, -193, -190, -418, 309, -294, -294, 278, 100, - -235, -34, -31, -230, -236, -232, -31, -79, -121, -134, - 68, 69, -133, -136, 26, 43, 72, 70, 40, -419, - 93, -419, -253, -419, 92, -38, -256, 91, 641, 671, - 641, 671, 66, 48, 94, 94, 92, 24, -231, -233, - -145, 17, -298, 4, -297, 27, -294, 94, 228, 17, - -191, 31, -190, -279, -279, 92, 95, 323, -269, -271, - 420, 422, 157, -299, -294, 94, 33, 93, 92, -190, - -320, -323, -325, -324, -326, -321, -322, 350, 351, 184, - 354, 356, 357, 358, 359, 360, 361, 362, 363, 364, - 367, 34, 268, 346, 347, 348, 349, 368, 369, 370, - 371, 373, 374, 375, 376, 331, 352, 583, 332, 333, - 334, 335, 336, 337, 339, 340, 343, 341, 342, 344, - 345, -295, -294, 91, 93, 92, -330, 91, -145, -137, - 245, -294, 246, 246, 246, -79, 475, -353, -353, -353, - 276, 22, -46, -43, -379, 21, -42, -43, 237, 128, - 129, 234, 91, -342, 91, -351, -295, -294, 91, 143, - 251, 142, -350, -347, -350, -351, -294, -218, -294, 143, - 143, -294, -294, -265, -294, -265, -265, 40, -265, 40, - -265, 40, 100, -294, -265, 40, -265, 40, -265, 40, - -265, 40, -265, 40, 33, 83, 84, 85, 33, 87, - 88, 89, -218, -294, -294, -218, -342, -218, -190, -294, - -272, 100, 100, 100, -353, -353, 100, 94, 94, 94, - -353, -353, 100, 94, -302, -300, 94, 94, -391, 262, - 306, 308, 100, 100, 100, 100, 33, 94, -392, 33, - 722, 721, 723, 724, 725, 94, 100, 33, 100, 33, - 100, -294, 91, -190, -143, 296, 232, 234, 237, 81, - 94, 312, 313, 310, 315, 316, 317, 157, 49, 92, - 248, 245, -294, -285, 250, -285, -294, -301, -300, -292, - -190, 248, 386, 94, -145, -349, 17, 168, -305, -305, - -283, -190, -349, -305, -283, -190, -283, -283, -283, -283, - -305, -305, -305, -283, -300, -300, -190, -190, -190, -190, - -190, -190, -190, -312, -284, -283, 697, 94, -277, 17, - 81, -312, -312, 92, 329, 423, 424, -310, 326, -81, - -294, 94, -10, -29, -18, -17, -19, 157, -10, 92, - 585, -183, -190, 697, 697, 697, 697, 697, 697, -145, - -145, -145, -145, 609, -208, -410, 149, 125, 126, 123, - 124, -162, 41, 42, 40, -145, -209, -214, -216, 110, - 168, 151, 165, -246, -150, -153, -150, -150, -150, -150, - -150, -150, 227, -150, 227, -150, -150, -150, -150, -150, - -150, -313, -294, 94, 184, -158, -157, 109, -408, -158, - 582, 92, -221, 228, -145, -145, -386, -119, 448, 449, - 450, 451, 453, 454, 455, 458, 459, 463, 464, 447, - 465, 452, 457, 460, 461, 462, 456, 349, -145, -211, - -210, -211, -145, -145, -223, -224, 153, -218, -145, -419, - -419, 100, 175, -127, 26, 43, -127, -127, -127, -127, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 98, + 104, 50, 412, 412, -190, -79, -79, -79, -79, -416, + 719, 594, -230, -128, -232, -33, -31, -419, 12, -79, + -31, -32, -30, -36, -38, 621, -37, -301, 109, -237, + -253, 16, 67, 175, 48, 56, -235, -236, -34, -31, + -145, 23, 41, 27, -132, 182, -145, -301, -132, -279, + 256, -79, -79, -268, -315, 330, -270, 427, 702, 426, + -260, -273, 100, -259, -272, 425, 101, -357, 172, -343, + -347, -295, 267, -373, 263, -190, -366, -365, -295, -419, + -129, -289, 253, 261, 260, 149, -390, 152, 309, 439, + 251, -53, -54, -55, -272, 190, 722, -111, 284, 288, + 96, 96, -347, -346, -345, -391, 288, 267, -372, -364, + 259, 268, -353, 260, 261, -348, 253, 150, -391, -348, + 258, 268, 263, 267, 288, 288, 139, 288, 139, 288, + 288, 288, 288, 288, 288, 288, 288, 288, 283, -354, + 164, -354, 597, 597, -360, -391, 263, 253, -391, -391, + 259, -291, -348, 255, 28, 255, 38, 38, -354, -354, + -354, -272, 190, -354, -354, -354, -354, 296, 296, -354, + -354, -354, -354, -354, -354, -354, -354, -354, -354, -354, + -354, -354, -354, -354, -354, -354, 252, -390, -137, 423, + 316, 90, -56, 298, -39, -190, -289, 253, 254, -390, + 285, -190, 235, 252, 705, -283, 172, 19, -283, -280, + 412, 410, 397, 402, -283, -283, -283, -283, 299, 395, + -349, 253, 38, 264, 412, 299, 395, 299, 300, 299, + 300, 405, 415, 299, -306, 18, 175, 439, 400, 404, + 292, 252, 293, 254, 414, 300, -306, 98, -284, 172, + 299, 412, 406, 295, -283, -283, -313, -419, -297, -295, + -293, 244, 41, 155, 28, 30, 158, 191, 142, 23, + 159, 40, 246, 360, 263, 190, 259, 484, 239, 81, + 602, 440, 447, 438, 446, 450, 486, 487, 439, 398, + 34, 17, 604, 31, 273, 27, 44, 184, 241, 162, + 605, 276, 29, 274, 129, 133, 607, 26, 84, 268, + 18, 261, 46, 20, 608, 609, 21, 74, 257, 256, + 175, 253, 79, 15, 234, 32, 171, 75, 610, 150, + 145, 611, 612, 613, 614, 143, 77, 172, 24, 742, + 448, 449, 36, 703, 589, 287, 186, 82, 65, 704, + 156, 444, 615, 616, 130, 617, 134, 85, 709, 152, + 22, 80, 48, 618, 288, 619, 258, 743, 620, 430, + 621, 173, 242, 483, 78, 174, 716, 622, 717, 251, + 411, 12, 489, 35, 272, 260, 73, 72, 141, 76, + 454, 623, 252, 161, 255, 144, 132, 11, 149, 37, + 16, 83, 86, 451, 452, 453, 63, 140, 593, 160, + 19, 624, 431, 154, -387, 705, -313, -313, 299, 35, + 101, -413, -414, -415, 593, 430, 255, -295, -190, -85, + 695, 243, -86, 701, 41, 250, -135, 412, -123, 191, + 723, 706, 707, 708, 705, 409, 713, 711, 709, 299, + 710, 96, 152, 154, 155, 4, -145, 171, -200, -201, + 170, 164, 165, 166, 167, 168, 169, 176, 175, 156, + 158, 172, -246, 153, 177, 178, 179, 180, 181, 182, + 183, 185, 184, 186, 187, 173, 174, 190, 237, 238, + -153, -153, -153, -153, -216, -222, -221, -419, -218, -387, + -294, -301, -419, -419, -153, -278, -419, -150, -419, -419, + -419, -419, -419, -225, -145, -419, -419, -423, -419, -423, + -423, -423, -332, -419, -332, -332, -419, -419, -419, -419, + -419, -419, -419, -419, -419, -419, -419, -419, -419, -419, + -419, -419, -419, -419, -419, -419, -419, -419, -419, -419, + -419, -419, -419, -419, -419, -419, -419, -419, -419, -419, + -419, -419, -419, -419, -419, -419, -419, -419, -419, -419, + -419, -419, -419, -419, -419, -419, -419, -419, -419, -419, + -419, -419, -419, -419, -419, -419, -419, -419, -419, -419, + -419, -419, -419, -419, -419, -419, -419, -419, -419, -419, + -419, -419, -419, -419, -419, -419, -419, -419, -419, -419, + -419, -419, -419, -419, -419, -419, -419, -419, -419, -419, + -419, -419, -419, -419, -419, -419, -419, -419, -419, -419, + -419, -419, -419, -419, -419, -419, -419, -419, -419, -419, + -419, -419, -419, -419, -419, -419, -419, -419, -419, -419, + -419, 235, -419, -419, -419, -419, -419, -332, -332, -332, + -332, -332, -332, -419, -419, -419, -419, -419, -419, -419, + -419, -419, -419, -419, -419, -419, -419, 98, 112, 108, + 111, 103, -220, 114, 98, 98, 98, 98, -31, -32, + -210, -419, -312, -400, -401, -193, -190, -419, 316, -295, + -295, 285, 105, -235, -34, -31, -230, -236, -232, -31, + -79, -121, -134, 69, 70, -133, -136, 27, 44, 74, + 76, 99, 72, 73, 71, 41, -420, 97, -420, -253, + -420, 96, -38, -256, 95, 649, 679, 649, 679, 67, + 49, 98, 98, 96, 25, -231, -233, -145, 18, -299, + 4, -298, 28, -295, 98, 235, 18, -191, 32, -190, + -279, -279, 96, 100, 330, -269, -271, 428, 430, 164, + -300, -295, 98, 34, 97, 96, -190, -321, -324, -326, + -325, -327, -322, -323, 357, 358, 191, 361, 363, 364, + 365, 366, 367, 368, 369, 370, 371, 374, 386, 35, + 275, 353, 354, 355, 356, 375, 376, 377, 378, 380, + 381, 382, 383, 338, 359, 591, 339, 340, 341, 342, + 343, 344, 346, 347, 350, 348, 349, 351, 352, -296, + -295, 95, 97, 96, -331, 95, -145, -137, 252, -295, + 253, 253, 253, -79, 483, -354, -354, -354, 283, 23, + -46, -43, -380, 22, -42, -43, 244, 135, 136, 241, + 95, -343, 95, -352, -296, -295, 95, 150, 258, 149, + -351, -348, -351, -352, -295, -218, -295, 150, 150, -295, + -295, -265, -295, -265, -265, 41, -265, 41, -265, 41, + 105, -295, -265, 41, -265, 41, -265, 41, -265, 41, + -265, 41, 34, 87, 88, 89, 34, 91, 92, 93, + -218, -295, -295, -218, -343, -218, -190, -295, -272, 105, + 105, 105, -354, -354, 105, 98, 98, 98, -354, -354, + 105, 98, -303, -301, 98, 98, -392, 269, 313, 315, + 105, 105, 105, 105, 34, 98, -393, 34, 730, 729, + 731, 732, 733, 98, 105, 34, 105, 34, 105, -295, + 95, -190, -143, 303, 239, 241, 244, 85, 98, 321, + 319, 320, 317, 322, 323, 324, 164, 50, 96, 255, + 252, -295, -285, 257, -285, -295, -302, -301, -293, -190, + 255, 394, 98, -145, -350, 18, 175, -306, -306, -283, + -190, -350, -306, -283, -190, -283, -283, -283, -283, -306, + -306, -306, -283, -301, -301, -190, -190, -190, -190, -190, + -190, -190, -313, -284, -283, 705, 98, -277, 18, 85, + -313, -313, -292, 26, 96, 336, 431, 432, -311, 333, + -81, -295, 98, -10, -29, -18, -17, -19, 164, -10, + 96, 593, -183, -190, 705, 705, 705, 705, 705, 705, + -145, -145, -145, -145, 617, -208, -411, 156, 132, 133, + 130, 131, -162, 42, 43, 41, -145, -209, -214, -216, + 115, 175, 158, 172, -246, -150, -153, -150, -150, -150, + -150, -150, -150, 234, -150, 234, -150, -150, -150, -150, + -150, -150, -314, -295, 98, 191, -158, -157, 114, -409, + -158, 590, 96, -221, 235, -145, -145, -387, -119, 456, + 457, 458, 459, 461, 462, 463, 466, 467, 471, 472, + 455, 473, 460, 465, 468, 469, 470, 464, 356, -145, + -211, -210, -211, -145, -145, -223, -224, 160, -218, -145, + -420, -420, 105, 182, -127, 27, 44, -127, -127, -127, + -127, -145, -145, -145, -145, -145, -145, -145, -145, -145, + -145, -127, -145, -120, 455, 473, 460, 465, 468, 469, + 470, 464, 356, 474, 475, 476, 477, 478, 479, 480, + 481, 482, -120, -119, -145, -145, -145, -145, -145, -145, + -145, -145, -87, -145, 142, 143, 144, -210, -145, -150, + -145, -145, -145, -420, -145, -145, -145, -211, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, - -127, -145, -120, 447, 465, 452, 457, 460, 461, 462, - 456, 349, 466, 467, 468, 469, 470, 471, 472, 473, - 474, -120, -119, -145, -145, -145, -145, -145, -145, -87, - -145, 135, 136, 137, -210, -145, -150, -145, -145, -145, - -419, -145, -145, -145, -211, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, + -145, -145, -145, -145, -386, -385, -384, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, - -145, -385, -384, -383, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, - -145, -145, -145, -145, -145, -145, -145, -210, -210, -210, - -210, -210, -145, -419, -145, -164, -148, 100, -261, 109, - 96, -145, -145, -145, -145, -145, -145, -211, -296, -301, - -292, -293, -210, -211, -211, -210, -210, -145, -145, -145, - -145, -145, -145, -145, -145, -419, -145, -145, -145, -145, - -145, -253, -419, -210, 92, -401, 422, 423, 695, -303, - 281, -302, 27, -211, 94, 17, -263, 82, -294, -235, - -235, 68, 69, 64, -131, -132, -136, -419, -37, 27, - -255, -294, 634, 634, 67, 94, -332, -272, 377, 378, - 184, -145, -145, 92, -234, 29, 30, -190, -297, 175, - -301, -190, -264, 281, -190, -168, -170, -171, -172, -193, - -217, -418, -173, -31, 605, 602, 17, -183, -184, -192, - -300, -270, -314, -269, 92, 421, 423, 424, 81, 127, - -145, -333, 183, -361, -360, -359, -342, -344, -345, -346, - 93, -333, -338, 383, 382, -330, -330, -330, -330, -330, - -332, -332, -332, -332, 91, 91, -330, -330, -330, -330, - -335, 91, -335, -335, -336, -335, 91, -336, -337, 91, - -337, -372, -145, -369, -368, -366, -367, 255, 105, 677, - 633, 585, 626, 667, 82, -364, -234, 100, -419, -143, - -286, 250, -370, -367, -294, -294, -294, -286, 95, 94, - 95, 94, 95, 94, -112, -60, -1, 734, 735, 736, - 92, 22, -343, -342, -59, 306, -375, -376, 281, -371, - -365, -351, 143, -350, -351, -351, -294, 92, 31, 132, - 132, 132, 132, 585, 234, 34, -287, 625, 149, 677, - 633, -342, -59, 248, 248, -313, -313, -313, 94, 94, - -282, 730, -183, -139, 298, 157, 287, 287, 245, 300, - 245, 300, -190, 311, 314, 312, 313, 310, 315, 316, - 317, 40, 40, 40, 40, 40, 40, 299, 301, 303, - 289, -190, -190, -285, 81, -185, -190, 28, -300, 94, - 94, -190, -283, -283, -190, -283, -283, -190, -414, 330, - -294, 364, 688, 690, -123, 422, 92, 585, 25, -124, - 25, -418, -410, 125, 126, -216, -216, -216, -209, -150, - -153, -150, 148, 269, -150, -150, -418, -218, -419, -296, - 27, 92, 82, -419, 173, 92, -419, -419, 92, 17, - 92, -226, -224, 155, -145, -419, 92, -419, -419, -210, - -145, -145, -145, -145, -419, -419, -419, -419, -419, -419, - -419, -419, -419, -419, -210, -419, 92, 92, 17, -317, - 27, -419, -419, -419, -419, -419, -225, -419, 17, -419, - 82, 92, 168, 92, -419, -419, -419, 92, 92, -419, - -419, 92, -419, 92, -419, -419, -419, -419, -419, -419, - 92, -419, 92, -419, -419, -419, 92, -419, 92, -419, - -419, 92, -419, 92, -419, 92, -419, 92, -419, 92, - -419, 92, -419, 92, -419, 92, -419, 92, -419, 92, - -419, 92, -419, 92, -419, 92, -419, 92, -419, 92, - -419, 92, -419, 92, -419, 92, -419, -419, -419, 92, - -419, 92, -419, 92, -419, -419, 92, -419, 92, -419, - 92, -419, 92, 92, -419, 92, 92, 92, -419, 92, - 92, 92, 92, -419, -419, -419, -419, 92, 92, 92, - 92, 92, 92, 92, 92, 92, 92, -419, -419, -419, - -419, -419, -419, 92, -94, 610, -419, -419, 92, -419, - 92, 92, 92, 92, 92, -419, -418, 228, -419, -419, - -419, -419, -419, 92, 92, 92, 92, 92, 92, -419, - -419, -419, 92, 92, -419, 92, -419, 92, -419, -400, - 694, 423, -197, -196, -194, 79, 249, 80, -418, -302, - -419, -158, -261, -262, -261, -203, -294, 100, 109, -237, - -167, 92, -169, 17, -216, 93, 92, -332, -241, -247, - -280, -294, 94, 184, -334, 184, -334, 377, 378, -233, - 228, -198, 18, -202, 34, 62, -29, -418, -418, 34, - 92, -186, -188, -187, -189, 71, 75, 77, 72, 73, - 74, 78, -308, 27, -31, -168, -31, -418, -190, -183, - -420, 17, 82, -420, 92, 228, -271, -274, 425, 422, - 428, -386, 94, -111, 92, -359, -346, -238, -140, 45, - -339, 384, -332, 593, -332, -341, 94, -341, 100, 100, - 100, 93, -49, -44, -45, 35, 86, -366, -353, 94, - 44, -353, -353, -294, 93, -234, -139, -190, 149, 81, - -370, -370, -370, -300, -2, 733, 739, 143, 91, 389, - 21, -255, 92, 93, -219, 307, 93, -113, -294, 93, - 91, -351, -351, -294, -418, 245, 33, 33, 677, 633, - 625, -59, -219, -218, -294, -333, 732, 731, 93, 247, - 305, -144, 442, -141, 94, 95, -190, -190, -190, -190, - -190, -190, 237, 234, 412, -409, 318, -409, 290, 248, - -183, -190, 92, -84, 264, 259, -305, -305, 35, -190, - 422, 706, 704, -145, 148, 269, -162, -153, -119, -119, - -150, -315, 184, 350, 268, 348, 344, 364, 355, 382, - 346, 383, 341, 340, 339, -315, -313, -150, -210, -145, - -145, -145, 156, -145, 154, -145, -95, -94, -419, -419, - -419, -419, -419, -95, -95, -95, -95, -95, -95, -95, - -95, -95, -95, -230, -145, -145, -145, -419, 184, 350, - 17, -145, -313, -145, -145, -145, -145, -145, -145, -145, + -210, -210, -210, -210, -210, -145, -420, -145, -164, -148, + 105, -261, 114, 101, -145, -145, -145, -145, -145, -145, + -211, -297, -302, -293, -294, -210, -211, -211, -210, -210, + -145, -145, -145, -145, -145, -145, -145, -145, -420, -145, + -145, -145, -145, -145, -253, -420, -210, 96, -402, 430, + 431, 703, -304, 288, -303, 28, -211, 98, 18, -263, + 86, -295, -235, -235, 69, 70, 65, -131, -132, -136, + -420, -37, 28, -255, -295, 642, 642, 68, 98, -333, + -272, 384, 385, 191, -145, -145, 96, -234, 30, 31, + -190, -298, 182, -302, -190, -264, 288, -190, -168, -170, + -171, -172, -193, -217, -419, -173, -31, 613, 610, 18, + -183, -184, -192, -301, -270, -315, -269, 96, 429, 431, + 432, 85, 134, -145, -334, 190, -362, -361, -360, -343, + -345, -346, -347, 97, -334, -339, 391, 390, -331, -331, + -331, -331, -331, -333, -333, -333, -333, 95, -331, 95, + -331, -331, -331, -331, -336, 95, -336, -336, -337, -336, + 95, -337, -338, 95, -338, -373, -145, -370, -369, -367, + -368, 262, 110, 685, 641, 593, 634, 675, 86, -365, + -234, 105, -420, -143, -286, 257, -371, -368, -295, -295, + -295, -286, 100, 98, 100, 98, 100, 98, -112, -60, + -1, 742, 743, 744, 96, 23, -344, -343, -59, 313, + -376, -377, 288, -372, -366, -352, 150, -351, -352, -352, + -295, 96, 32, 139, 139, 139, 139, 593, 241, 35, + -287, 633, 156, 685, 641, -343, -59, 255, 255, -314, + -314, -314, 98, 98, -282, 738, -183, -139, 305, 164, + 294, 294, 252, 307, 252, 307, -190, 318, 321, 319, + 320, 317, 322, 323, 324, 41, 41, 41, 41, 41, + 41, 41, 306, 308, 310, 296, -190, -190, -285, 85, + -185, -190, 29, -301, 98, 98, -190, -283, -283, -190, + -283, -283, -190, 98, -415, 337, -295, 371, 696, 698, + -123, 430, 96, 593, 26, -124, 26, -419, -411, 132, + 133, -216, -216, -216, -209, -150, -153, -150, 155, 276, + -150, -150, -419, -218, -420, -297, 28, 96, 86, -420, + 180, 96, -420, -420, 96, 18, 96, -226, -224, 162, + -145, -420, 96, -420, -420, -210, -145, -145, -145, -145, + -420, -420, -420, -420, -420, -420, -420, -420, -420, -420, + -210, -420, 96, 96, 18, -318, 28, -420, -420, -420, + -420, 96, -420, -420, -225, -420, 18, -420, 86, 96, + 175, 96, -420, -420, -420, 96, 96, -420, -420, 96, + -420, 96, -420, -420, -420, -420, -420, -420, 96, -420, + 96, -420, -420, -420, 96, -420, 96, -420, -420, 96, + -420, 96, -420, 96, -420, 96, -420, 96, -420, 96, + -420, 96, -420, 96, -420, 96, -420, 96, -420, 96, + -420, 96, -420, 96, -420, 96, -420, 96, -420, 96, + -420, 96, -420, 96, -420, -420, -420, 96, -420, 96, + -420, 96, -420, -420, 96, -420, 96, -420, 96, -420, + 96, 96, -420, 96, 96, 96, -420, 96, 96, 96, + 96, -420, -420, -420, -420, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, -420, -420, -420, -420, -420, + -420, 96, -94, 618, -420, -420, 96, -420, 96, 96, + 96, 96, 96, -420, -419, 235, -420, -420, -420, -420, + -420, 96, 96, 96, 96, 96, 96, -420, -420, -420, + 96, 96, -420, 96, -420, 96, -420, -401, 702, 431, + -197, -196, -194, 83, 256, 84, -419, -303, -420, -158, + -261, -262, -261, -203, -295, 105, 114, -237, -167, 96, + -169, 18, -216, 97, 96, -333, -241, -247, -280, -295, + 98, 191, -335, 191, -335, 384, 385, -233, 235, -198, + 19, -202, 35, 63, -29, -419, -419, 35, 96, -186, + -188, -187, -189, 75, 79, 81, 76, 77, 78, 82, + -309, 28, -31, -168, -31, -419, -190, -183, -421, 18, + 86, -421, 96, 235, -271, -274, 433, 430, 436, -387, + 98, -111, 96, -360, -347, -238, -140, 46, -340, 392, + -333, 601, -333, -342, 98, -342, 105, 105, 105, 97, + -49, -44, -45, 36, 90, -367, -354, 98, 45, -354, + -354, -295, 97, -234, -139, -190, 156, 85, -371, -371, + -371, -301, -2, 741, 747, 150, 95, 397, 22, -255, + 96, 97, -219, 314, 97, -113, -295, 97, 95, -352, + -352, -295, -419, 252, 34, 34, 685, 641, 633, -59, + -219, -218, -295, -334, 740, 739, 97, 254, 312, -144, + 450, -141, 98, 100, -190, -190, -190, -190, -190, -190, + 244, 241, 420, -410, 325, -410, 297, 255, -183, -190, + 96, -84, 271, 266, -306, -306, 36, -190, 430, 714, + 712, -145, 155, 276, -162, -153, -119, -119, -150, -316, + 191, 357, 275, 355, 351, 371, 362, 390, 353, 391, + 348, 347, 346, -316, -314, -150, -210, -145, -145, -145, + 163, -145, 161, -145, -95, -94, -420, -420, -420, -420, + -420, -95, -95, -95, -95, -95, -95, -95, -95, -95, + -95, -230, -145, -145, -145, -420, 191, 357, -95, -145, + 18, -145, -314, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, - -145, -145, -145, -145, -145, -145, -145, -145, -383, -145, - -210, -145, -210, -145, -145, -145, -145, -145, -384, -384, - -384, -384, -384, -210, -210, -210, -210, -145, -418, -294, - -98, -97, -96, 660, 249, -94, -164, -98, -164, 227, - -145, 227, 227, 227, -145, -211, -296, -145, -145, -145, - -145, -145, -145, -145, -145, -145, -145, -194, -347, 287, - -347, 287, -347, -265, 92, -276, 25, 17, 62, 62, - -167, -198, -132, -168, -294, -244, 687, -250, 51, -248, - -249, 52, -245, 53, 61, -334, -334, 175, -235, -145, - -266, 81, -267, -275, -218, -213, -215, -214, -418, -254, - -419, -294, -265, -267, -170, -171, -171, -170, -171, 71, - 71, 71, 76, 71, 76, 71, -187, -300, -419, -145, - -303, 82, -168, -168, -192, -300, 175, 422, 426, 427, - -359, -407, 123, 149, 33, 81, 380, 105, -405, 183, - 622, 672, 677, 633, 626, 667, -406, 251, 142, 143, - 263, 27, 46, 93, 92, 93, 92, 93, 93, 92, - -288, -287, -45, -44, -353, -353, 100, -386, 94, 94, - 247, 28, -190, 81, 81, 81, -114, 737, 100, 91, - -3, 86, -145, 91, 22, -342, -218, -377, -327, -378, - -328, -329, -5, -6, -354, -117, 62, 105, -63, 49, - 246, 717, 718, 132, -418, 730, -369, -255, -373, -375, - -190, -149, -418, -161, -147, -146, -148, -154, 173, 174, - 268, 346, 347, -219, -190, -138, 296, 304, 91, -142, - 96, -388, 82, 287, 380, 287, 380, 94, -411, 319, - 94, -411, -190, -84, -49, -190, -283, -283, 35, -386, - -419, -162, -153, -126, 168, 585, -318, 592, -330, -330, - -330, -337, -330, 336, -330, 336, -330, -419, -419, -419, - 92, -419, 25, -419, 92, -145, 92, -95, -95, -95, - -95, -95, -122, 481, 92, 92, -419, 91, 91, -145, - -419, -419, -419, 92, -419, -419, -419, -419, -419, -419, - -419, -419, -419, -419, -419, -419, -419, 92, -419, 92, - -419, 92, -419, 92, -419, 92, -419, 92, -419, 92, - -419, 92, -419, 92, -419, 92, -419, 92, -419, 92, - -419, 92, -419, 92, -419, 92, -419, 92, -419, -419, - 92, -419, -419, -419, 92, -419, 92, -419, 92, -419, - -419, -419, 92, -316, 678, -419, -419, -419, -419, -419, - -419, -419, -419, -419, -419, -419, -93, -295, -94, 642, - 642, -419, -94, -227, 92, -150, -419, -150, -150, -150, - -419, -419, -419, 92, -419, 92, 92, -419, 92, -419, - 92, -419, -419, -419, -419, 92, -195, 25, -418, -195, - -418, -195, -419, -261, -190, -198, -228, 19, -241, 56, - 356, -252, -251, 60, 52, -249, 22, 54, 22, 32, - -266, 92, 157, -307, 92, 27, -419, -419, 92, 62, - 228, -419, -198, -181, -180, 81, 82, -182, 81, -180, - 71, 71, -256, 92, -264, -168, -198, -198, 228, 123, - -418, -149, 15, 94, 94, -386, -404, 721, 722, 33, - 100, -353, -353, 143, 143, -190, 91, -332, 94, -332, - 100, 100, 33, 87, 88, 89, 33, 83, 84, 85, - -190, -190, -190, -190, -374, 91, 22, -145, 91, 157, - 93, -255, -255, 283, 168, -353, 715, 289, 289, -353, - -353, -353, -116, -115, 737, 93, -419, 92, -340, 585, - 588, -145, -155, -155, -256, 93, -382, 585, -387, -294, - -294, -294, -294, 100, 102, -419, 583, 78, 586, -419, - -332, -145, -145, -145, -145, -235, 94, -145, -145, 100, - 100, -419, -145, -145, -145, -145, -145, -145, -145, -145, + -145, -145, -145, -145, -145, -145, -145, -145, -384, -145, + -210, -145, -210, -145, -145, -145, -145, -145, -385, -385, + -385, -385, -385, -210, -210, -210, -210, -145, -419, -295, + -98, -97, -96, 668, 256, -94, -164, -98, -164, 234, + -145, 234, 234, 234, -145, -211, -297, -145, -145, -145, + -145, -145, -145, -145, -145, -145, -145, -194, -348, 294, + -348, 294, -348, -265, 96, -276, 26, 18, 63, 63, + -167, -198, -132, -168, -295, -244, 695, -250, 52, -248, + -249, 53, -245, 54, 62, -335, -335, 182, -235, -145, + -266, 85, -267, -275, -218, -213, -215, -214, -419, -254, + -420, -295, -265, -267, -170, -171, -171, -170, -171, 75, + 75, 75, 80, 75, 80, 75, -187, -301, -420, -145, + -304, 86, -168, -168, -192, -301, 182, 430, 434, 435, + -360, -408, 130, 156, 34, 85, 388, 110, -406, 190, + 630, 680, 685, 641, 634, 675, -407, 258, 149, 150, + 270, 28, 47, 97, 96, 97, 96, 97, 97, 96, + -288, -287, -45, -44, -354, -354, 105, -387, 98, 98, + 254, 29, -190, 85, 85, 85, -114, 745, 105, 95, + -3, 90, -145, 95, 23, -343, -218, -378, -328, -379, + -329, -330, -5, -6, -355, -117, 63, 110, -63, 50, + 253, 725, 726, 139, -419, 738, -370, -255, -374, -376, + -190, -149, -419, -161, -147, -146, -148, -154, 180, 181, + 275, 353, 354, -219, -190, -138, 303, 311, 95, -142, + 101, -389, 86, 294, 388, 294, 388, 98, -412, 326, + 98, -412, -190, -84, -49, -190, -283, -283, 36, -387, + -420, -162, -153, -126, 175, 593, -319, 600, -331, -331, + -331, -338, -331, 343, -331, 343, -331, -420, -420, -420, + 96, -420, 26, -420, 96, -145, 96, -95, -95, -95, + -95, -95, -122, 489, 96, 96, -420, 95, 95, -420, + -145, -420, -420, -420, 96, -420, -420, -420, -420, -420, + -420, -420, -420, -420, -420, -420, -420, -420, 96, -420, + 96, -420, 96, -420, 96, -420, 96, -420, 96, -420, + 96, -420, 96, -420, 96, -420, 96, -420, 96, -420, + 96, -420, 96, -420, 96, -420, 96, -420, 96, -420, + -420, 96, -420, -420, -420, 96, -420, 96, -420, 96, + -420, -420, -420, 96, -317, 686, -420, -420, -420, -420, + -420, -420, -420, -420, -420, -420, -420, -93, -296, -94, + 650, 650, -420, -94, -227, 96, -150, -420, -150, -150, + -150, -420, -420, -420, 96, -420, 96, 96, -420, 96, + -420, 96, -420, -420, -420, -420, 96, -195, 26, -419, + -195, -419, -195, -420, -261, -190, -198, -228, 20, -241, + 57, 363, -252, -251, 61, 53, -249, 23, 55, 23, + 33, -266, 96, 164, -308, 96, 28, -420, -420, 96, + 63, 235, -420, -198, -181, -180, 85, 86, -182, 85, + -180, 75, 75, -256, 96, -264, -168, -198, -198, 235, + 130, -419, -149, 16, 98, 98, -387, -405, 729, 730, + 34, 105, -354, -354, 150, 150, -190, 95, -333, 98, + -333, 105, 105, 34, 91, 92, 93, 34, 87, 88, + 89, -190, -190, -190, -190, -375, 95, 23, -145, 95, + 164, 97, -255, -255, 290, 175, -354, 723, 296, 296, + -354, -354, -354, -116, -115, 745, 97, -420, 96, -341, + 593, 596, -145, -155, -155, -256, 97, -383, 593, -388, + -295, -295, -295, -295, 105, 107, -420, 591, 82, 594, + -420, -333, -145, -145, -145, -145, -235, 98, -145, -145, + 105, 105, -95, -420, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, -145, - -145, -145, -210, -145, -419, -178, -177, -179, 698, 123, - 33, -315, -419, -212, 281, -101, -100, -99, 17, -419, - -145, -119, -119, -119, -119, -145, -145, -145, -145, -145, - -145, -418, 71, 21, 19, -258, -294, 251, -418, -258, - -418, -303, -228, -229, 20, 22, -242, 58, -240, 57, - -240, -251, 22, 22, 94, 22, 94, 143, -275, -145, - -215, -302, 62, -29, -294, -213, -294, -230, -145, 91, - -145, -158, -198, -198, -145, -205, 505, 507, 508, 509, - 506, 511, 512, 513, 514, 515, 516, 517, 518, 519, - 520, 510, 521, 482, 483, 484, 112, 114, 113, 485, - 486, 487, 350, 533, 534, 528, 531, 532, 530, 529, - 365, 366, 488, 551, 552, 556, 555, 553, 554, 557, - 560, 561, 562, 563, 564, 565, 567, 566, 558, 559, - 536, 535, 537, 538, 539, 540, 541, 542, 544, 543, - 545, 546, 547, 548, 549, 550, 568, 569, 570, 571, - 572, 574, 573, 578, 577, 575, 576, 580, 579, 489, - 490, 115, 116, 117, 118, 119, 120, 121, 491, 494, - 492, 495, 496, 497, 502, 503, 498, 499, 500, 501, - 504, 376, 374, 375, 371, 370, 369, 429, 434, 435, - 437, 522, 523, 524, 525, 526, 527, 679, 680, 681, - 682, 683, 684, 685, 686, 94, 94, 91, -145, 93, - 93, -256, -373, -60, 93, -257, -255, 100, 93, 284, - -214, -418, 94, -353, -353, -353, 100, 100, -302, -419, - 92, -294, -406, -375, 589, 589, -419, 27, -381, -380, - -296, 91, 82, 67, 584, 587, -419, -419, -419, 92, - -419, -419, -419, 93, 93, -419, -419, -419, -419, -419, - -419, -419, -419, -419, -419, -419, -419, -419, -419, -419, - -419, -419, -419, -419, -419, -419, -419, 92, -419, -177, - -179, -419, 81, -158, -230, 22, -98, 306, 308, -98, - -419, -419, -419, -419, -419, 92, -419, -419, 92, -419, - 92, -419, -419, -258, -419, 22, 22, 92, -419, -258, - -419, -258, -197, -229, -108, -107, -106, 616, -145, -210, - -243, 59, 81, 127, 94, 94, 94, 15, -418, -213, - 228, -307, -235, -255, -175, 389, -230, -419, -255, 93, - 27, 93, 739, 143, 93, -214, -125, -418, 280, -302, - 94, 94, -115, -118, -29, 92, 157, -255, -190, 67, - -145, -210, -419, 81, 597, 698, -92, -91, -88, 709, - 735, -210, -94, -94, -145, -145, -145, -419, -294, 251, - -419, -419, -108, 92, -105, -104, -294, -319, 585, 81, - 127, -267, -255, -307, -294, 93, -419, -418, -235, 93, - -239, -29, 91, -3, 280, -327, -378, -328, -329, -5, - -6, -354, -82, 585, -380, -358, -300, -296, 94, 100, - 93, 585, -419, -419, -90, 151, 707, 675, -155, 227, - -419, 92, -419, 92, -419, 92, -106, 92, 27, 590, - -419, -303, -176, -174, -294, 639, -397, -396, 581, -407, - -403, 123, 149, 105, -405, 677, 633, 133, 134, -82, - -145, 91, -419, -83, 295, 694, 228, -388, 586, -90, - 708, 653, 628, 653, 628, -150, -145, -145, -145, -104, - -418, -419, 92, 25, -320, -62, 650, -394, -395, 81, - -398, 395, 649, 670, 123, 94, 93, -255, 256, -301, - -382, 587, 148, -119, -419, 92, -419, 92, -419, -93, - -174, 646, -333, -158, -395, 81, -394, 81, 16, 15, - -4, 738, 93, 297, -90, 653, 628, -145, -145, -419, - -61, 28, -175, -393, 264, 259, 262, 34, -393, 100, - -4, -419, -419, 650, 258, 33, 123, -158, -178, -177, - -177, + -145, -145, -145, -145, -210, -145, -420, -178, -177, -179, + 706, 130, 34, -316, -420, -212, 288, -101, -100, -99, + 18, -420, -145, -119, -119, -119, -119, -145, -145, -145, + -145, -145, -145, -419, 75, 22, 20, -258, -295, 258, + -419, -258, -419, -304, -228, -229, 21, 23, -242, 59, + -240, 58, -240, -251, 23, 23, 98, 23, 98, 150, + -275, -145, -215, -303, 63, -29, -295, -213, -295, -230, + -145, 95, -145, -158, -198, -198, -145, -205, 513, 515, + 516, 517, 514, 519, 520, 521, 522, 523, 524, 525, + 526, 527, 528, 518, 529, 490, 491, 492, 117, 119, + 118, 127, 128, 493, 494, 495, 357, 541, 542, 536, + 539, 540, 538, 537, 372, 373, 496, 559, 560, 564, + 563, 561, 562, 565, 568, 569, 570, 571, 572, 573, + 575, 574, 566, 567, 544, 543, 545, 546, 547, 548, + 549, 550, 552, 551, 553, 554, 555, 556, 557, 558, + 576, 577, 578, 579, 580, 582, 581, 586, 585, 583, + 584, 588, 587, 497, 498, 120, 121, 122, 123, 124, + 125, 126, 499, 502, 500, 503, 504, 505, 510, 511, + 506, 507, 508, 509, 512, 383, 381, 382, 378, 377, + 376, 437, 442, 443, 445, 530, 531, 532, 533, 534, + 535, 687, 688, 689, 690, 691, 692, 693, 694, 98, + 98, 95, -145, 97, 97, -256, -374, -60, 97, -257, + -255, 105, 97, 291, -214, -419, 98, -354, -354, -354, + 105, 105, -303, -420, 96, -295, -407, -376, 597, 597, + -420, 28, -382, -381, -297, 95, 86, 68, 592, 595, + -420, -420, -420, 96, -420, -420, -420, 97, 97, -420, + -420, -420, -420, -420, -420, -420, -420, -420, -420, -420, + -420, -420, -420, -420, -420, -420, -420, -420, -420, -420, + -420, 96, -420, -177, -179, -420, 85, -158, -230, 23, + -98, 313, 315, -98, -420, -420, -420, -420, -420, 96, + -420, -420, 96, -420, 96, -420, -420, -258, -420, 23, + 23, 96, -420, -258, -420, -258, -197, -229, -108, -107, + -106, 624, -145, -210, -243, 60, 85, 134, 98, 98, + 98, 16, -419, -213, 235, -308, -235, -255, -175, 397, + -230, -420, -255, 97, 28, 97, 747, 150, 97, -214, + -125, -419, 287, -303, 98, 98, -115, -118, -29, 96, + 164, -255, -190, 68, -145, -210, -420, 85, 605, 706, + -92, -91, -88, 717, 743, -210, -94, -94, -145, -145, + -145, -420, -295, 258, -420, -420, -108, 96, -105, -104, + -295, -320, 593, 85, 134, -267, -255, -308, -295, 97, + -420, -419, -235, 97, -239, -29, 95, -3, 287, -328, + -379, -329, -330, -5, -6, -355, -82, 593, -381, -359, + -301, -297, 98, 105, 97, 593, -420, -420, -90, 158, + 715, 683, -155, 234, -420, 96, -420, 96, -420, 96, + -106, 96, 28, 598, -420, -304, -176, -174, -295, 647, + -398, -397, 589, -408, -404, 130, 156, 110, -406, 685, + 641, 140, 141, -82, -145, 95, -420, -83, 302, 702, + 235, -389, 594, -90, 716, 661, 636, 661, 636, -150, + -145, -145, -145, -104, -419, -420, 96, 26, -321, -62, + 658, -395, -396, 85, -399, 403, 657, 678, 130, 98, + 97, -255, 263, -302, -383, 595, 155, -119, -420, 96, + -420, 96, -420, -93, -174, 654, -334, -158, -396, 85, + -395, 85, 17, 16, -4, 746, 97, 304, -90, 661, + 636, -145, -145, -420, -61, 29, -175, -394, 271, 266, + 269, 35, -394, 105, -4, -420, -420, 658, 265, 34, + 130, -158, -178, -177, -177, } var yyDef = [...]int{ - 880, -2, -2, 882, 2, 4, 5, 6, 7, 8, + 885, -2, -2, 887, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 70, 72, 73, 880, 880, 880, 0, 880, 0, - 0, 880, -2, -2, 880, 1629, 0, 880, 0, 875, - 0, -2, 797, 803, 0, 812, -2, 0, 0, 880, - 880, 2259, 2259, 875, 0, 0, 0, 0, 0, 880, - 880, 880, 880, 1634, 1487, 50, 880, 0, 85, 86, - 830, 831, 832, 65, 0, 2257, 881, 1, 3, 71, - 75, 0, 0, 0, 58, 1496, 0, 78, 0, 0, - 884, 0, 0, 1612, 880, 880, 0, 126, 127, 0, + 39, 70, 72, 73, 885, 885, 885, 0, 885, 0, + 0, 885, -2, -2, 885, 1640, 0, 885, 0, 880, + 0, -2, 802, 808, 0, 817, -2, 0, 0, 885, + 885, 2277, 2277, 880, 0, 0, 0, 0, 0, 885, + 885, 885, 885, 1645, 1498, 50, 885, 0, 85, 86, + 835, 836, 837, 65, 0, 2275, 886, 1, 3, 71, + 75, 0, 0, 0, 58, 1507, 0, 78, 0, 0, + 889, 0, 0, 1623, 885, 885, 0, 126, 127, 0, 0, 0, -2, 130, -2, 159, 160, 161, 0, 166, - 607, 526, 578, 524, 563, -2, 512, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 529, - 401, 401, 0, 0, -2, 512, 512, 512, 1614, 0, - 0, 0, 560, 463, 401, 401, 401, 0, 401, 401, - 401, 401, 0, 0, 401, 401, 401, 401, 401, 401, - 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, - 401, 1514, 165, 1630, 1627, 1628, 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, 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, 0, 1606, 0, 720, - 980, 0, 876, 877, 0, 786, 786, 0, 786, 786, - 786, 786, 0, 0, 0, 734, 0, 0, 0, 0, - 783, 0, 750, 751, 0, 783, 0, 757, 789, 0, - 0, 764, 786, 786, 767, 2260, 0, 2260, 2260, 1597, - 0, 780, 778, 792, 793, 42, 796, 799, 800, 801, - 802, 805, 0, 816, 819, 1623, 1624, 0, 821, 826, - 843, 844, 0, 45, 1140, 0, 1004, 0, 1015, -2, - 1026, 1043, 1044, 1045, 1046, 1047, 1049, 1050, 1051, 0, - 0, 0, 0, 1056, 1057, 0, 0, 0, 0, 0, - 1120, 0, 0, 0, 0, 1987, 1458, 0, 0, 1420, - 1420, 1156, 1420, 1420, 1422, 1422, 1422, 1840, 1979, 1988, - 2166, 1801, 1807, 1808, 1809, 2112, 2113, 2114, 2115, 2204, - 2205, 2209, 1903, 1796, 2179, 2180, 0, 2256, 1940, 1948, - 1949, 1973, 2075, 2189, 1819, 1968, 2038, 1900, 1922, 1923, - 2056, 2057, 1944, 1945, 1926, 2118, 2120, 2136, 2137, 2122, - 2124, 2133, 2139, 2144, 2123, 2135, 2140, 2153, 2157, 2160, - 2161, 2162, 2130, 2128, 2141, 2145, 2147, 2149, 2155, 2158, - 2131, 2129, 2142, 2146, 2148, 2150, 2156, 2159, 2117, 2121, - 2125, 2134, 2152, 2132, 2151, 2126, 2138, 2143, 2154, 2127, - 2119, 1938, 1941, 1929, 1930, 1932, 1934, 1939, 1946, 1952, - 1931, 1951, 1950, 0, 1927, 1928, 1933, 1943, 1947, 1935, - 1936, 1937, 1942, 1953, 1994, 1993, 1992, 2037, 1964, 2036, - 0, 0, 0, 0, 0, 1790, 1845, 1846, 2163, 1342, - 1343, 1344, 1345, 0, 0, 0, 0, 0, 0, 0, - 291, 292, 1471, 1472, 44, 1139, 1593, 1422, 1422, 1422, - 1422, 1422, 1422, 1078, 1079, 1080, 1081, 1082, 1108, 1109, - 1115, 1116, 2051, 2052, 2053, 2054, 1883, 2199, 1892, 1893, - 2033, 2034, 1905, 1906, 2230, 2231, -2, -2, -2, 232, - 233, 234, 235, 236, 237, 238, 239, 0, 1844, 2177, - 2178, 228, 0, 0, 296, 293, 294, 295, 1122, 1123, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 290, 298, 299, 2259, 0, 853, 0, 0, 0, - 0, 0, 0, 1635, 1636, 1496, 0, 1488, 1487, 63, - 0, 880, -2, 0, 0, 0, 0, 47, 0, 52, - 937, 883, 77, 76, 1536, 1539, 0, 0, 0, 59, - 1497, 67, 69, 1498, 0, 885, 886, 0, 913, 917, - 0, 0, 0, 1613, 1612, 1612, 102, 0, 0, 103, - 123, 124, 125, 0, 0, 109, 110, 1599, 1600, 43, - 0, 0, 177, 178, 0, 1096, 428, 0, 173, 0, - 421, 360, 0, 1514, 0, 0, 0, 0, 0, 880, - 0, 1607, 154, 155, 162, 163, 164, 401, 401, 401, - 575, 0, 0, 165, 165, 533, 534, 535, 0, 0, - -2, 426, 0, 513, 0, 0, 415, 415, 419, 417, - 418, 0, 0, 0, 0, 0, 0, 0, 0, 552, - 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 668, 0, 402, 0, 573, 574, 464, 0, 0, - 0, 0, 0, 0, 0, 0, 1615, 1616, 0, 550, - 551, 0, 0, 0, 401, 401, 0, 0, 0, 0, - 401, 401, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 153, 1527, 0, 0, 0, -2, 0, 712, 0, 0, - 0, 1608, 1608, 0, 719, 0, 0, 0, 724, 0, - 0, 725, 0, 783, 783, 781, 782, 727, 728, 729, - 730, 786, 0, 0, 410, 411, 412, 783, 786, 0, - 786, 786, 786, 786, 783, 783, 783, 786, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2260, 789, 786, - 0, 758, 0, 759, 760, 761, 762, 765, 766, 768, - 2261, 2262, 1625, 1626, 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, 1728, 1729, 1730, 1731, 1732, - 1733, 1734, 1735, 1736, 1737, 1738, 1739, 1740, 1741, 1742, - 1743, 1744, 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, 2260, 2260, 772, 776, 1598, 798, - 804, 806, 807, 0, 0, 817, 820, 837, 49, 1891, - 825, 49, 827, 828, 829, 855, 856, 861, 0, 0, - 0, 0, 867, 868, 869, 0, 0, 872, 873, 874, - 0, 0, 0, 0, 0, 1002, 0, 0, 1128, 1129, - 1130, 1131, 1132, 1133, 1134, 1135, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1027, 1028, 0, 0, 0, 1052, - 1053, 1054, 1055, 1058, 0, 1069, 0, 1071, 1467, -2, - 0, 0, 0, 1063, 1064, 0, 0, 0, 1618, 1618, - 0, 0, 0, 1459, 0, 0, 1154, 0, 1155, 1157, - 1158, 1159, 0, 1160, 1161, 890, 890, 890, 890, 890, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 890, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1618, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1618, 0, 0, - 1618, 1618, 0, 0, 220, 221, 222, 223, 224, 225, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 297, 240, 241, 242, 243, 244, - 245, 300, 246, 247, 248, 1139, 0, 0, 0, 46, - 845, 846, 0, 963, 1618, 0, 0, 896, 0, 1633, - 57, 66, 68, 1496, 61, 1496, 0, 900, 0, 0, - -2, -2, 901, 902, 906, 907, 908, 909, 910, 54, - 2258, 55, 0, 74, 0, 48, 0, 0, 1537, 0, - 1540, 0, 0, 0, 374, 1544, 0, 0, 1489, 1490, - 1493, 0, 914, 1985, 918, 0, 920, 921, 0, 0, - 100, 0, 979, 0, 0, 0, 111, 0, 113, 114, - 0, 0, 0, 385, 1601, 1602, 1603, -2, 408, 0, - 385, 369, 308, 309, 310, 360, 312, 360, 360, 360, - 360, 374, 374, 374, 374, 343, 344, 345, 346, 347, - 0, 0, 329, 360, 360, 360, 360, 350, 351, 352, - 353, 354, 355, 356, 357, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 362, 362, 362, 362, 362, 366, - 366, 0, 1097, 0, 389, 0, 1493, 0, 0, 1527, - 1610, 1620, 0, 0, 0, 1610, 132, 0, 0, 0, - 576, 618, 527, 564, 577, 0, 530, 531, -2, 0, - 0, 512, 0, 514, 0, 409, 0, -2, 0, 419, - 0, 415, 419, 416, 419, 407, 420, 554, 555, 556, - 0, 558, 559, 648, 949, 0, 0, 0, 0, 0, - 654, 655, 656, 0, 658, 659, 660, 661, 662, 663, - 664, 665, 666, 667, 565, 566, 567, 568, 569, 570, - 571, 572, 0, 0, 0, 0, 514, 0, 561, 0, - 0, 465, 466, 467, 0, 0, 470, 471, 472, 473, - 0, 0, 476, 477, 478, 966, 967, 479, 480, 505, - 506, 507, 481, 482, 483, 484, 485, 486, 487, 499, - 500, 501, 502, 503, 504, 488, 489, 490, 491, 492, - 493, 496, 0, 147, 1518, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1608, 0, 0, 0, 0, 899, 981, 1631, 1632, - 721, 0, 0, 787, 788, 0, 413, 414, 786, 786, - 731, 773, 0, 786, 735, 774, 736, 738, 737, 739, - 752, 753, 786, 742, 784, 785, 743, 744, 745, 746, - 747, 748, 749, 769, 754, 755, 756, 790, 0, 794, - 795, 770, 771, 0, 0, 810, 811, 0, 818, 840, - 838, 839, 841, 833, 834, 835, 836, 0, 842, 0, - 0, 858, 96, 863, 864, 865, 866, 878, 871, 1141, - 999, 1000, 1001, 0, 1003, 1009, 0, 1124, 1126, 1007, - 1008, 1011, 0, 0, 0, 1005, 1016, 1136, 1137, 1138, - 0, 0, 0, 0, 0, 1020, 1024, 1029, 1030, 1031, - 1032, 1033, 0, 1034, 0, 1037, 1038, 1039, 1040, 1041, - 1042, 1048, 1435, 1436, 1437, 1067, 301, 302, 0, 1068, - 0, 0, 0, 0, 0, 0, 0, 0, 1382, 1383, - 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1393, - 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1140, 0, - 1619, 0, 0, 0, 1465, 1462, 0, 0, 0, 1421, - 1423, 0, 0, 0, 891, 892, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1402, 1403, 1404, 1405, 1406, 1407, 1408, - 1409, 1410, 1411, 1412, 1413, 1414, 1415, 1416, 1417, 1418, - 1419, 0, 0, 1438, 0, 0, 0, 0, 0, 1458, - 0, 1073, 1074, 1075, 0, 0, 0, 0, 0, 0, - 1200, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 142, 143, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1346, 1347, 1348, 1349, - 41, 0, 0, 0, 0, 0, 0, 0, 1469, 0, - -2, -2, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1371, 0, 0, 0, 0, - 0, 0, 1591, 0, 0, 848, 849, 851, 0, 983, - 0, 964, 0, 0, 854, 0, 895, 0, 898, 60, - 62, 904, 905, 0, 922, 911, 903, 56, 51, 0, - 0, 941, 1538, 1541, 1542, 374, 1564, 0, 383, 383, - 380, 1499, 1500, 0, 1492, 1494, 1495, 79, 919, 915, - 0, 997, 0, 0, 978, 0, 925, 927, 928, 929, - 961, 0, 932, 933, 0, 0, 0, 0, 0, 98, - 980, 104, 0, 112, 0, 0, 117, 118, 105, 106, - 107, 108, 0, 607, -2, 460, 179, 181, 182, 183, - 174, -2, 372, 370, 371, 311, 374, 374, 337, 338, - 339, 340, 341, 342, 0, 0, 330, 331, 332, 333, - 322, 0, 323, 324, 325, 364, 0, 326, 327, 0, - 328, 427, 0, 1501, 390, 391, 393, 401, 0, 396, - 397, 0, 401, 401, 0, 422, 423, 0, 1493, 1518, - 0, 0, 0, 1621, 1620, 1620, 1620, 0, 167, 168, - 169, 170, 171, 172, 643, 0, 0, 619, 641, 642, - 165, 0, 0, 175, 516, 515, 0, 675, 0, 425, - 0, 0, 419, 419, 404, 405, 557, 0, 0, 650, - 651, 652, 653, 0, 0, 0, 543, 454, 0, 544, - 545, 514, 516, 0, 0, 385, 468, 469, 474, 475, - 494, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 592, 593, 594, 597, 599, 518, 603, - 605, 596, 598, 600, 518, 604, 606, 1515, 1516, 1517, - 0, 0, 713, 0, 0, 451, 94, 1609, 718, 722, - 723, 783, 741, 775, 783, 733, 740, 763, 808, 809, - 814, 822, 823, 824, 862, 0, 0, 0, 0, 870, - 0, 0, 1010, 1125, 1127, 1012, 1013, 1014, 1017, 0, - 1021, 1025, 0, 0, 0, 0, 0, 1072, 1070, 1469, - 0, 0, 0, 1121, 0, 0, 1144, 1145, 0, 0, - 0, 0, 1463, 0, 0, 1152, 0, 1424, 1102, 0, - 0, 0, 0, 0, 1102, 1102, 1102, 1102, 1102, 1102, - 1102, 1102, 1102, 1102, 1487, 1179, 0, 0, 0, 0, - 0, 1184, 1185, 1186, 1187, 1188, 0, 1190, 0, 1191, - 0, 0, 0, 0, 1198, 1199, 1201, 0, 0, 1204, - 1205, 0, 1207, 0, 1209, 1210, 1211, 1212, 1213, 1214, - 0, 1216, 0, 1218, 1219, 1220, 0, 1222, 0, 1224, - 1225, 0, 1227, 0, 1229, 0, 1232, 0, 1235, 0, - 1238, 0, 1241, 0, 1244, 0, 1247, 0, 1250, 0, - 1253, 0, 1256, 0, 1259, 0, 1262, 0, 1265, 0, - 1268, 0, 1271, 0, 1274, 0, 1277, 1278, 1279, 0, - 1281, 0, 1283, 0, 1286, 1287, 0, 1289, 0, 1292, - 0, 1295, 0, 0, 1296, 0, 0, 0, 1300, 0, - 0, 0, 0, 1309, 1310, 1311, 1312, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1323, 1324, 1325, - 1326, 1327, 1328, 0, 1330, 0, 1103, 0, 0, 1103, - 0, 0, 0, 0, 0, 1142, 1618, 0, 1425, 1426, - 1427, 1428, 1429, 0, 0, 0, 0, 0, 0, 1369, - 1370, 1372, 0, 0, 1375, 0, 1377, 0, 1592, 847, - 850, 852, 935, 984, 985, 0, 0, 0, 0, 965, - 1617, 893, 894, 897, 943, 0, 1473, 0, 0, 922, - 997, 0, 923, 0, 53, 938, 0, 1546, 1545, 1558, - 1571, 383, 383, 377, 378, 384, 379, 381, 382, 1491, - 0, 1496, 0, 1585, 0, 0, 1574, 0, 0, 0, - 0, 0, 0, 0, 0, 968, 0, 0, 971, 0, - 0, 0, 0, 962, 933, 0, 934, 0, -2, 0, - 0, 92, 93, 0, 0, 0, 115, 116, 0, 0, - 122, 386, 387, 156, 165, 462, 180, 435, 0, 0, - 307, 373, 334, 335, 336, 0, 358, 0, 0, 0, - 0, 456, 128, 1505, 1504, 401, 401, 392, 0, 395, - 0, 0, 0, 1622, 361, 424, 0, 146, 0, 0, - 0, 0, 0, 152, 613, 0, 0, 620, 0, 0, - 0, 525, 0, 536, 537, 0, 647, -2, 709, 389, - 0, 403, 406, 950, 0, 0, 538, 0, 541, 542, - 455, 516, 547, 548, 562, 549, 497, 498, 495, 0, - 0, 1528, 1529, 1534, 1532, 1533, 133, 583, 585, 589, - 584, 588, 0, 0, 0, 520, 0, 520, 581, 0, - 451, 1501, 0, 717, 452, 453, 786, 786, 857, 97, - 0, 860, 0, 0, 0, 0, 1018, 1022, 1035, 1036, - 1430, 1456, 360, 360, 1443, 360, 366, 1446, 360, 1448, - 360, 1451, 360, 1454, 1455, 0, 0, 1065, 0, 0, - 0, 0, 1151, 1466, 0, 0, 1162, 1101, 1102, 1102, - 1102, 1102, 1102, 1168, 1169, 1170, 1171, 1172, 1173, 1174, - 1175, 1176, 1177, 1460, 0, 0, 0, 1183, 0, 0, + 609, 527, 579, 525, 564, -2, 513, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 530, + 402, 402, 0, 0, -2, 513, 513, 513, 1625, 0, + 0, 0, 561, 464, 402, 402, 402, 0, 402, 402, + 402, 402, 0, 0, 402, 402, 402, 402, 402, 402, + 402, 402, 402, 402, 402, 402, 402, 402, 402, 402, + 402, 1525, 165, 1641, 1638, 1639, 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, 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, + 0, 1617, 0, 722, 989, 0, 881, 882, 0, 791, + 791, 0, 791, 791, 791, 791, 0, 0, 0, 736, + 0, 0, 0, 0, 788, 0, 752, 753, 0, 788, + 0, 759, 794, 0, 0, 766, 791, 791, 769, 2278, + 0, 2278, 2278, 0, 1608, 0, 785, 783, 797, 798, + 42, 801, 804, 805, 806, 807, 810, 0, 821, 824, + 1634, 1635, 0, 826, 831, 848, 849, 0, 45, 1149, + 0, 1013, 0, 1024, -2, 1035, 1052, 1053, 1054, 1055, + 1056, 1058, 1059, 1060, 0, 0, 0, 0, 1065, 1066, + 0, 0, 0, 0, 0, 1129, 0, 0, 0, 0, + 2003, 1469, 0, 0, 1431, 1431, 1165, 1431, 1431, 1433, + 1433, 1433, 1854, 1995, 2004, 2183, 1815, 1821, 1822, 1823, + 2129, 2130, 2131, 2132, 2221, 2222, 2226, 1917, 1810, 2196, + 2197, 0, 2274, 1956, 1964, 1965, 1941, 1950, 1989, 2091, + 2206, 1833, 1984, 2054, 1914, 1936, 1937, 2072, 2073, 1960, + 1961, 1940, 2135, 2137, 2153, 2154, 2139, 2141, 2150, 2156, + 2161, 2140, 2152, 2157, 2170, 2174, 2177, 2178, 2179, 2147, + 2145, 2158, 2162, 2164, 2166, 2172, 2175, 2148, 2146, 2159, + 2163, 2165, 2167, 2173, 2176, 2134, 2138, 2142, 2151, 2169, + 2149, 2168, 2143, 2155, 2160, 2171, 2144, 2136, 1954, 1957, + 1944, 1945, 1947, 1949, 1955, 1962, 1968, 1946, 1967, 1966, + 0, 1942, 1943, 1948, 1959, 1963, 1951, 1952, 1953, 1958, + 1969, 2010, 2009, 2008, 2053, 1980, 2052, 0, 0, 0, + 0, 0, 1804, 1859, 1860, 2180, 1353, 1354, 1355, 1356, + 0, 0, 0, 0, 0, 0, 0, 291, 292, 1482, + 1483, 44, 1148, 1604, 1433, 1433, 1433, 1433, 1433, 1433, + 1087, 1088, 1089, 1090, 1091, 1117, 1118, 1124, 1125, 2067, + 2068, 2069, 2070, 1897, 2216, 1906, 1907, 2049, 2050, 1919, + 1920, 2248, 2249, -2, -2, -2, 232, 233, 234, 235, + 236, 237, 238, 239, 0, 1858, 2194, 2195, 228, 0, + 0, 296, 293, 294, 295, 1131, 1132, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 298, + 299, 2277, 0, 858, 0, 0, 0, 0, 0, 0, + 1646, 1647, 1507, 0, 1499, 1498, 63, 0, 885, -2, + 0, 0, 0, 0, 47, 0, 52, 946, 888, 77, + 76, 1547, 1550, 0, 0, 0, 59, 1508, 67, 69, + 1509, 0, 890, 891, 0, 922, 926, 0, 0, 0, + 1624, 1623, 1623, 102, 0, 0, 103, 123, 124, 125, + 0, 0, 109, 110, 1610, 1611, 43, 0, 0, 177, + 178, 0, 1105, 429, 0, 173, 0, 422, 361, 0, + 1525, 0, 0, 0, 0, 0, 885, 0, 1618, 154, + 155, 162, 163, 164, 402, 402, 402, 576, 0, 0, + 165, 165, 534, 535, 536, 0, 0, -2, 427, 0, + 514, 0, 0, 416, 416, 420, 418, 419, 0, 0, + 0, 0, 0, 0, 0, 0, 553, 0, 554, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 670, 0, + 403, 0, 574, 575, 465, 0, 0, 0, 0, 0, + 0, 0, 0, 1626, 1627, 0, 551, 552, 0, 0, + 0, 402, 402, 0, 0, 0, 0, 402, 402, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 153, 1538, 0, + 0, 0, -2, 0, 714, 0, 0, 0, 1619, 1619, + 0, 721, 0, 0, 0, 726, 0, 0, 727, 0, + 788, 788, 786, 787, 729, 730, 731, 732, 791, 0, + 0, 411, 412, 413, 788, 791, 0, 791, 791, 791, + 791, 788, 788, 788, 791, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2278, 794, 791, 0, 760, 0, + 761, 762, 763, 764, 767, 768, 770, 2279, 2280, 1636, + 1637, 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, 1728, 1729, 1730, 1731, 1732, 1733, 1734, 1735, 1736, + 1737, 1738, 1739, 1740, 1741, 1742, 1743, 1744, 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, 2278, 2278, 774, 778, 780, 1609, + 803, 809, 811, 812, 0, 0, 822, 825, 842, 49, + 1905, 830, 49, 832, 833, 834, 860, 861, 866, 0, + 0, 0, 0, 872, 873, 874, 0, 0, 877, 878, + 879, 0, 0, 0, 0, 0, 1011, 0, 0, 1137, + 1138, 1139, 1140, 1141, 1142, 1143, 1144, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1036, 1037, 0, 0, 0, + 1061, 1062, 1063, 1064, 1067, 0, 1078, 0, 1080, 1478, + -2, 0, 0, 0, 1072, 1073, 0, 0, 0, 1629, + 1629, 0, 0, 0, 1470, 0, 0, 1163, 0, 1164, + 1166, 1167, 1168, 0, 1169, 1170, 895, 895, 895, 895, + 895, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 895, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1629, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1629, 0, 0, 1629, 1629, 0, 0, 220, 221, 222, + 223, 224, 225, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 297, 240, 241, + 242, 243, 244, 245, 300, 246, 247, 248, 1148, 0, + 0, 0, 46, 850, 851, 0, 972, 1629, 0, 0, + 901, 0, 1644, 57, 66, 68, 1507, 61, 1507, 0, + 905, 0, 0, -2, -2, 906, 907, 911, 912, 913, + 914, 915, 916, 917, 918, 919, 54, 2276, 55, 0, + 74, 0, 48, 0, 0, 1548, 0, 1551, 0, 0, + 0, 375, 1555, 0, 0, 1500, 1501, 1504, 0, 923, + 2001, 927, 0, 929, 930, 0, 0, 100, 0, 988, + 0, 0, 0, 111, 0, 113, 114, 0, 0, 0, + 386, 1612, 1613, 1614, -2, 409, 0, 386, 370, 308, + 309, 310, 361, 312, 361, 361, 361, 361, 375, 375, + 375, 375, 343, 344, 345, 346, 347, 0, 361, 0, + 329, 361, 361, 361, 361, 351, 352, 353, 354, 355, + 356, 357, 358, 313, 314, 315, 316, 317, 318, 319, + 320, 321, 363, 363, 363, 363, 363, 367, 367, 0, + 1106, 0, 390, 0, 1504, 0, 0, 1538, 1621, 1631, + 0, 0, 0, 1621, 132, 0, 0, 0, 577, 620, + 528, 565, 578, 0, 531, 532, -2, 0, 0, 513, + 0, 515, 0, 410, 0, -2, 0, 420, 0, 416, + 420, 417, 420, 408, 421, 555, 556, 557, 0, 559, + 560, 650, 958, 0, 0, 0, 0, 0, 656, 657, + 658, 0, 660, 661, 662, 663, 664, 665, 666, 667, + 668, 669, 566, 567, 568, 569, 570, 571, 572, 573, + 0, 0, 0, 0, 515, 0, 562, 0, 0, 466, + 467, 468, 0, 0, 471, 472, 473, 474, 0, 0, + 477, 478, 479, 975, 976, 480, 481, 506, 507, 508, + 482, 483, 484, 485, 486, 487, 488, 500, 501, 502, + 503, 504, 505, 489, 490, 491, 492, 493, 494, 497, + 0, 147, 1529, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1619, 0, 0, 0, 0, 904, 990, 1642, 1643, 723, + 0, 0, 792, 793, 0, 414, 415, 791, 791, 733, + 775, 0, 791, 737, 776, 738, 740, 739, 741, 754, + 755, 791, 744, 789, 790, 745, 746, 747, 748, 749, + 750, 751, 771, 756, 757, 758, 795, 0, 799, 800, + 772, 773, 0, 781, 0, 0, 815, 816, 0, 823, + 845, 843, 844, 846, 838, 839, 840, 841, 0, 847, + 0, 0, 863, 96, 868, 869, 870, 871, 883, 876, + 1150, 1008, 1009, 1010, 0, 1012, 1018, 0, 1133, 1135, + 1016, 1017, 1020, 0, 0, 0, 1014, 1025, 1145, 1146, + 1147, 0, 0, 0, 0, 0, 1029, 1033, 1038, 1039, + 1040, 1041, 1042, 0, 1043, 0, 1046, 1047, 1048, 1049, + 1050, 1051, 1057, 1446, 1447, 1448, 1076, 301, 302, 0, + 1077, 0, 0, 0, 0, 0, 0, 0, 0, 1393, + 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, + 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1149, + 0, 1630, 0, 0, 0, 1476, 1473, 0, 0, 0, + 1432, 1434, 0, 0, 0, 896, 897, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1413, 1414, 1415, 1416, 1417, 1418, + 1419, 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1428, + 1429, 1430, 0, 0, 1449, 0, 0, 0, 0, 0, + 0, 0, 1469, 0, 1082, 1083, 1084, 0, 0, 0, + 0, 0, 0, 1211, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 142, 143, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1357, + 1358, 1359, 1360, 41, 0, 0, 0, 0, 0, 0, + 0, 1480, 0, -2, -2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1382, 0, + 0, 0, 0, 0, 0, 1602, 0, 0, 853, 854, + 856, 0, 992, 0, 973, 0, 0, 859, 0, 900, + 0, 903, 60, 62, 909, 910, 0, 931, 920, 908, + 56, 51, 0, 0, 950, 1549, 1552, 1553, 375, 1575, + 0, 384, 384, 381, 1510, 1511, 0, 1503, 1505, 1506, + 79, 928, 924, 0, 1006, 0, 0, 987, 0, 934, + 936, 937, 938, 970, 0, 941, 942, 0, 0, 0, + 0, 0, 98, 989, 104, 0, 112, 0, 0, 117, + 118, 105, 106, 107, 108, 0, 609, -2, 461, 179, + 181, 182, 183, 174, -2, 373, 371, 372, 311, 375, + 375, 337, 338, 339, 340, 341, 342, 0, 349, 0, + 330, 331, 332, 333, 322, 0, 323, 324, 325, 365, + 0, 326, 327, 0, 328, 428, 0, 1512, 391, 392, + 394, 402, 0, 397, 398, 0, 402, 402, 0, 423, + 424, 0, 1504, 1529, 0, 0, 0, 1632, 1631, 1631, + 1631, 0, 167, 168, 169, 170, 171, 172, 645, 0, + 0, 621, 643, 644, 165, 0, 0, 175, 517, 516, + 0, 677, 0, 426, 0, 0, 420, 420, 405, 406, + 558, 0, 0, 652, 653, 654, 655, 0, 0, 0, + 544, 455, 0, 545, 546, 515, 517, 0, 0, 386, + 469, 470, 475, 476, 495, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 593, 594, 596, + 599, 601, 519, 605, 607, 595, 598, 600, 602, 519, + 606, 608, 1526, 1527, 1528, 0, 0, 715, 0, 0, + 452, 94, 1620, 720, 724, 725, 788, 743, 777, 788, + 735, 742, 765, 779, 813, 814, 819, 827, 828, 829, + 867, 0, 0, 0, 0, 875, 0, 0, 1019, 1134, + 1136, 1021, 1022, 1023, 1026, 0, 1030, 1034, 0, 0, + 0, 0, 0, 1081, 1079, 1480, 0, 0, 0, 1130, + 0, 0, 1153, 1154, 0, 0, 0, 0, 1474, 0, + 0, 1161, 0, 1435, 1111, 0, 0, 0, 0, 0, + 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, + 1498, 1188, 0, 0, 0, 0, 0, 1193, 1194, 1195, + 1111, 0, 1198, 1199, 0, 1201, 0, 1202, 0, 0, + 0, 0, 1209, 1210, 1212, 0, 0, 1215, 1216, 0, + 1218, 0, 1220, 1221, 1222, 1223, 1224, 1225, 0, 1227, + 0, 1229, 1230, 1231, 0, 1233, 0, 1235, 1236, 0, + 1238, 0, 1240, 0, 1243, 0, 1246, 0, 1249, 0, + 1252, 0, 1255, 0, 1258, 0, 1261, 0, 1264, 0, + 1267, 0, 1270, 0, 1273, 0, 1276, 0, 1279, 0, + 1282, 0, 1285, 0, 1288, 1289, 1290, 0, 1292, 0, + 1294, 0, 1297, 1298, 0, 1300, 0, 1303, 0, 1306, + 0, 0, 1307, 0, 0, 0, 1311, 0, 0, 0, + 0, 1320, 1321, 1322, 1323, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1334, 1335, 1336, 1337, 1338, + 1339, 0, 1341, 0, 1112, 0, 0, 1112, 0, 0, + 0, 0, 0, 1151, 1629, 0, 1436, 1437, 1438, 1439, + 1440, 0, 0, 0, 0, 0, 0, 1380, 1381, 1383, + 0, 0, 1386, 0, 1388, 0, 1603, 852, 855, 857, + 944, 993, 994, 0, 0, 0, 0, 974, 1628, 898, + 899, 902, 952, 0, 1484, 0, 0, 931, 1006, 0, + 932, 0, 53, 947, 0, 1557, 1556, 1569, 1582, 384, + 384, 378, 379, 385, 380, 382, 383, 1502, 0, 1507, + 0, 1596, 0, 0, 1585, 0, 0, 0, 0, 0, + 0, 0, 0, 977, 0, 0, 980, 0, 0, 0, + 0, 971, 942, 0, 943, 0, -2, 0, 0, 92, + 93, 0, 0, 0, 115, 116, 0, 0, 122, 387, + 388, 156, 165, 463, 180, 436, 0, 0, 307, 374, + 334, 335, 336, 0, 359, 0, 0, 0, 0, 457, + 128, 1516, 1515, 402, 402, 393, 0, 396, 0, 0, + 0, 1633, 362, 425, 0, 146, 0, 0, 0, 0, + 0, 152, 615, 0, 0, 622, 0, 0, 0, 526, + 0, 537, 538, 0, 649, -2, 711, 390, 0, 404, + 407, 959, 0, 0, 539, 0, 542, 543, 456, 517, + 548, 549, 563, 550, 498, 499, 496, 0, 0, 1539, + 1540, 1545, 1543, 1544, 133, 584, 586, 590, 585, 589, + 0, 0, 0, 521, 0, 521, 582, 0, 452, 1512, + 0, 719, 453, 454, 791, 791, 862, 97, 0, 865, + 0, 0, 0, 0, 1027, 1031, 1044, 1045, 1441, 1467, + 361, 361, 1454, 361, 367, 1457, 361, 1459, 361, 1462, + 361, 1465, 1466, 0, 0, 1074, 0, 0, 0, 0, + 1160, 1477, 0, 0, 1171, 1110, 1111, 1111, 1111, 1111, + 1111, 1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, + 1186, 1471, 0, 0, 0, 1192, 0, 0, 1196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 145, - 0, 0, 0, 0, 0, 0, 1380, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1096, 1100, - 0, 1104, 1105, 0, 0, 1332, 0, 0, 1350, 0, - 0, 0, 0, 0, 0, 0, 1470, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 986, 993, 0, - 993, 0, 993, 0, 0, 0, 1604, 1605, 1474, 1475, - 997, 1476, 912, 924, 942, 1564, 0, 1557, 0, -2, - 1566, 0, 0, 0, 1572, 375, 376, 916, 80, 998, - 83, 0, 1585, 1594, 0, 1582, 1587, 1589, 0, 0, - 0, 1578, 0, 997, 926, 957, 959, 0, 954, 969, - 970, 972, 0, 974, 0, 976, 977, 937, 931, 0, - 100, 0, 997, 997, 99, 0, 982, 119, 120, 121, - 461, 184, 189, 0, 0, 0, 194, 0, 196, 0, - 0, 0, 201, 202, 401, 401, 436, 0, 304, 306, - 0, 0, 187, 374, 0, 374, 0, 365, 367, 0, - 437, 457, 1502, 1503, 0, 0, 394, 398, 399, 400, - 0, 1611, 148, 0, 0, 0, 616, 0, 644, 0, - 0, 0, 0, 0, 0, 176, 517, 676, 677, 678, - 679, 680, 681, 682, 683, 684, 0, 401, 0, 0, - 0, 401, 401, 401, 0, 701, 388, 0, 0, 672, - 669, 539, 0, 218, 219, 226, 227, 229, 0, 0, - 0, 0, 0, 546, 937, 1519, 1520, 1521, 0, 1531, - 1535, 136, 0, 0, 0, 0, 591, 595, 601, 0, - 519, 602, 714, 715, 716, 95, 726, 732, 859, 879, - 1006, 1019, 1023, 0, 0, 0, 0, 1457, 1441, 374, - 1444, 1445, 1447, 1449, 1450, 1452, 1453, 1061, 1062, 1066, - 0, 1148, 0, 1150, 0, 1464, 0, 1163, 1164, 1165, - 1166, 1167, 1496, 0, 0, 0, 1182, 0, 0, 0, - 1193, 1192, 1194, 0, 1196, 1197, 1202, 1203, 1206, 1208, - 1215, 1217, 1221, 1223, 1226, 1228, 1230, 0, 1233, 0, - 1236, 0, 1239, 0, 1242, 0, 1245, 0, 1248, 0, - 1251, 0, 1254, 0, 1257, 0, 1260, 0, 1263, 0, - 1266, 0, 1269, 0, 1272, 0, 1275, 0, 1280, 1282, - 0, 1285, 1288, 1290, 0, 1293, 0, 1297, 0, 1299, - 1301, 1302, 0, 0, 0, 1313, 1314, 1315, 1316, 1317, - 1318, 1319, 1320, 1321, 1322, 1329, 0, 1094, 1331, 1106, - 1107, 1112, 1334, 0, 0, 0, 1337, 0, 0, 0, - 1341, 1143, 1352, 0, 1357, 0, 0, 1363, 0, 1367, - 0, 1373, 1374, 1376, 1378, 0, 0, 0, 0, 0, - 0, 0, 963, 944, 64, 1476, 1480, 0, 1551, 1549, - 1549, 1559, 1560, 0, 0, 1567, 0, 0, 0, 0, - 84, 0, 0, 1573, 0, 0, 1590, 0, 0, 0, - 0, 101, 1487, 951, 958, 0, 0, 952, 0, 953, - 973, 975, 930, 0, 997, 997, 90, 91, 0, 190, - 0, 192, 0, 195, 197, 198, 199, 205, 206, 207, - 200, 0, 0, 303, 305, 0, 0, 348, 359, 349, - 0, 0, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513, - 937, 149, 150, 151, 608, 0, 618, 0, 939, 0, - 611, 0, 528, 0, 0, 0, 401, 401, 401, 0, - 0, 0, 0, 686, 0, 0, 649, 0, 657, 0, - 0, 0, 230, 231, 0, 1530, 582, 0, 134, 135, - 0, 0, 587, 521, 522, 1059, 0, 0, 0, 1060, - 1442, 0, 0, 0, 0, 0, 1461, 0, 0, 0, - 0, 1189, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1305, 0, 0, 0, 638, 639, - 0, 1381, 1099, 1487, 0, 1103, 1113, 1114, 0, 1103, - 1351, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 994, 0, 0, 0, 945, 946, 0, 0, - 0, 983, 1480, 1485, 0, 0, 1554, 0, 1547, 1550, - 1548, 1561, 0, 0, 1568, 0, 1570, 0, 1595, 1596, - 1588, 1583, 0, 1577, 1580, 1582, 1579, 1496, 955, 0, - 960, 0, 1487, 89, 0, 193, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 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, 204, 0, 0, 363, - 368, 0, 0, 0, 609, 0, 940, 621, 612, 0, - 699, 0, 703, 0, 0, 0, 706, 707, 708, 685, - 0, 689, 429, 673, 670, 671, 540, 0, 137, 138, - 0, 0, 0, 1431, 0, 1434, 1146, 1149, 1147, 0, - 1178, 1180, 1181, 1439, 1440, 1195, 1231, 1234, 1237, 1240, - 1243, 1246, 1249, 1252, 1255, 1258, 1261, 1264, 1267, 1270, - 1273, 1276, 1284, 1291, 1294, 1298, 1303, 0, 1306, 0, - 0, 1307, 0, 640, 1090, 0, 0, 1110, 1111, 0, - 1336, 1338, 1339, 1340, 1353, 0, 1358, 1359, 0, 1364, - 0, 1368, 1379, 0, 988, 995, 996, 0, 991, 0, - 992, 0, 936, 1485, 82, 1486, 1483, 0, 1481, 1478, - 1543, 0, 1552, 1553, 1562, 1563, 1569, 0, 0, 1582, - 0, 1576, 87, 0, 0, 0, 1496, 191, 0, 210, - 0, 617, 0, 620, 610, 697, 698, 0, 710, 702, - 704, 705, 687, -2, 1522, 0, 0, 0, 590, 1432, - 0, 0, 1308, 0, 636, 637, 1098, 1091, 0, 1076, - 1077, 1095, 1333, 1335, 0, 0, 0, 987, 947, 948, - 989, 990, 81, 0, 1482, 1118, 0, 1477, 0, 1555, - 1556, 1586, 0, 1575, 1581, 956, 963, 0, 88, 442, - 435, 1522, 0, 0, 0, 690, 691, 692, 693, 694, - 695, 696, 579, 1524, 139, 140, 0, 509, 510, 511, - 133, 0, 1153, 1304, 1092, 0, 0, 0, 0, 0, - 1354, 0, 1360, 0, 1365, 0, 1484, 0, 0, 1479, - 1584, 622, 0, 624, 0, -2, 430, 443, 0, 185, - 211, 212, 0, 0, 215, 216, 217, 208, 209, 129, - 0, 0, 711, 0, 1525, 1526, 0, 136, 0, 0, - 1083, 1084, 1085, 1086, 1088, 0, 0, 0, 0, 1119, - 1096, 623, 0, 0, 385, 0, 633, 431, 432, 0, - 438, 439, 440, 441, 213, 214, 645, 0, 0, 508, - 586, 1433, 0, 0, 1355, 0, 1361, 0, 1366, 0, - 625, 626, 634, 0, 433, 0, 434, 0, 0, 0, - 614, 0, 645, 1523, 1093, 1087, 1089, 0, 0, 1117, - 0, 635, 631, 444, 446, 447, 0, 0, 445, 646, - 615, 1356, 1362, 0, 448, 449, 450, 627, 628, 629, - 630, + 0, 0, 0, 0, 0, 0, 1391, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1105, 1109, + 0, 1113, 1114, 0, 0, 1343, 0, 0, 1361, 0, + 0, 0, 0, 0, 0, 0, 1481, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 995, 1002, 0, + 1002, 0, 1002, 0, 0, 0, 1615, 1616, 1485, 1486, + 1006, 1487, 921, 933, 951, 1575, 0, 1568, 0, -2, + 1577, 0, 0, 0, 1583, 376, 377, 925, 80, 1007, + 83, 0, 1596, 1605, 0, 1593, 1598, 1600, 0, 0, + 0, 1589, 0, 1006, 935, 966, 968, 0, 963, 978, + 979, 981, 0, 983, 0, 985, 986, 946, 940, 0, + 100, 0, 1006, 1006, 99, 0, 991, 119, 120, 121, + 462, 184, 189, 0, 0, 0, 194, 0, 196, 0, + 0, 0, 201, 202, 402, 402, 437, 0, 304, 306, + 0, 0, 187, 375, 0, 375, 0, 366, 368, 0, + 438, 458, 1513, 1514, 0, 0, 395, 399, 400, 401, + 0, 1622, 148, 0, 0, 0, 618, 0, 646, 0, + 0, 0, 0, 0, 0, 176, 518, 678, 679, 680, + 681, 682, 683, 684, 685, 686, 0, 402, 0, 0, + 0, 402, 402, 402, 0, 703, 389, 0, 0, 674, + 671, 540, 0, 218, 219, 226, 227, 229, 0, 0, + 0, 0, 0, 547, 946, 1530, 1531, 1532, 0, 1542, + 1546, 136, 0, 0, 0, 0, 592, 597, 603, 0, + 520, 604, 716, 717, 718, 95, 728, 734, 864, 884, + 1015, 1028, 1032, 0, 0, 0, 0, 1468, 1452, 375, + 1455, 1456, 1458, 1460, 1461, 1463, 1464, 1070, 1071, 1075, + 0, 1157, 0, 1159, 0, 1475, 0, 1172, 1173, 1174, + 1175, 1176, 1507, 0, 0, 0, 1191, 0, 0, 1111, + 0, 1204, 1203, 1205, 0, 1207, 1208, 1213, 1214, 1217, + 1219, 1226, 1228, 1232, 1234, 1237, 1239, 1241, 0, 1244, + 0, 1247, 0, 1250, 0, 1253, 0, 1256, 0, 1259, + 0, 1262, 0, 1265, 0, 1268, 0, 1271, 0, 1274, + 0, 1277, 0, 1280, 0, 1283, 0, 1286, 0, 1291, + 1293, 0, 1296, 1299, 1301, 0, 1304, 0, 1308, 0, + 1310, 1312, 1313, 0, 0, 0, 1324, 1325, 1326, 1327, + 1328, 1329, 1330, 1331, 1332, 1333, 1340, 0, 1103, 1342, + 1115, 1116, 1121, 1345, 0, 0, 0, 1348, 0, 0, + 0, 1352, 1152, 1363, 0, 1368, 0, 0, 1374, 0, + 1378, 0, 1384, 1385, 1387, 1389, 0, 0, 0, 0, + 0, 0, 0, 972, 953, 64, 1487, 1491, 0, 1562, + 1560, 1560, 1570, 1571, 0, 0, 1578, 0, 0, 0, + 0, 84, 0, 0, 1584, 0, 0, 1601, 0, 0, + 0, 0, 101, 1498, 960, 967, 0, 0, 961, 0, + 962, 982, 984, 939, 0, 1006, 1006, 90, 91, 0, + 190, 0, 192, 0, 195, 197, 198, 199, 205, 206, + 207, 200, 0, 0, 303, 305, 0, 0, 348, 360, + 350, 0, 0, 1517, 1518, 1519, 1520, 1521, 1522, 1523, + 1524, 946, 149, 150, 151, 610, 0, 620, 0, 948, + 0, 613, 0, 529, 0, 0, 0, 402, 402, 402, + 0, 0, 0, 0, 688, 0, 0, 651, 0, 659, + 0, 0, 0, 230, 231, 0, 1541, 583, 0, 134, + 135, 0, 0, 588, 522, 523, 1068, 0, 0, 0, + 1069, 1453, 0, 0, 0, 0, 0, 1472, 0, 0, + 0, 0, 1197, 1200, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1316, 0, 0, 0, + 640, 641, 0, 1392, 1108, 1498, 0, 1112, 1122, 1123, + 0, 1112, 1362, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1003, 0, 0, 0, 954, 955, + 0, 0, 0, 992, 1491, 1496, 0, 0, 1565, 0, + 1558, 1561, 1559, 1572, 0, 0, 1579, 0, 1581, 0, + 1606, 1607, 1599, 1594, 0, 1588, 1591, 1593, 1590, 1507, + 964, 0, 969, 0, 1498, 89, 0, 193, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 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, + 204, 0, 0, 364, 369, 0, 0, 0, 611, 0, + 949, 623, 614, 0, 701, 0, 705, 0, 0, 0, + 708, 709, 710, 687, 0, 691, 430, 675, 672, 673, + 541, 0, 137, 138, 0, 0, 0, 1442, 0, 1445, + 1155, 1158, 1156, 0, 1187, 1189, 1190, 1450, 1451, 1206, + 1242, 1245, 1248, 1251, 1254, 1257, 1260, 1263, 1266, 1269, + 1272, 1275, 1278, 1281, 1284, 1287, 1295, 1302, 1305, 1309, + 1314, 0, 1317, 0, 0, 1318, 0, 642, 1099, 0, + 0, 1119, 1120, 0, 1347, 1349, 1350, 1351, 1364, 0, + 1369, 1370, 0, 1375, 0, 1379, 1390, 0, 997, 1004, + 1005, 0, 1000, 0, 1001, 0, 945, 1496, 82, 1497, + 1494, 0, 1492, 1489, 1554, 0, 1563, 1564, 1573, 1574, + 1580, 0, 0, 1593, 0, 1587, 87, 0, 0, 0, + 1507, 191, 0, 210, 0, 619, 0, 622, 612, 699, + 700, 0, 712, 704, 706, 707, 689, -2, 1533, 0, + 0, 0, 591, 1443, 0, 0, 1319, 0, 638, 639, + 1107, 1100, 0, 1085, 1086, 1104, 1344, 1346, 0, 0, + 0, 996, 956, 957, 998, 999, 81, 0, 1493, 1127, + 0, 1488, 0, 1566, 1567, 1597, 0, 1586, 1592, 965, + 972, 0, 88, 443, 436, 1533, 0, 0, 0, 692, + 693, 694, 695, 696, 697, 698, 580, 1535, 139, 140, + 0, 510, 511, 512, 133, 0, 1162, 1315, 1101, 0, + 0, 0, 0, 0, 1365, 0, 1371, 0, 1376, 0, + 1495, 0, 0, 1490, 1595, 624, 0, 626, 0, -2, + 431, 444, 0, 185, 211, 212, 0, 0, 215, 216, + 217, 208, 209, 129, 0, 0, 713, 0, 1536, 1537, + 0, 136, 0, 0, 1092, 1093, 1094, 1095, 1097, 0, + 0, 0, 0, 1128, 1105, 625, 0, 0, 386, 0, + 635, 432, 433, 0, 439, 440, 441, 442, 213, 214, + 647, 0, 0, 509, 587, 1444, 0, 0, 1366, 0, + 1372, 0, 1377, 0, 627, 628, 636, 0, 434, 0, + 435, 0, 0, 0, 616, 0, 647, 1534, 1102, 1096, + 1098, 0, 0, 1126, 0, 637, 633, 445, 447, 448, + 0, 0, 446, 648, 617, 1367, 1373, 0, 449, 450, + 451, 629, 630, 631, 632, } var yyTok1 = [...]int{ 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 150, 3, 3, 3, 178, 170, 3, - 91, 93, 175, 173, 92, 174, 228, 176, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 740, - 158, 157, 159, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 157, 3, 3, 3, 185, 177, 3, + 95, 97, 182, 180, 96, 181, 235, 183, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 748, + 165, 164, 166, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 180, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 187, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 146, 3, 181, + 3, 3, 3, 3, 153, 3, 188, } var yyTok2 = [...]int{ @@ -9800,20 +9839,20 @@ var yyTok2 = [...]int{ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, 90, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 147, 148, 149, 151, 152, 153, 154, 155, 156, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, - 171, 172, 177, 179, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, + 145, 146, 147, 148, 149, 150, 151, 152, 154, 155, + 156, 158, 159, 160, 161, 162, 163, 167, 168, 169, + 170, 171, 172, 173, 174, 175, 176, 178, 179, 184, + 186, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, - 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, + 228, 229, 230, 231, 232, 233, 234, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, @@ -9914,7 +9953,8 @@ var yyTok3 = [...]int{ 58050, 725, 58051, 726, 58052, 727, 58053, 728, 58054, 729, 58055, 730, 58056, 731, 58057, 732, 58058, 733, 58059, 734, 58060, 735, 58061, 736, 58062, 737, 58063, 738, 58064, 739, - 0, + 58065, 740, 58066, 741, 58067, 742, 58068, 743, 58069, 744, + 58070, 745, 58071, 746, 58072, 747, 0, } var yyErrorMessages = [...]struct { @@ -10264,7 +10304,7 @@ yydefault: case 1: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:621 +//line sql.y:630 { stmt := yyDollar[2].statementUnion() // If the statement is empty and we have comments @@ -10278,46 +10318,46 @@ yydefault: } case 2: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:634 +//line sql.y:643 { } case 3: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:635 +//line sql.y:644 { } case 4: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:639 +//line sql.y:648 { yyLOCAL = yyDollar[1].selStmtUnion() } yyVAL.union = yyLOCAL case 40: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:678 +//line sql.y:687 { setParseTree(yylex, nil) } case 41: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Variable -//line sql.y:684 +//line sql.y:693 { yyLOCAL = NewVariableExpression(yyDollar[1].str, SingleAt) } yyVAL.union = yyLOCAL case 42: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:690 +//line sql.y:699 { yyVAL.identifierCI = NewIdentifierCI(string(yyDollar[1].str)) } case 43: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Variable -//line sql.y:696 +//line sql.y:705 { yyLOCAL = NewVariableExpression(string(yyDollar[1].str), SingleAt) } @@ -10325,7 +10365,7 @@ yydefault: case 44: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Variable -//line sql.y:700 +//line sql.y:709 { yyLOCAL = NewVariableExpression(string(yyDollar[1].str), DoubleAt) } @@ -10333,7 +10373,7 @@ yydefault: case 45: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:706 +//line sql.y:715 { yyLOCAL = &OtherAdmin{} } @@ -10341,7 +10381,7 @@ yydefault: case 46: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:712 +//line sql.y:721 { yyLOCAL = &Load{} } @@ -10349,7 +10389,7 @@ yydefault: case 47: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *With -//line sql.y:718 +//line sql.y:727 { yyLOCAL = &With{CTEs: yyDollar[2].ctesUnion(), Recursive: false} } @@ -10357,7 +10397,7 @@ yydefault: case 48: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *With -//line sql.y:722 +//line sql.y:731 { yyLOCAL = &With{CTEs: yyDollar[3].ctesUnion(), Recursive: true} } @@ -10365,7 +10405,7 @@ yydefault: case 49: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *With -//line sql.y:727 +//line sql.y:736 { yyLOCAL = nil } @@ -10373,14 +10413,14 @@ yydefault: case 50: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *With -//line sql.y:731 +//line sql.y:740 { yyLOCAL = yyDollar[1].withUnion() } yyVAL.union = yyLOCAL case 51: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:737 +//line sql.y:746 { yySLICE := (*[]*CommonTableExpr)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].cteUnion()) @@ -10388,7 +10428,7 @@ yydefault: case 52: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*CommonTableExpr -//line sql.y:741 +//line sql.y:750 { yyLOCAL = []*CommonTableExpr{yyDollar[1].cteUnion()} } @@ -10396,7 +10436,7 @@ yydefault: case 53: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *CommonTableExpr -//line sql.y:747 +//line sql.y:756 { yyLOCAL = &CommonTableExpr{ID: yyDollar[1].identifierCS, Columns: yyDollar[2].columnsUnion(), Subquery: yyDollar[4].subqueryUnion()} } @@ -10404,7 +10444,7 @@ yydefault: case 54: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:753 +//line sql.y:762 { yyLOCAL = yyDollar[2].selStmtUnion() } @@ -10412,7 +10452,7 @@ yydefault: case 55: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:757 +//line sql.y:766 { yyLOCAL = yyDollar[2].selStmtUnion() } @@ -10420,7 +10460,7 @@ yydefault: case 56: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:761 +//line sql.y:770 { setLockInSelect(yyDollar[2].selStmtUnion(), yyDollar[3].lockUnion()) yyLOCAL = yyDollar[2].selStmtUnion() @@ -10429,7 +10469,7 @@ yydefault: case 57: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:784 +//line sql.y:793 { yyDollar[1].selStmtUnion().SetOrderBy(yyDollar[2].orderByUnion()) yyDollar[1].selStmtUnion().SetLimit(yyDollar[3].limitUnion()) @@ -10439,7 +10479,7 @@ yydefault: case 58: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:790 +//line sql.y:799 { yyDollar[1].selStmtUnion().SetLimit(yyDollar[2].limitUnion()) yyLOCAL = yyDollar[1].selStmtUnion() @@ -10448,7 +10488,7 @@ yydefault: case 59: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:795 +//line sql.y:804 { yyDollar[1].selStmtUnion().SetOrderBy(yyDollar[2].orderByUnion()) yyDollar[1].selStmtUnion().SetLimit(yyDollar[3].limitUnion()) @@ -10458,7 +10498,7 @@ yydefault: case 60: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:801 +//line sql.y:810 { yyDollar[2].selStmtUnion().SetWith(yyDollar[1].withUnion()) yyDollar[2].selStmtUnion().SetOrderBy(yyDollar[3].orderByUnion()) @@ -10469,7 +10509,7 @@ yydefault: case 61: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:808 +//line sql.y:817 { yyDollar[2].selStmtUnion().SetWith(yyDollar[1].withUnion()) yyDollar[2].selStmtUnion().SetLimit(yyDollar[3].limitUnion()) @@ -10479,7 +10519,7 @@ yydefault: case 62: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:814 +//line sql.y:823 { yyDollar[2].selStmtUnion().SetWith(yyDollar[1].withUnion()) yyDollar[2].selStmtUnion().SetOrderBy(yyDollar[3].orderByUnion()) @@ -10489,14 +10529,14 @@ yydefault: yyVAL.union = yyLOCAL case 63: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:821 +//line sql.y:830 { yyDollar[2].selStmtUnion().SetWith(yyDollar[1].withUnion()) } case 64: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:825 +//line sql.y:834 { yyLOCAL = NewSelect(Comments(yyDollar[2].strs), SelectExprs{&Nextval{Expr: yyDollar[5].exprUnion()}}, []string{yyDollar[3].str} /*options*/, nil, TableExprs{&AliasedTableExpr{Expr: yyDollar[7].tableName}}, nil /*where*/, nil /*groupBy*/, nil /*having*/, nil) } @@ -10504,7 +10544,7 @@ yydefault: case 65: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:831 +//line sql.y:840 { yyLOCAL = yyDollar[1].selStmtUnion() } @@ -10512,7 +10552,7 @@ yydefault: case 66: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:835 +//line sql.y:844 { yyLOCAL = &Union{Left: yyDollar[1].selStmtUnion(), Distinct: yyDollar[2].booleanUnion(), Right: yyDollar[3].selStmtUnion()} } @@ -10520,7 +10560,7 @@ yydefault: case 67: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:839 +//line sql.y:848 { yyLOCAL = &Union{Left: yyDollar[1].selStmtUnion(), Distinct: yyDollar[2].booleanUnion(), Right: yyDollar[3].selStmtUnion()} } @@ -10528,7 +10568,7 @@ yydefault: case 68: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:843 +//line sql.y:852 { yyLOCAL = &Union{Left: yyDollar[1].selStmtUnion(), Distinct: yyDollar[2].booleanUnion(), Right: yyDollar[3].selStmtUnion()} } @@ -10536,7 +10576,7 @@ yydefault: case 69: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:847 +//line sql.y:856 { yyLOCAL = &Union{Left: yyDollar[1].selStmtUnion(), Distinct: yyDollar[2].booleanUnion(), Right: yyDollar[3].selStmtUnion()} } @@ -10544,7 +10584,7 @@ yydefault: case 70: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:853 +//line sql.y:862 { yyLOCAL = yyDollar[1].selStmtUnion() } @@ -10552,7 +10592,7 @@ yydefault: case 71: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:857 +//line sql.y:866 { setLockInSelect(yyDollar[1].selStmtUnion(), yyDollar[2].lockUnion()) yyLOCAL = yyDollar[1].selStmtUnion() @@ -10561,7 +10601,7 @@ yydefault: case 72: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:862 +//line sql.y:871 { yyLOCAL = yyDollar[1].selStmtUnion() } @@ -10569,7 +10609,7 @@ yydefault: case 73: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:866 +//line sql.y:875 { yyLOCAL = yyDollar[1].selStmtUnion() } @@ -10577,7 +10617,7 @@ yydefault: case 74: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:872 +//line sql.y:881 { yyLOCAL = yyDollar[2].selStmtUnion() } @@ -10585,7 +10625,7 @@ yydefault: case 75: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:876 +//line sql.y:885 { yyDollar[1].selStmtUnion().SetInto(yyDollar[2].selectIntoUnion()) yyLOCAL = yyDollar[1].selStmtUnion() @@ -10594,7 +10634,7 @@ yydefault: case 76: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:881 +//line sql.y:890 { yyDollar[1].selStmtUnion().SetInto(yyDollar[2].selectIntoUnion()) yyDollar[1].selStmtUnion().SetLock(yyDollar[3].lockUnion()) @@ -10604,7 +10644,7 @@ yydefault: case 77: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:887 +//line sql.y:896 { yyDollar[1].selStmtUnion().SetInto(yyDollar[3].selectIntoUnion()) yyDollar[1].selStmtUnion().SetLock(yyDollar[2].lockUnion()) @@ -10614,7 +10654,7 @@ yydefault: case 78: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:893 +//line sql.y:902 { yyDollar[1].selStmtUnion().SetInto(yyDollar[2].selectIntoUnion()) yyLOCAL = yyDollar[1].selStmtUnion() @@ -10623,7 +10663,7 @@ yydefault: case 79: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:900 +//line sql.y:909 { yyLOCAL = &Stream{Comments: Comments(yyDollar[2].strs).Parsed(), SelectExpr: yyDollar[3].selectExprUnion(), Table: yyDollar[5].tableName} } @@ -10631,7 +10671,7 @@ yydefault: case 80: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:906 +//line sql.y:915 { 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()} } @@ -10639,7 +10679,7 @@ yydefault: case 81: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:914 +//line sql.y:923 { 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()) } @@ -10647,7 +10687,7 @@ yydefault: case 82: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL SelectStatement -//line sql.y:918 +//line sql.y:927 { 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()) } @@ -10655,7 +10695,7 @@ yydefault: case 83: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:924 +//line sql.y:933 { // insert_data returns a *Insert pre-filled with Columns & Values ins := yyDollar[6].insUnion() @@ -10671,7 +10711,7 @@ yydefault: case 84: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Statement -//line sql.y:936 +//line sql.y:945 { cols := make(Columns, 0, len(yyDollar[7].updateExprsUnion())) vals := make(ValTuple, 0, len(yyDollar[8].updateExprsUnion())) @@ -10685,7 +10725,7 @@ yydefault: case 85: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL InsertAction -//line sql.y:948 +//line sql.y:957 { yyLOCAL = InsertAct } @@ -10693,7 +10733,7 @@ yydefault: case 86: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL InsertAction -//line sql.y:952 +//line sql.y:961 { yyLOCAL = ReplaceAct } @@ -10701,7 +10741,7 @@ yydefault: case 87: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL Statement -//line sql.y:958 +//line sql.y:967 { 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()} } @@ -10709,7 +10749,7 @@ yydefault: case 88: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL Statement -//line sql.y:964 +//line sql.y:973 { 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()} } @@ -10717,7 +10757,7 @@ yydefault: case 89: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL Statement -//line sql.y:968 +//line sql.y:977 { 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())} } @@ -10725,7 +10765,7 @@ yydefault: case 90: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Statement -//line sql.y:972 +//line sql.y:981 { 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())} } @@ -10733,32 +10773,32 @@ yydefault: case 91: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Statement -//line sql.y:976 +//line sql.y:985 { 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 92: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:981 +//line sql.y:990 { } case 93: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:982 +//line sql.y:991 { } case 94: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableNames -//line sql.y:986 +//line sql.y:995 { yyLOCAL = TableNames{yyDollar[1].tableName} } yyVAL.union = yyLOCAL case 95: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:990 +//line sql.y:999 { yySLICE := (*TableNames)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].tableName) @@ -10766,14 +10806,14 @@ yydefault: case 96: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableNames -//line sql.y:996 +//line sql.y:1005 { yyLOCAL = TableNames{yyDollar[1].tableName} } yyVAL.union = yyLOCAL case 97: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1000 +//line sql.y:1009 { yySLICE := (*TableNames)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].tableName) @@ -10781,14 +10821,14 @@ yydefault: case 98: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableNames -//line sql.y:1006 +//line sql.y:1015 { yyLOCAL = TableNames{yyDollar[1].tableName} } yyVAL.union = yyLOCAL case 99: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1010 +//line sql.y:1019 { yySLICE := (*TableNames)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].tableName) @@ -10796,7 +10836,7 @@ yydefault: case 100: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Partitions -//line sql.y:1015 +//line sql.y:1024 { yyLOCAL = nil } @@ -10804,7 +10844,7 @@ yydefault: case 101: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Partitions -//line sql.y:1019 +//line sql.y:1028 { yyLOCAL = yyDollar[3].partitionsUnion() } @@ -10812,7 +10852,7 @@ yydefault: case 102: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:1025 +//line sql.y:1034 { yyLOCAL = NewSetStatement(Comments(yyDollar[2].strs).Parsed(), yyDollar[3].setExprsUnion()) } @@ -10820,14 +10860,14 @@ yydefault: case 103: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL SetExprs -//line sql.y:1031 +//line sql.y:1040 { yyLOCAL = SetExprs{yyDollar[1].setExprUnion()} } yyVAL.union = yyLOCAL case 104: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1035 +//line sql.y:1044 { yySLICE := (*SetExprs)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].setExprUnion()) @@ -10835,7 +10875,7 @@ yydefault: case 105: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *SetExpr -//line sql.y:1041 +//line sql.y:1050 { yyLOCAL = &SetExpr{Var: yyDollar[1].variableUnion(), Expr: NewStrLiteral("on")} } @@ -10843,7 +10883,7 @@ yydefault: case 106: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *SetExpr -//line sql.y:1045 +//line sql.y:1054 { yyLOCAL = &SetExpr{Var: yyDollar[1].variableUnion(), Expr: NewStrLiteral("off")} } @@ -10851,7 +10891,7 @@ yydefault: case 107: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *SetExpr -//line sql.y:1049 +//line sql.y:1058 { yyLOCAL = &SetExpr{Var: yyDollar[1].variableUnion(), Expr: yyDollar[3].exprUnion()} } @@ -10859,7 +10899,7 @@ yydefault: case 108: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *SetExpr -//line sql.y:1053 +//line sql.y:1062 { yyLOCAL = &SetExpr{Var: NewSetVariable(string(yyDollar[1].str), SessionScope), Expr: yyDollar[2].exprUnion()} } @@ -10867,7 +10907,7 @@ yydefault: case 109: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Variable -//line sql.y:1059 +//line sql.y:1068 { yyLOCAL = NewSetVariable(string(yyDollar[1].str), SessionScope) } @@ -10875,7 +10915,7 @@ yydefault: case 110: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Variable -//line sql.y:1063 +//line sql.y:1072 { yyLOCAL = yyDollar[1].variableUnion() } @@ -10883,7 +10923,7 @@ yydefault: case 111: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *Variable -//line sql.y:1067 +//line sql.y:1076 { yyLOCAL = NewSetVariable(string(yyDollar[2].str), yyDollar[1].scopeUnion()) } @@ -10891,7 +10931,7 @@ yydefault: case 112: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:1073 +//line sql.y:1082 { yyLOCAL = NewSetStatement(Comments(yyDollar[2].strs).Parsed(), UpdateSetExprsScope(yyDollar[5].setExprsUnion(), yyDollar[3].scopeUnion())) } @@ -10899,7 +10939,7 @@ yydefault: case 113: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:1077 +//line sql.y:1086 { yyLOCAL = NewSetStatement(Comments(yyDollar[2].strs).Parsed(), yyDollar[4].setExprsUnion()) } @@ -10907,14 +10947,14 @@ yydefault: case 114: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL SetExprs -//line sql.y:1083 +//line sql.y:1092 { yyLOCAL = SetExprs{yyDollar[1].setExprUnion()} } yyVAL.union = yyLOCAL case 115: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1087 +//line sql.y:1096 { yySLICE := (*SetExprs)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].setExprUnion()) @@ -10922,7 +10962,7 @@ yydefault: case 116: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *SetExpr -//line sql.y:1093 +//line sql.y:1102 { yyLOCAL = &SetExpr{Var: NewSetVariable(TransactionIsolationStr, NextTxScope), Expr: NewStrLiteral(yyDollar[3].str)} } @@ -10930,7 +10970,7 @@ yydefault: case 117: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *SetExpr -//line sql.y:1097 +//line sql.y:1106 { yyLOCAL = &SetExpr{Var: NewSetVariable(TransactionReadOnlyStr, NextTxScope), Expr: NewStrLiteral("off")} } @@ -10938,39 +10978,39 @@ yydefault: case 118: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *SetExpr -//line sql.y:1101 +//line sql.y:1110 { yyLOCAL = &SetExpr{Var: NewSetVariable(TransactionReadOnlyStr, NextTxScope), Expr: NewStrLiteral("on")} } yyVAL.union = yyLOCAL case 119: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1107 +//line sql.y:1116 { yyVAL.str = RepeatableReadStr } case 120: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1111 +//line sql.y:1120 { yyVAL.str = ReadCommittedStr } case 121: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1115 +//line sql.y:1124 { yyVAL.str = ReadUncommittedStr } case 122: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1119 +//line sql.y:1128 { yyVAL.str = SerializableStr } case 123: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Scope -//line sql.y:1125 +//line sql.y:1134 { yyLOCAL = SessionScope } @@ -10978,7 +11018,7 @@ yydefault: case 124: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Scope -//line sql.y:1129 +//line sql.y:1138 { yyLOCAL = SessionScope } @@ -10986,7 +11026,7 @@ yydefault: case 125: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Scope -//line sql.y:1133 +//line sql.y:1142 { yyLOCAL = GlobalScope } @@ -10994,7 +11034,7 @@ yydefault: case 126: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:1139 +//line sql.y:1148 { yyDollar[1].createTableUnion().TableSpec = yyDollar[2].tableSpecUnion() yyDollar[1].createTableUnion().FullyParsed = true @@ -11004,7 +11044,7 @@ yydefault: case 127: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:1145 +//line sql.y:1154 { // Create table [name] like [name] yyDollar[1].createTableUnion().OptLike = yyDollar[2].optLikeUnion() @@ -11015,7 +11055,7 @@ yydefault: case 128: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:1152 +//line sql.y:1161 { indexDef := yyDollar[1].alterTableUnion().AlterOptions[0].(*AddIndexDefinition).IndexDefinition indexDef.Columns = yyDollar[3].indexColumnsUnion() @@ -11028,7 +11068,7 @@ yydefault: case 129: yyDollar = yyS[yypt-12 : yypt+1] var yyLOCAL Statement -//line sql.y:1161 +//line sql.y:1170 { 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, Columns: yyDollar[9].columnsUnion(), Select: yyDollar[11].selStmtUnion(), CheckOption: yyDollar[12].str} } @@ -11036,7 +11076,7 @@ yydefault: case 130: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:1165 +//line sql.y:1174 { yyDollar[1].createDatabaseUnion().FullyParsed = true yyDollar[1].createDatabaseUnion().CreateOptions = yyDollar[2].databaseOptionsUnion() @@ -11046,7 +11086,7 @@ yydefault: case 131: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:1172 +//line sql.y:1181 { yyLOCAL = false } @@ -11054,33 +11094,33 @@ yydefault: case 132: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:1176 +//line sql.y:1185 { yyLOCAL = true } yyVAL.union = yyLOCAL case 133: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1181 +//line sql.y:1190 { yyVAL.identifierCI = NewIdentifierCI("") } case 134: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1185 +//line sql.y:1194 { yyVAL.identifierCI = yyDollar[2].identifierCI } case 135: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1191 +//line sql.y:1200 { yyVAL.identifierCI = yyDollar[1].identifierCI } case 136: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []VindexParam -//line sql.y:1196 +//line sql.y:1205 { var v []VindexParam yyLOCAL = v @@ -11089,7 +11129,7 @@ yydefault: case 137: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []VindexParam -//line sql.y:1201 +//line sql.y:1210 { yyLOCAL = yyDollar[2].vindexParamsUnion() } @@ -11097,7 +11137,7 @@ yydefault: case 138: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []VindexParam -//line sql.y:1207 +//line sql.y:1216 { yyLOCAL = make([]VindexParam, 0, 4) yyLOCAL = append(yyLOCAL, yyDollar[1].vindexParam) @@ -11105,21 +11145,21 @@ yydefault: yyVAL.union = yyLOCAL case 139: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1212 +//line sql.y:1221 { yySLICE := (*[]VindexParam)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].vindexParam) } case 140: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1218 +//line sql.y:1227 { yyVAL.vindexParam = VindexParam{Key: yyDollar[1].identifierCI, Val: yyDollar[3].str} } case 141: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*JSONObjectParam -//line sql.y:1223 +//line sql.y:1232 { yyLOCAL = nil } @@ -11127,7 +11167,7 @@ yydefault: case 142: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*JSONObjectParam -//line sql.y:1227 +//line sql.y:1236 { yyLOCAL = yyDollar[1].jsonObjectParamsUnion() } @@ -11135,28 +11175,28 @@ yydefault: case 143: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*JSONObjectParam -//line sql.y:1233 +//line sql.y:1242 { yyLOCAL = []*JSONObjectParam{yyDollar[1].jsonObjectParam} } yyVAL.union = yyLOCAL case 144: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1237 +//line sql.y:1246 { yySLICE := (*[]*JSONObjectParam)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].jsonObjectParam) } case 145: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1243 +//line sql.y:1252 { yyVAL.jsonObjectParam = &JSONObjectParam{Key: yyDollar[1].exprUnion(), Value: yyDollar[3].exprUnion()} } case 146: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *CreateTable -//line sql.y:1249 +//line sql.y:1258 { yyLOCAL = &CreateTable{Comments: Comments(yyDollar[2].strs).Parsed(), Table: yyDollar[6].tableName, IfNotExists: yyDollar[5].booleanUnion(), Temp: yyDollar[3].booleanUnion()} setDDL(yylex, yyLOCAL) @@ -11165,7 +11205,7 @@ yydefault: case 147: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *AlterTable -//line sql.y:1256 +//line sql.y:1265 { yyLOCAL = &AlterTable{Comments: Comments(yyDollar[2].strs).Parsed(), Table: yyDollar[4].tableName} setDDL(yylex, yyLOCAL) @@ -11174,7 +11214,7 @@ yydefault: case 148: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *AlterTable -//line sql.y:1263 +//line sql.y:1272 { yyLOCAL = &AlterTable{Table: yyDollar[7].tableName, AlterOptions: []AlterOption{&AddIndexDefinition{IndexDefinition: &IndexDefinition{Info: &IndexInfo{Name: yyDollar[4].identifierCI}, Options: yyDollar[5].indexOptionsUnion()}}}} setDDL(yylex, yyLOCAL) @@ -11183,7 +11223,7 @@ yydefault: case 149: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *AlterTable -//line sql.y:1268 +//line sql.y:1277 { yyLOCAL = &AlterTable{Table: yyDollar[8].tableName, AlterOptions: []AlterOption{&AddIndexDefinition{IndexDefinition: &IndexDefinition{Info: &IndexInfo{Name: yyDollar[5].identifierCI, Type: IndexTypeFullText}, Options: yyDollar[6].indexOptionsUnion()}}}} setDDL(yylex, yyLOCAL) @@ -11192,7 +11232,7 @@ yydefault: case 150: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *AlterTable -//line sql.y:1273 +//line sql.y:1282 { yyLOCAL = &AlterTable{Table: yyDollar[8].tableName, AlterOptions: []AlterOption{&AddIndexDefinition{IndexDefinition: &IndexDefinition{Info: &IndexInfo{Name: yyDollar[5].identifierCI, Type: IndexTypeSpatial}, Options: yyDollar[6].indexOptionsUnion()}}}} setDDL(yylex, yyLOCAL) @@ -11201,7 +11241,7 @@ yydefault: case 151: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *AlterTable -//line sql.y:1278 +//line sql.y:1287 { yyLOCAL = &AlterTable{Table: yyDollar[8].tableName, AlterOptions: []AlterOption{&AddIndexDefinition{IndexDefinition: &IndexDefinition{Info: &IndexInfo{Name: yyDollar[5].identifierCI, Type: IndexTypeUnique}, Options: yyDollar[6].indexOptionsUnion()}}}} setDDL(yylex, yyLOCAL) @@ -11210,7 +11250,7 @@ yydefault: case 152: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *CreateDatabase -//line sql.y:1285 +//line sql.y:1294 { yyLOCAL = &CreateDatabase{Comments: Comments(yyDollar[4].strs).Parsed(), DBName: yyDollar[6].identifierCS, IfNotExists: yyDollar[5].booleanUnion()} setDDL(yylex, yyLOCAL) @@ -11219,7 +11259,7 @@ yydefault: case 153: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *AlterDatabase -//line sql.y:1292 +//line sql.y:1301 { yyLOCAL = &AlterDatabase{} setDDL(yylex, yyLOCAL) @@ -11228,7 +11268,7 @@ yydefault: case 156: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *TableSpec -//line sql.y:1303 +//line sql.y:1312 { yyLOCAL = yyDollar[2].tableSpecUnion() yyLOCAL.Options = yyDollar[4].tableOptionsUnion() @@ -11238,7 +11278,7 @@ yydefault: case 157: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []DatabaseOption -//line sql.y:1310 +//line sql.y:1319 { yyLOCAL = nil } @@ -11246,7 +11286,7 @@ yydefault: case 158: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []DatabaseOption -//line sql.y:1314 +//line sql.y:1323 { yyLOCAL = yyDollar[1].databaseOptionsUnion() } @@ -11254,7 +11294,7 @@ yydefault: case 159: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []DatabaseOption -//line sql.y:1320 +//line sql.y:1329 { yyLOCAL = []DatabaseOption{yyDollar[1].databaseOption} } @@ -11262,7 +11302,7 @@ yydefault: case 160: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []DatabaseOption -//line sql.y:1324 +//line sql.y:1333 { yyLOCAL = []DatabaseOption{yyDollar[1].databaseOption} } @@ -11270,28 +11310,28 @@ yydefault: case 161: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []DatabaseOption -//line sql.y:1328 +//line sql.y:1337 { yyLOCAL = []DatabaseOption{yyDollar[1].databaseOption} } yyVAL.union = yyLOCAL case 162: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1332 +//line sql.y:1341 { yySLICE := (*[]DatabaseOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[2].databaseOption) } case 163: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1336 +//line sql.y:1345 { yySLICE := (*[]DatabaseOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[2].databaseOption) } case 164: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1340 +//line sql.y:1349 { yySLICE := (*[]DatabaseOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[2].databaseOption) @@ -11299,7 +11339,7 @@ yydefault: case 165: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:1346 +//line sql.y:1355 { yyLOCAL = false } @@ -11307,51 +11347,51 @@ yydefault: case 166: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:1350 +//line sql.y:1359 { yyLOCAL = true } yyVAL.union = yyLOCAL case 167: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1356 +//line sql.y:1365 { yyVAL.databaseOption = DatabaseOption{Type: CharacterSetType, Value: string(yyDollar[4].str), IsDefault: yyDollar[1].booleanUnion()} } case 168: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1360 +//line sql.y:1369 { yyVAL.databaseOption = DatabaseOption{Type: CharacterSetType, Value: encodeSQLString(yyDollar[4].str), IsDefault: yyDollar[1].booleanUnion()} } case 169: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1366 +//line sql.y:1375 { yyVAL.databaseOption = DatabaseOption{Type: CollateType, Value: string(yyDollar[4].str), IsDefault: yyDollar[1].booleanUnion()} } case 170: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1370 +//line sql.y:1379 { yyVAL.databaseOption = DatabaseOption{Type: CollateType, Value: encodeSQLString(yyDollar[4].str), IsDefault: yyDollar[1].booleanUnion()} } case 171: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1376 +//line sql.y:1385 { yyVAL.databaseOption = DatabaseOption{Type: EncryptionType, Value: string(yyDollar[4].str), IsDefault: yyDollar[1].booleanUnion()} } case 172: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1380 +//line sql.y:1389 { yyVAL.databaseOption = DatabaseOption{Type: EncryptionType, Value: encodeSQLString(yyDollar[4].str), IsDefault: yyDollar[1].booleanUnion()} } case 173: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *OptLike -//line sql.y:1386 +//line sql.y:1395 { yyLOCAL = &OptLike{LikeTable: yyDollar[2].tableName} } @@ -11359,7 +11399,7 @@ yydefault: case 174: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *OptLike -//line sql.y:1390 +//line sql.y:1399 { yyLOCAL = &OptLike{LikeTable: yyDollar[3].tableName} } @@ -11367,14 +11407,14 @@ yydefault: case 175: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*ColumnDefinition -//line sql.y:1396 +//line sql.y:1405 { yyLOCAL = []*ColumnDefinition{yyDollar[1].columnDefinitionUnion()} } yyVAL.union = yyLOCAL case 176: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1400 +//line sql.y:1409 { yySLICE := (*[]*ColumnDefinition)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].columnDefinitionUnion()) @@ -11382,7 +11422,7 @@ yydefault: case 177: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *TableSpec -//line sql.y:1406 +//line sql.y:1415 { yyLOCAL = &TableSpec{} yyLOCAL.AddColumn(yyDollar[1].columnDefinitionUnion()) @@ -11391,7 +11431,7 @@ yydefault: case 178: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *TableSpec -//line sql.y:1411 +//line sql.y:1420 { yyLOCAL = &TableSpec{} yyLOCAL.AddConstraint(yyDollar[1].constraintDefinitionUnion()) @@ -11399,39 +11439,39 @@ yydefault: yyVAL.union = yyLOCAL case 179: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1416 +//line sql.y:1425 { yyVAL.tableSpecUnion().AddColumn(yyDollar[3].columnDefinitionUnion()) } case 180: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1420 +//line sql.y:1429 { yyVAL.tableSpecUnion().AddColumn(yyDollar[3].columnDefinitionUnion()) yyVAL.tableSpecUnion().AddConstraint(yyDollar[4].constraintDefinitionUnion()) } case 181: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1425 +//line sql.y:1434 { yyVAL.tableSpecUnion().AddIndex(yyDollar[3].indexDefinitionUnion()) } case 182: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1429 +//line sql.y:1438 { yyVAL.tableSpecUnion().AddConstraint(yyDollar[3].constraintDefinitionUnion()) } case 183: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1433 +//line sql.y:1442 { yyVAL.tableSpecUnion().AddConstraint(yyDollar[3].constraintDefinitionUnion()) } case 184: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *ColumnDefinition -//line sql.y:1444 +//line sql.y:1453 { yyDollar[2].columnType.Options = yyDollar[4].columnTypeOptionsUnion() if yyDollar[2].columnType.Options.Collate == "" { @@ -11444,7 +11484,7 @@ yydefault: case 185: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL *ColumnDefinition -//line sql.y:1453 +//line sql.y:1462 { yyDollar[2].columnType.Options = yyDollar[9].columnTypeOptionsUnion() yyDollar[2].columnType.Options.As = yyDollar[7].exprUnion() @@ -11455,20 +11495,20 @@ yydefault: yyVAL.union = yyLOCAL case 186: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1462 +//line sql.y:1471 { yyVAL.str = "" } case 187: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1466 +//line sql.y:1475 { yyVAL.str = "" } case 188: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1475 +//line sql.y:1484 { yyLOCAL = &ColumnTypeOptions{Null: nil, Default: nil, OnUpdate: nil, Autoincrement: false, KeyOpt: ColKeyNone, Comment: nil, As: nil, Invisible: nil, Format: UnspecifiedFormat, EngineAttribute: nil, SecondaryEngineAttribute: nil} } @@ -11476,7 +11516,7 @@ yydefault: case 189: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1479 +//line sql.y:1488 { yyDollar[1].columnTypeOptionsUnion().Null = ptr.Of(true) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11485,7 +11525,7 @@ yydefault: case 190: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1484 +//line sql.y:1493 { yyDollar[1].columnTypeOptionsUnion().Null = ptr.Of(false) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11494,7 +11534,7 @@ yydefault: case 191: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1489 +//line sql.y:1498 { yyDollar[1].columnTypeOptionsUnion().Default = yyDollar[4].exprUnion() yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11503,7 +11543,7 @@ yydefault: case 192: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1494 +//line sql.y:1503 { yyDollar[1].columnTypeOptionsUnion().Default = yyDollar[3].exprUnion() yyDollar[1].columnTypeOptionsUnion().DefaultLiteral = true @@ -11513,7 +11553,7 @@ yydefault: case 193: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1500 +//line sql.y:1509 { yyDollar[1].columnTypeOptionsUnion().OnUpdate = yyDollar[4].exprUnion() yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11522,7 +11562,7 @@ yydefault: case 194: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1505 +//line sql.y:1514 { yyDollar[1].columnTypeOptionsUnion().Autoincrement = true yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11531,7 +11571,7 @@ yydefault: case 195: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1510 +//line sql.y:1519 { yyDollar[1].columnTypeOptionsUnion().Comment = NewStrLiteral(yyDollar[3].str) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11540,7 +11580,7 @@ yydefault: case 196: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1515 +//line sql.y:1524 { yyDollar[1].columnTypeOptionsUnion().KeyOpt = yyDollar[2].colKeyOptUnion() yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11548,14 +11588,14 @@ yydefault: yyVAL.union = yyLOCAL case 197: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1520 +//line sql.y:1529 { yyDollar[1].columnTypeOptionsUnion().Collate = encodeSQLString(yyDollar[3].str) } case 198: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1524 +//line sql.y:1533 { yyDollar[1].columnTypeOptionsUnion().Collate = string(yyDollar[3].identifierCI.String()) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11563,14 +11603,14 @@ yydefault: yyVAL.union = yyLOCAL case 199: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1529 +//line sql.y:1538 { yyDollar[1].columnTypeOptionsUnion().Format = yyDollar[3].columnFormatUnion() } case 200: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1533 +//line sql.y:1542 { yyDollar[1].columnTypeOptionsUnion().SRID = NewIntLiteral(yyDollar[3].str) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11579,7 +11619,7 @@ yydefault: case 201: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1538 +//line sql.y:1547 { yyDollar[1].columnTypeOptionsUnion().Invisible = ptr.Of(false) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11588,7 +11628,7 @@ yydefault: case 202: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1543 +//line sql.y:1552 { yyDollar[1].columnTypeOptionsUnion().Invisible = ptr.Of(true) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11596,20 +11636,20 @@ yydefault: yyVAL.union = yyLOCAL case 203: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1548 +//line sql.y:1557 { yyDollar[1].columnTypeOptionsUnion().EngineAttribute = NewStrLiteral(yyDollar[4].str) } case 204: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1552 +//line sql.y:1561 { yyDollar[1].columnTypeOptionsUnion().SecondaryEngineAttribute = NewStrLiteral(yyDollar[4].str) } case 205: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColumnFormat -//line sql.y:1558 +//line sql.y:1567 { yyLOCAL = FixedFormat } @@ -11617,7 +11657,7 @@ yydefault: case 206: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColumnFormat -//line sql.y:1562 +//line sql.y:1571 { yyLOCAL = DynamicFormat } @@ -11625,7 +11665,7 @@ yydefault: case 207: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColumnFormat -//line sql.y:1566 +//line sql.y:1575 { yyLOCAL = DefaultFormat } @@ -11633,7 +11673,7 @@ yydefault: case 208: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColumnStorage -//line sql.y:1572 +//line sql.y:1581 { yyLOCAL = VirtualStorage } @@ -11641,7 +11681,7 @@ yydefault: case 209: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColumnStorage -//line sql.y:1576 +//line sql.y:1585 { yyLOCAL = StoredStorage } @@ -11649,7 +11689,7 @@ yydefault: case 210: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1581 +//line sql.y:1590 { yyLOCAL = &ColumnTypeOptions{} } @@ -11657,7 +11697,7 @@ yydefault: case 211: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1585 +//line sql.y:1594 { yyDollar[1].columnTypeOptionsUnion().Storage = yyDollar[2].columnStorageUnion() yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11666,7 +11706,7 @@ yydefault: case 212: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1590 +//line sql.y:1599 { yyDollar[1].columnTypeOptionsUnion().Null = ptr.Of(true) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11675,7 +11715,7 @@ yydefault: case 213: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1595 +//line sql.y:1604 { yyDollar[1].columnTypeOptionsUnion().Null = ptr.Of(false) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11684,7 +11724,7 @@ yydefault: case 214: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1600 +//line sql.y:1609 { yyDollar[1].columnTypeOptionsUnion().Comment = NewStrLiteral(yyDollar[3].str) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11693,7 +11733,7 @@ yydefault: case 215: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1605 +//line sql.y:1614 { yyDollar[1].columnTypeOptionsUnion().KeyOpt = yyDollar[2].colKeyOptUnion() yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11702,7 +11742,7 @@ yydefault: case 216: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1610 +//line sql.y:1619 { yyDollar[1].columnTypeOptionsUnion().Invisible = ptr.Of(false) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11711,7 +11751,7 @@ yydefault: case 217: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColumnTypeOptions -//line sql.y:1615 +//line sql.y:1624 { yyDollar[1].columnTypeOptionsUnion().Invisible = ptr.Of(true) yyLOCAL = yyDollar[1].columnTypeOptionsUnion() @@ -11720,7 +11760,7 @@ yydefault: case 218: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1622 +//line sql.y:1631 { yyLOCAL = yyDollar[1].exprUnion() } @@ -11728,7 +11768,7 @@ yydefault: case 220: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1629 +//line sql.y:1638 { yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("current_timestamp"), Fsp: yyDollar[2].integerUnion()} } @@ -11736,7 +11776,7 @@ yydefault: case 221: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1633 +//line sql.y:1642 { yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("localtime"), Fsp: yyDollar[2].integerUnion()} } @@ -11744,7 +11784,7 @@ yydefault: case 222: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1637 +//line sql.y:1646 { yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("localtimestamp"), Fsp: yyDollar[2].integerUnion()} } @@ -11752,7 +11792,7 @@ yydefault: case 223: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1641 +//line sql.y:1650 { yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("utc_timestamp"), Fsp: yyDollar[2].integerUnion()} } @@ -11760,7 +11800,7 @@ yydefault: case 224: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1645 +//line sql.y:1654 { yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("now"), Fsp: yyDollar[2].integerUnion()} } @@ -11768,7 +11808,7 @@ yydefault: case 225: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1649 +//line sql.y:1658 { yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("sysdate"), Fsp: yyDollar[2].integerUnion()} } @@ -11776,7 +11816,7 @@ yydefault: case 228: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1659 +//line sql.y:1668 { yyLOCAL = &NullVal{} } @@ -11784,7 +11824,7 @@ yydefault: case 230: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1666 +//line sql.y:1675 { yyLOCAL = yyDollar[2].exprUnion() } @@ -11792,7 +11832,7 @@ yydefault: case 231: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1670 +//line sql.y:1679 { yyLOCAL = &UnaryExpr{Operator: UMinusOp, Expr: yyDollar[2].exprUnion()} } @@ -11800,7 +11840,7 @@ yydefault: case 232: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1676 +//line sql.y:1685 { yyLOCAL = yyDollar[1].exprUnion() } @@ -11808,7 +11848,7 @@ yydefault: case 233: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1680 +//line sql.y:1689 { yyLOCAL = yyDollar[1].exprUnion() } @@ -11816,7 +11856,7 @@ yydefault: case 234: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1684 +//line sql.y:1693 { yyLOCAL = yyDollar[1].boolValUnion() } @@ -11824,7 +11864,7 @@ yydefault: case 235: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1688 +//line sql.y:1697 { yyLOCAL = NewHexLiteral(yyDollar[1].str) } @@ -11832,7 +11872,7 @@ yydefault: case 236: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1692 +//line sql.y:1701 { yyLOCAL = NewHexNumLiteral(yyDollar[1].str) } @@ -11840,7 +11880,7 @@ yydefault: case 237: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1696 +//line sql.y:1705 { yyLOCAL = NewBitLiteral(yyDollar[1].str) } @@ -11848,7 +11888,7 @@ yydefault: case 238: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1700 +//line sql.y:1709 { yyLOCAL = NewBitLiteral("0b" + yyDollar[1].str) } @@ -11856,7 +11896,7 @@ yydefault: case 239: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1704 +//line sql.y:1713 { yyLOCAL = parseBindVariable(yylex, yyDollar[1].str[1:]) } @@ -11864,7 +11904,7 @@ yydefault: case 240: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1708 +//line sql.y:1717 { yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: NewBitLiteral("0b" + yyDollar[2].str)} } @@ -11872,7 +11912,7 @@ yydefault: case 241: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1712 +//line sql.y:1721 { yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: NewHexNumLiteral(yyDollar[2].str)} } @@ -11880,7 +11920,7 @@ yydefault: case 242: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1716 +//line sql.y:1725 { yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: NewBitLiteral(yyDollar[2].str)} } @@ -11888,7 +11928,7 @@ yydefault: case 243: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1720 +//line sql.y:1729 { yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: NewHexLiteral(yyDollar[2].str)} } @@ -11896,7 +11936,7 @@ yydefault: case 244: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1724 +//line sql.y:1733 { yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: yyDollar[2].exprUnion()} } @@ -11904,7 +11944,7 @@ yydefault: case 245: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1728 +//line sql.y:1737 { arg := parseBindVariable(yylex, yyDollar[2].str[1:]) yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: arg} @@ -11913,7 +11953,7 @@ yydefault: case 246: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1733 +//line sql.y:1742 { yyLOCAL = NewDateLiteral(yyDollar[2].str) } @@ -11921,7 +11961,7 @@ yydefault: case 247: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1737 +//line sql.y:1746 { yyLOCAL = NewTimeLiteral(yyDollar[2].str) } @@ -11929,267 +11969,267 @@ yydefault: case 248: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1741 +//line sql.y:1750 { yyLOCAL = NewTimestampLiteral(yyDollar[2].str) } yyVAL.union = yyLOCAL case 249: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1747 +//line sql.y:1756 { yyVAL.str = Armscii8Str } case 250: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1751 +//line sql.y:1760 { yyVAL.str = ASCIIStr } case 251: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1755 +//line sql.y:1764 { yyVAL.str = Big5Str } case 252: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1759 +//line sql.y:1768 { yyVAL.str = UBinaryStr } case 253: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1763 +//line sql.y:1772 { yyVAL.str = Cp1250Str } case 254: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1767 +//line sql.y:1776 { yyVAL.str = Cp1251Str } case 255: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1771 +//line sql.y:1780 { yyVAL.str = Cp1256Str } case 256: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1775 +//line sql.y:1784 { yyVAL.str = Cp1257Str } case 257: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1779 +//line sql.y:1788 { yyVAL.str = Cp850Str } case 258: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1783 +//line sql.y:1792 { yyVAL.str = Cp852Str } case 259: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1787 +//line sql.y:1796 { yyVAL.str = Cp866Str } case 260: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1791 +//line sql.y:1800 { yyVAL.str = Cp932Str } case 261: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1795 +//line sql.y:1804 { yyVAL.str = Dec8Str } case 262: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1799 +//line sql.y:1808 { yyVAL.str = EucjpmsStr } case 263: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1803 +//line sql.y:1812 { yyVAL.str = EuckrStr } case 264: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1807 +//line sql.y:1816 { yyVAL.str = Gb18030Str } case 265: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1811 +//line sql.y:1820 { yyVAL.str = Gb2312Str } case 266: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1815 +//line sql.y:1824 { yyVAL.str = GbkStr } case 267: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1819 +//line sql.y:1828 { yyVAL.str = Geostd8Str } case 268: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1823 +//line sql.y:1832 { yyVAL.str = GreekStr } case 269: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1827 +//line sql.y:1836 { yyVAL.str = HebrewStr } case 270: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1831 +//line sql.y:1840 { yyVAL.str = Hp8Str } case 271: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1835 +//line sql.y:1844 { yyVAL.str = Keybcs2Str } case 272: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1839 +//line sql.y:1848 { yyVAL.str = Koi8rStr } case 273: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1843 +//line sql.y:1852 { yyVAL.str = Koi8uStr } case 274: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1847 +//line sql.y:1856 { yyVAL.str = Latin1Str } case 275: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1851 +//line sql.y:1860 { yyVAL.str = Latin2Str } case 276: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1855 +//line sql.y:1864 { yyVAL.str = Latin5Str } case 277: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1859 +//line sql.y:1868 { yyVAL.str = Latin7Str } case 278: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1863 +//line sql.y:1872 { yyVAL.str = MacceStr } case 279: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1867 +//line sql.y:1876 { yyVAL.str = MacromanStr } case 280: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1871 +//line sql.y:1880 { yyVAL.str = SjisStr } case 281: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1875 +//line sql.y:1884 { yyVAL.str = Swe7Str } case 282: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1879 +//line sql.y:1888 { yyVAL.str = Tis620Str } case 283: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1883 +//line sql.y:1892 { yyVAL.str = Ucs2Str } case 284: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1887 +//line sql.y:1896 { yyVAL.str = UjisStr } case 285: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1891 +//line sql.y:1900 { yyVAL.str = Utf16Str } case 286: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1895 +//line sql.y:1904 { yyVAL.str = Utf16leStr } case 287: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1899 +//line sql.y:1908 { yyVAL.str = Utf32Str } case 288: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1903 +//line sql.y:1912 { yyVAL.str = Utf8mb3Str } case 289: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1907 +//line sql.y:1916 { yyVAL.str = Utf8mb4Str } case 290: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1911 +//line sql.y:1920 { yyVAL.str = Utf8mb3Str } case 293: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1921 +//line sql.y:1930 { yyLOCAL = NewIntLiteral(yyDollar[1].str) } @@ -12197,7 +12237,7 @@ yydefault: case 294: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1925 +//line sql.y:1934 { yyLOCAL = NewFloatLiteral(yyDollar[1].str) } @@ -12205,7 +12245,7 @@ yydefault: case 295: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1929 +//line sql.y:1938 { yyLOCAL = NewDecimalLiteral(yyDollar[1].str) } @@ -12213,7 +12253,7 @@ yydefault: case 296: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1935 +//line sql.y:1944 { yyLOCAL = yyDollar[1].exprUnion() } @@ -12221,7 +12261,7 @@ yydefault: case 297: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1939 +//line sql.y:1948 { yyLOCAL = AppendString(yyDollar[1].exprUnion(), yyDollar[2].str) } @@ -12229,7 +12269,7 @@ yydefault: case 298: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1945 +//line sql.y:1954 { yyLOCAL = NewStrLiteral(yyDollar[1].str) } @@ -12237,7 +12277,7 @@ yydefault: case 299: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1949 +//line sql.y:1958 { yyLOCAL = &UnaryExpr{Operator: NStringOp, Expr: NewStrLiteral(yyDollar[1].str)} } @@ -12245,7 +12285,7 @@ yydefault: case 300: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:1953 +//line sql.y:1962 { yyLOCAL = &IntroducerExpr{CharacterSet: yyDollar[1].str, Expr: NewStrLiteral(yyDollar[2].str)} } @@ -12253,7 +12293,7 @@ yydefault: case 301: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1959 +//line sql.y:1968 { yyLOCAL = yyDollar[1].exprUnion() } @@ -12261,7 +12301,7 @@ yydefault: case 302: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:1963 +//line sql.y:1972 { yyLOCAL = parseBindVariable(yylex, yyDollar[1].str[1:]) } @@ -12269,7 +12309,7 @@ yydefault: case 303: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL ColumnKeyOption -//line sql.y:1969 +//line sql.y:1978 { yyLOCAL = ColKeyPrimary } @@ -12277,7 +12317,7 @@ yydefault: case 304: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColumnKeyOption -//line sql.y:1973 +//line sql.y:1982 { yyLOCAL = ColKeyUnique } @@ -12285,7 +12325,7 @@ yydefault: case 305: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL ColumnKeyOption -//line sql.y:1977 +//line sql.y:1986 { yyLOCAL = ColKeyUniqueKey } @@ -12293,14 +12333,14 @@ yydefault: case 306: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColumnKeyOption -//line sql.y:1981 +//line sql.y:1990 { yyLOCAL = ColKey } yyVAL.union = yyLOCAL case 307: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1987 +//line sql.y:1996 { yyVAL.columnType = yyDollar[1].columnType yyVAL.columnType.Unsigned = yyDollar[2].booleanUnion() @@ -12308,74 +12348,74 @@ yydefault: } case 311: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1998 +//line sql.y:2007 { yyVAL.columnType = yyDollar[1].columnType yyVAL.columnType.Length = yyDollar[2].intPtrUnion() } case 312: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2003 +//line sql.y:2012 { yyVAL.columnType = yyDollar[1].columnType } case 313: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2009 +//line sql.y:2018 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 314: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2013 +//line sql.y:2022 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 315: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2017 +//line sql.y:2026 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 316: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2021 +//line sql.y:2030 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 317: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2025 +//line sql.y:2034 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 318: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2029 +//line sql.y:2038 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 319: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2033 +//line sql.y:2042 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 320: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2037 +//line sql.y:2046 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 321: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2041 +//line sql.y:2050 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 322: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2047 +//line sql.y:2056 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -12383,7 +12423,7 @@ yydefault: } case 323: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2053 +//line sql.y:2062 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -12391,7 +12431,7 @@ yydefault: } case 324: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2059 +//line sql.y:2068 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -12399,7 +12439,7 @@ yydefault: } case 325: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2065 +//line sql.y:2074 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -12407,7 +12447,7 @@ yydefault: } case 326: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2071 +//line sql.y:2080 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -12415,7 +12455,7 @@ yydefault: } case 327: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2077 +//line sql.y:2086 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -12423,7 +12463,7 @@ yydefault: } case 328: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2083 +//line sql.y:2092 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -12431,43 +12471,43 @@ yydefault: } case 329: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2091 +//line sql.y:2100 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 330: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2095 +//line sql.y:2104 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } case 331: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2099 +//line sql.y:2108 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } case 332: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2103 +//line sql.y:2112 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } case 333: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2107 +//line sql.y:2116 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } case 334: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2113 +//line sql.y:2122 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion(), Charset: yyDollar[3].columnCharset} } case 335: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2117 +//line sql.y:2126 { // CHAR BYTE is an alias for binary. See also: // https://dev.mysql.com/doc/refman/8.0/en/string-type-syntax.html @@ -12475,1705 +12515,1711 @@ yydefault: } case 336: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2123 +//line sql.y:2132 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion(), Charset: yyDollar[3].columnCharset} } case 337: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2127 +//line sql.y:2136 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } case 338: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2131 +//line sql.y:2140 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } case 339: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2135 +//line sql.y:2144 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Charset: yyDollar[2].columnCharset} } case 340: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2139 +//line sql.y:2148 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Charset: yyDollar[2].columnCharset} } case 341: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2143 +//line sql.y:2152 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Charset: yyDollar[2].columnCharset} } case 342: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2147 +//line sql.y:2156 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Charset: yyDollar[2].columnCharset} } case 343: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2151 +//line sql.y:2160 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 344: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2155 +//line sql.y:2164 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 345: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2159 +//line sql.y:2168 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 346: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2163 +//line sql.y:2172 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 347: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2167 +//line sql.y:2176 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 348: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2171 +//line sql.y:2180 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), EnumValues: yyDollar[3].strs, Charset: yyDollar[5].columnCharset} } case 349: - yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2176 + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:2184 { - yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), EnumValues: yyDollar[3].strs, Charset: yyDollar[5].columnCharset} + yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } case 350: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2182 + yyDollar = yyS[yypt-5 : yypt+1] +//line sql.y:2189 { - 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 351: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2186 +//line sql.y:2195 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 352: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2190 +//line sql.y:2199 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 353: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2194 +//line sql.y:2203 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 354: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2198 +//line sql.y:2207 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 355: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2202 +//line sql.y:2211 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 356: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2206 +//line sql.y:2215 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 357: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2210 +//line sql.y:2219 { yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} } case 358: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2216 +//line sql.y:2223 + { + yyVAL.columnType = &ColumnType{Type: string(yyDollar[1].str)} + } + case 359: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:2229 { yyVAL.strs = make([]string, 0, 4) yyVAL.strs = append(yyVAL.strs, encodeSQLString(yyDollar[1].str)) } - case 359: + case 360: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2221 +//line sql.y:2234 { yyVAL.strs = append(yyDollar[1].strs, encodeSQLString(yyDollar[3].str)) } - case 360: + case 361: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *int -//line sql.y:2226 +//line sql.y:2239 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 361: + case 362: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *int -//line sql.y:2230 +//line sql.y:2243 { yyLOCAL = ptr.Of(convertStringToInt(yyDollar[2].str)) } yyVAL.union = yyLOCAL - case 362: + case 363: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2235 +//line sql.y:2248 { yyVAL.LengthScaleOption = LengthScaleOption{} } - case 363: + case 364: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2239 +//line sql.y:2252 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: ptr.Of(convertStringToInt(yyDollar[2].str)), Scale: ptr.Of(convertStringToInt(yyDollar[4].str)), } } - case 364: + case 365: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2248 +//line sql.y:2261 { yyVAL.LengthScaleOption = yyDollar[1].LengthScaleOption } - case 365: + case 366: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2252 +//line sql.y:2265 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: ptr.Of(convertStringToInt(yyDollar[2].str)), } } - case 366: + case 367: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2259 +//line sql.y:2272 { yyVAL.LengthScaleOption = LengthScaleOption{} } - case 367: + case 368: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2263 +//line sql.y:2276 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: ptr.Of(convertStringToInt(yyDollar[2].str)), } } - case 368: + case 369: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2269 +//line sql.y:2282 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: ptr.Of(convertStringToInt(yyDollar[2].str)), Scale: ptr.Of(convertStringToInt(yyDollar[4].str)), } } - case 369: + case 370: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:2277 +//line sql.y:2290 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 370: + case 371: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:2281 +//line sql.y:2294 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 371: + case 372: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:2285 +//line sql.y:2298 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 372: + case 373: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:2290 +//line sql.y:2303 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 373: + case 374: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:2294 +//line sql.y:2307 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 374: + case 375: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2299 +//line sql.y:2312 { yyVAL.columnCharset = ColumnCharset{} } - case 375: + case 376: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2303 +//line sql.y:2316 { yyVAL.columnCharset = ColumnCharset{Name: string(yyDollar[2].identifierCI.String()), Binary: yyDollar[3].booleanUnion()} } - case 376: + case 377: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2307 +//line sql.y:2320 { yyVAL.columnCharset = ColumnCharset{Name: encodeSQLString(yyDollar[2].str), Binary: yyDollar[3].booleanUnion()} } - case 377: + case 378: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2311 +//line sql.y:2324 { yyVAL.columnCharset = ColumnCharset{Name: string(yyDollar[2].str)} } - case 378: + case 379: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2315 +//line sql.y:2328 { // ASCII: Shorthand for CHARACTER SET latin1. yyVAL.columnCharset = ColumnCharset{Name: "latin1", Binary: yyDollar[2].booleanUnion()} } - case 379: + case 380: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2320 +//line sql.y:2333 { // UNICODE: Shorthand for CHARACTER SET ucs2. yyVAL.columnCharset = ColumnCharset{Name: "ucs2", Binary: yyDollar[2].booleanUnion()} } - case 380: + case 381: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2325 +//line sql.y:2338 { // BINARY: Shorthand for default CHARACTER SET but with binary collation yyVAL.columnCharset = ColumnCharset{Name: "", Binary: true} } - case 381: + case 382: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2330 +//line sql.y:2343 { // BINARY ASCII: Shorthand for CHARACTER SET latin1 with binary collation yyVAL.columnCharset = ColumnCharset{Name: "latin1", Binary: true} } - case 382: + case 383: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2335 +//line sql.y:2348 { // BINARY UNICODE: Shorthand for CHARACTER SET ucs2 with binary collation yyVAL.columnCharset = ColumnCharset{Name: "ucs2", Binary: true} } - case 383: + case 384: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:2341 +//line sql.y:2354 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 384: + case 385: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:2345 +//line sql.y:2358 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 385: + case 386: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2350 +//line sql.y:2363 { yyVAL.str = "" } - case 386: + case 387: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2354 +//line sql.y:2367 { yyVAL.str = string(yyDollar[2].identifierCI.String()) } - case 387: + case 388: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2358 +//line sql.y:2371 { yyVAL.str = encodeSQLString(yyDollar[2].str) } - case 388: + case 389: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *IndexDefinition -//line sql.y:2364 +//line sql.y:2377 { yyLOCAL = &IndexDefinition{Info: yyDollar[1].indexInfoUnion(), Columns: yyDollar[3].indexColumnsUnion(), Options: yyDollar[5].indexOptionsUnion()} } yyVAL.union = yyLOCAL - case 389: + case 390: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*IndexOption -//line sql.y:2369 +//line sql.y:2382 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 390: + case 391: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*IndexOption -//line sql.y:2373 +//line sql.y:2386 { yyLOCAL = yyDollar[1].indexOptionsUnion() } yyVAL.union = yyLOCAL - case 391: + case 392: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*IndexOption -//line sql.y:2379 +//line sql.y:2392 { yyLOCAL = []*IndexOption{yyDollar[1].indexOptionUnion()} } yyVAL.union = yyLOCAL - case 392: + case 393: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2383 +//line sql.y:2396 { yySLICE := (*[]*IndexOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[2].indexOptionUnion()) } - case 393: + case 394: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *IndexOption -//line sql.y:2389 +//line sql.y:2402 { yyLOCAL = yyDollar[1].indexOptionUnion() } yyVAL.union = yyLOCAL - case 394: + case 395: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *IndexOption -//line sql.y:2393 +//line sql.y:2406 { // should not be string yyLOCAL = &IndexOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 395: + case 396: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *IndexOption -//line sql.y:2398 +//line sql.y:2411 { yyLOCAL = &IndexOption{Name: string(yyDollar[1].str), Value: NewStrLiteral(yyDollar[2].str)} } yyVAL.union = yyLOCAL - case 396: + case 397: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *IndexOption -//line sql.y:2402 +//line sql.y:2415 { yyLOCAL = &IndexOption{Name: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 397: + case 398: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *IndexOption -//line sql.y:2406 +//line sql.y:2419 { yyLOCAL = &IndexOption{Name: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 398: + case 399: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *IndexOption -//line sql.y:2410 +//line sql.y:2423 { yyLOCAL = &IndexOption{Name: string(yyDollar[1].str) + " " + string(yyDollar[2].str), String: yyDollar[3].identifierCI.String()} } yyVAL.union = yyLOCAL - case 399: + case 400: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *IndexOption -//line sql.y:2414 +//line sql.y:2427 { yyLOCAL = &IndexOption{Name: string(yyDollar[1].str), Value: NewStrLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 400: + case 401: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *IndexOption -//line sql.y:2418 +//line sql.y:2431 { yyLOCAL = &IndexOption{Name: string(yyDollar[1].str), Value: NewStrLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 401: + case 402: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2424 +//line sql.y:2437 { yyVAL.str = "" } - case 402: + case 403: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2428 +//line sql.y:2441 { yyVAL.str = string(yyDollar[1].str) } - case 403: + case 404: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *IndexInfo -//line sql.y:2434 +//line sql.y:2447 { yyLOCAL = &IndexInfo{Type: IndexTypePrimary, ConstraintName: NewIdentifierCI(yyDollar[1].str), Name: NewIdentifierCI("PRIMARY")} } yyVAL.union = yyLOCAL - case 404: + case 405: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *IndexInfo -//line sql.y:2438 +//line sql.y:2451 { yyLOCAL = &IndexInfo{Type: IndexTypeSpatial, Name: NewIdentifierCI(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 405: + case 406: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *IndexInfo -//line sql.y:2442 +//line sql.y:2455 { yyLOCAL = &IndexInfo{Type: IndexTypeFullText, Name: NewIdentifierCI(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 406: + case 407: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *IndexInfo -//line sql.y:2446 +//line sql.y:2459 { yyLOCAL = &IndexInfo{Type: IndexTypeUnique, ConstraintName: NewIdentifierCI(yyDollar[1].str), Name: NewIdentifierCI(yyDollar[4].str)} } yyVAL.union = yyLOCAL - case 407: + case 408: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *IndexInfo -//line sql.y:2450 +//line sql.y:2463 { yyLOCAL = &IndexInfo{Type: IndexTypeDefault, Name: NewIdentifierCI(yyDollar[2].str)} } yyVAL.union = yyLOCAL - case 408: + case 409: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2455 +//line sql.y:2468 { yyVAL.str = "" } - case 409: + case 410: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2459 +//line sql.y:2472 { yyVAL.str = yyDollar[2].str } - case 410: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2465 - { - yyVAL.str = string(yyDollar[1].str) - } case 411: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2469 +//line sql.y:2478 { yyVAL.str = string(yyDollar[1].str) } case 412: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2473 +//line sql.y:2482 { yyVAL.str = string(yyDollar[1].str) } case 413: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2479 +//line sql.y:2486 { yyVAL.str = string(yyDollar[1].str) } case 414: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2483 +//line sql.y:2492 { yyVAL.str = string(yyDollar[1].str) } case 415: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:2496 + { + yyVAL.str = string(yyDollar[1].str) + } + case 416: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2488 +//line sql.y:2501 { yyVAL.str = "" } - case 416: + case 417: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2492 +//line sql.y:2505 { yyVAL.str = yyDollar[1].str } - case 417: + case 418: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2498 +//line sql.y:2511 { yyVAL.str = string(yyDollar[1].str) } - case 418: + case 419: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2502 +//line sql.y:2515 { yyVAL.str = string(yyDollar[1].str) } - case 419: + case 420: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2507 +//line sql.y:2520 { yyVAL.str = "" } - case 420: + case 421: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2511 +//line sql.y:2524 { yyVAL.str = string(yyDollar[1].identifierCI.String()) } - case 421: + case 422: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*IndexColumn -//line sql.y:2517 +//line sql.y:2530 { yyLOCAL = []*IndexColumn{yyDollar[1].indexColumnUnion()} } yyVAL.union = yyLOCAL - case 422: + case 423: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2521 +//line sql.y:2534 { yySLICE := (*[]*IndexColumn)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].indexColumnUnion()) } - case 423: + case 424: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *IndexColumn -//line sql.y:2527 +//line sql.y:2540 { yyLOCAL = &IndexColumn{Column: yyDollar[1].identifierCI, Length: yyDollar[2].intPtrUnion(), Direction: yyDollar[3].orderDirectionUnion()} } yyVAL.union = yyLOCAL - case 424: + case 425: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *IndexColumn -//line sql.y:2531 +//line sql.y:2544 { yyLOCAL = &IndexColumn{Expression: yyDollar[2].exprUnion(), Direction: yyDollar[4].orderDirectionUnion()} } yyVAL.union = yyLOCAL - case 425: + case 426: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ConstraintDefinition -//line sql.y:2537 +//line sql.y:2550 { yyLOCAL = &ConstraintDefinition{Name: yyDollar[2].identifierCI, Details: yyDollar[3].constraintInfoUnion()} } yyVAL.union = yyLOCAL - case 426: + case 427: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ConstraintDefinition -//line sql.y:2541 +//line sql.y:2554 { yyLOCAL = &ConstraintDefinition{Details: yyDollar[1].constraintInfoUnion()} } yyVAL.union = yyLOCAL - case 427: + case 428: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ConstraintDefinition -//line sql.y:2547 +//line sql.y:2560 { yyLOCAL = &ConstraintDefinition{Name: yyDollar[2].identifierCI, Details: yyDollar[3].constraintInfoUnion()} } yyVAL.union = yyLOCAL - case 428: + case 429: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ConstraintDefinition -//line sql.y:2551 +//line sql.y:2564 { yyLOCAL = &ConstraintDefinition{Details: yyDollar[1].constraintInfoUnion()} } yyVAL.union = yyLOCAL - case 429: + case 430: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL ConstraintInfo -//line sql.y:2557 +//line sql.y:2570 { yyLOCAL = &ForeignKeyDefinition{IndexName: NewIdentifierCI(yyDollar[3].str), Source: yyDollar[5].columnsUnion(), ReferenceDefinition: yyDollar[7].referenceDefinitionUnion()} } yyVAL.union = yyLOCAL - case 430: + case 431: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *ReferenceDefinition -//line sql.y:2563 +//line sql.y:2576 { yyLOCAL = &ReferenceDefinition{ReferencedTable: yyDollar[2].tableName, ReferencedColumns: yyDollar[4].columnsUnion(), Match: yyDollar[6].matchActionUnion()} } yyVAL.union = yyLOCAL - case 431: + case 432: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *ReferenceDefinition -//line sql.y:2567 +//line sql.y:2580 { yyLOCAL = &ReferenceDefinition{ReferencedTable: yyDollar[2].tableName, ReferencedColumns: yyDollar[4].columnsUnion(), Match: yyDollar[6].matchActionUnion(), OnDelete: yyDollar[7].referenceActionUnion()} } yyVAL.union = yyLOCAL - case 432: + case 433: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *ReferenceDefinition -//line sql.y:2571 +//line sql.y:2584 { yyLOCAL = &ReferenceDefinition{ReferencedTable: yyDollar[2].tableName, ReferencedColumns: yyDollar[4].columnsUnion(), Match: yyDollar[6].matchActionUnion(), OnUpdate: yyDollar[7].referenceActionUnion()} } yyVAL.union = yyLOCAL - case 433: + case 434: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *ReferenceDefinition -//line sql.y:2575 +//line sql.y:2588 { 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 434: + case 435: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *ReferenceDefinition -//line sql.y:2579 +//line sql.y:2592 { 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 435: + case 436: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ReferenceDefinition -//line sql.y:2584 +//line sql.y:2597 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 436: + case 437: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ReferenceDefinition -//line sql.y:2588 +//line sql.y:2601 { yyLOCAL = yyDollar[1].referenceDefinitionUnion() } yyVAL.union = yyLOCAL - case 437: + case 438: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL ConstraintInfo -//line sql.y:2594 +//line sql.y:2607 { yyLOCAL = &CheckConstraintDefinition{Expr: yyDollar[3].exprUnion(), Enforced: yyDollar[5].booleanUnion()} } yyVAL.union = yyLOCAL - case 438: + case 439: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL MatchAction -//line sql.y:2600 +//line sql.y:2613 { yyLOCAL = yyDollar[2].matchActionUnion() } yyVAL.union = yyLOCAL - case 439: + case 440: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL MatchAction -//line sql.y:2606 +//line sql.y:2619 { yyLOCAL = Full } yyVAL.union = yyLOCAL - case 440: + case 441: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL MatchAction -//line sql.y:2610 +//line sql.y:2623 { yyLOCAL = Partial } yyVAL.union = yyLOCAL - case 441: + case 442: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL MatchAction -//line sql.y:2614 +//line sql.y:2627 { yyLOCAL = Simple } yyVAL.union = yyLOCAL - case 442: + case 443: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL MatchAction -//line sql.y:2619 +//line sql.y:2632 { yyLOCAL = DefaultMatch } yyVAL.union = yyLOCAL - case 443: + case 444: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL MatchAction -//line sql.y:2623 +//line sql.y:2636 { yyLOCAL = yyDollar[1].matchActionUnion() } yyVAL.union = yyLOCAL - case 444: + case 445: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL ReferenceAction -//line sql.y:2629 +//line sql.y:2642 { yyLOCAL = yyDollar[3].referenceActionUnion() } yyVAL.union = yyLOCAL - case 445: + case 446: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL ReferenceAction -//line sql.y:2635 +//line sql.y:2648 { yyLOCAL = yyDollar[3].referenceActionUnion() } yyVAL.union = yyLOCAL - case 446: + case 447: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ReferenceAction -//line sql.y:2641 +//line sql.y:2654 { yyLOCAL = Restrict } yyVAL.union = yyLOCAL - case 447: + case 448: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ReferenceAction -//line sql.y:2645 +//line sql.y:2658 { yyLOCAL = Cascade } yyVAL.union = yyLOCAL - case 448: + case 449: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL ReferenceAction -//line sql.y:2649 +//line sql.y:2662 { yyLOCAL = NoAction } yyVAL.union = yyLOCAL - case 449: + case 450: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL ReferenceAction -//line sql.y:2653 +//line sql.y:2666 { yyLOCAL = SetDefault } yyVAL.union = yyLOCAL - case 450: + case 451: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL ReferenceAction -//line sql.y:2657 +//line sql.y:2670 { yyLOCAL = SetNull } yyVAL.union = yyLOCAL - case 451: + case 452: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2662 +//line sql.y:2675 { yyVAL.str = "" } - case 452: + case 453: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2666 +//line sql.y:2679 { yyVAL.str = string(yyDollar[1].str) } - case 453: + case 454: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2670 +//line sql.y:2683 { yyVAL.str = string(yyDollar[1].str) } - case 454: + case 455: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:2676 +//line sql.y:2689 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 455: + case 456: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:2680 +//line sql.y:2693 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 456: + case 457: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:2685 +//line sql.y:2698 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 457: + case 458: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:2689 +//line sql.y:2702 { yyLOCAL = yyDollar[1].booleanUnion() } yyVAL.union = yyLOCAL - case 458: + case 459: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL TableOptions -//line sql.y:2694 +//line sql.y:2707 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 459: + case 460: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableOptions -//line sql.y:2698 +//line sql.y:2711 { yyLOCAL = yyDollar[1].tableOptionsUnion() } yyVAL.union = yyLOCAL - case 460: + case 461: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableOptions -//line sql.y:2704 +//line sql.y:2717 { yyLOCAL = TableOptions{yyDollar[1].tableOptionUnion()} } yyVAL.union = yyLOCAL - case 461: + case 462: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2708 +//line sql.y:2721 { yySLICE := (*TableOptions)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].tableOptionUnion()) } - case 462: + case 463: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2712 +//line sql.y:2725 { yySLICE := (*TableOptions)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[2].tableOptionUnion()) } - case 463: + case 464: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableOptions -//line sql.y:2718 +//line sql.y:2731 { yyLOCAL = TableOptions{yyDollar[1].tableOptionUnion()} } yyVAL.union = yyLOCAL - case 464: + case 465: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2722 +//line sql.y:2735 { yySLICE := (*TableOptions)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[2].tableOptionUnion()) } - case 465: + case 466: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2728 +//line sql.y:2741 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 466: + case 467: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2732 +//line sql.y:2745 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 467: + case 468: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2736 +//line sql.y:2749 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 468: + case 469: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2740 +//line sql.y:2753 { yyLOCAL = &TableOption{Name: (string(yyDollar[2].str)), String: yyDollar[4].str, CaseSensitive: true} } yyVAL.union = yyLOCAL - case 469: + case 470: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2744 +//line sql.y:2757 { yyLOCAL = &TableOption{Name: string(yyDollar[2].str), String: yyDollar[4].str, CaseSensitive: true} } yyVAL.union = yyLOCAL - case 470: + case 471: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2748 +//line sql.y:2761 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 471: + case 472: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2752 +//line sql.y:2765 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewStrLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 472: + case 473: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2756 +//line sql.y:2769 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewStrLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 473: + case 474: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2760 +//line sql.y:2773 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewStrLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 474: + case 475: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2764 +//line sql.y:2777 { yyLOCAL = &TableOption{Name: (string(yyDollar[1].str) + " " + string(yyDollar[2].str)), Value: NewStrLiteral(yyDollar[4].str)} } yyVAL.union = yyLOCAL - case 475: + case 476: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2768 +//line sql.y:2781 { yyLOCAL = &TableOption{Name: (string(yyDollar[1].str) + " " + string(yyDollar[2].str)), Value: NewStrLiteral(yyDollar[4].str)} } yyVAL.union = yyLOCAL - case 476: + case 477: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2772 +//line sql.y:2785 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 477: + case 478: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2776 +//line sql.y:2789 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewStrLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 478: + case 479: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2780 +//line sql.y:2793 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), String: yyDollar[3].identifierCS.String(), CaseSensitive: true} } yyVAL.union = yyLOCAL - case 479: + case 480: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2784 +//line sql.y:2797 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewStrLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 480: + case 481: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2788 +//line sql.y:2801 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), String: string(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 481: + case 482: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2792 +//line sql.y:2805 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 482: + case 483: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2796 +//line sql.y:2809 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 483: + case 484: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2800 +//line sql.y:2813 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 484: + case 485: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2804 +//line sql.y:2817 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 485: + case 486: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2808 +//line sql.y:2821 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), String: string(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 486: + case 487: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2812 +//line sql.y:2825 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewStrLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 487: + case 488: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2816 +//line sql.y:2829 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), String: string(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 488: + case 489: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2820 +//line sql.y:2833 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewStrLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 489: + case 490: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2824 +//line sql.y:2837 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 490: + case 491: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2828 +//line sql.y:2841 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), String: string(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 491: + case 492: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2832 +//line sql.y:2845 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 492: + case 493: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2836 +//line sql.y:2849 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), String: string(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 493: + case 494: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2840 +//line sql.y:2853 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Value: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 494: + case 495: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2844 +//line sql.y:2857 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), String: (yyDollar[3].identifierCI.String() + yyDollar[4].str), CaseSensitive: true} } yyVAL.union = yyLOCAL - case 495: + case 496: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *TableOption -//line sql.y:2848 +//line sql.y:2861 { yyLOCAL = &TableOption{Name: string(yyDollar[1].str), Tables: yyDollar[4].tableNamesUnion()} } yyVAL.union = yyLOCAL - case 496: + case 497: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2853 +//line sql.y:2866 { yyVAL.str = "" } - case 497: + case 498: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2857 +//line sql.y:2870 { yyVAL.str = " " + string(yyDollar[1].str) + " " + string(yyDollar[2].str) } - case 498: + case 499: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2861 +//line sql.y:2874 { yyVAL.str = " " + string(yyDollar[1].str) + " " + string(yyDollar[2].str) } - case 508: + case 509: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2880 +//line sql.y:2893 { yyVAL.str = String(TableName{Qualifier: yyDollar[1].identifierCS, Name: yyDollar[3].identifierCS}) } - case 509: + case 510: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2884 +//line sql.y:2897 { yyVAL.str = yyDollar[1].identifierCI.String() } - case 510: + case 511: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2888 +//line sql.y:2901 { yyVAL.str = encodeSQLString(yyDollar[1].str) } - case 511: + case 512: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2892 +//line sql.y:2905 { yyVAL.str = string(yyDollar[1].str) } - case 512: + case 513: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2897 +//line sql.y:2910 { yyVAL.str = "" } - case 514: + case 515: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:2903 +//line sql.y:2916 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 515: + case 516: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:2907 +//line sql.y:2920 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 516: + case 517: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ColName -//line sql.y:2912 +//line sql.y:2925 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 517: + case 518: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ColName -//line sql.y:2916 +//line sql.y:2929 { yyLOCAL = yyDollar[2].colNameUnion() } yyVAL.union = yyLOCAL - case 518: + case 519: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2921 +//line sql.y:2934 { yyVAL.str = "" } - case 519: + case 520: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2925 +//line sql.y:2938 { yyVAL.str = string(yyDollar[2].str) } - case 520: + case 521: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *Literal -//line sql.y:2930 +//line sql.y:2943 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 521: + case 522: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *Literal -//line sql.y:2934 +//line sql.y:2947 { yyLOCAL = NewIntLiteral(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 522: + case 523: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *Literal -//line sql.y:2938 +//line sql.y:2951 { yyLOCAL = NewDecimalLiteral(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 523: + case 524: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:2943 +//line sql.y:2956 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 524: + case 525: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:2947 +//line sql.y:2960 { yyLOCAL = yyDollar[1].alterOptionsUnion() } yyVAL.union = yyLOCAL - case 525: + case 526: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2951 +//line sql.y:2964 { yySLICE := (*[]AlterOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, &OrderByOption{Cols: yyDollar[5].columnsUnion()}) } - case 526: + case 527: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:2955 +//line sql.y:2968 { yyLOCAL = yyDollar[1].alterOptionsUnion() } yyVAL.union = yyLOCAL - case 527: + case 528: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2959 +//line sql.y:2972 { yySLICE := (*[]AlterOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].alterOptionsUnion()...) } - case 528: + case 529: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:2963 +//line sql.y:2976 { yyLOCAL = append(append(yyDollar[1].alterOptionsUnion(), yyDollar[3].alterOptionsUnion()...), &OrderByOption{Cols: yyDollar[7].columnsUnion()}) } yyVAL.union = yyLOCAL - case 529: + case 530: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:2969 +//line sql.y:2982 { yyLOCAL = []AlterOption{yyDollar[1].alterOptionUnion()} } yyVAL.union = yyLOCAL - case 530: + case 531: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2973 +//line sql.y:2986 { yySLICE := (*[]AlterOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].alterOptionUnion()) } - case 531: + case 532: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2977 +//line sql.y:2990 { yySLICE := (*[]AlterOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].alterOptionUnion()) } - case 532: + case 533: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL AlterOption -//line sql.y:2983 +//line sql.y:2996 { yyLOCAL = yyDollar[1].tableOptionsUnion() } yyVAL.union = yyLOCAL - case 533: + case 534: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:2987 +//line sql.y:3000 { yyLOCAL = &AddConstraintDefinition{ConstraintDefinition: yyDollar[2].constraintDefinitionUnion()} } yyVAL.union = yyLOCAL - case 534: + case 535: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:2991 +//line sql.y:3004 { yyLOCAL = &AddConstraintDefinition{ConstraintDefinition: yyDollar[2].constraintDefinitionUnion()} } yyVAL.union = yyLOCAL - case 535: + case 536: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:2995 +//line sql.y:3008 { yyLOCAL = &AddIndexDefinition{IndexDefinition: yyDollar[2].indexDefinitionUnion()} } yyVAL.union = yyLOCAL - case 536: + case 537: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL AlterOption -//line sql.y:2999 +//line sql.y:3012 { yyLOCAL = &AddColumns{Columns: yyDollar[4].columnDefinitionsUnion()} } yyVAL.union = yyLOCAL - case 537: + case 538: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3003 +//line sql.y:3016 { yyLOCAL = &AddColumns{Columns: []*ColumnDefinition{yyDollar[3].columnDefinitionUnion()}, First: yyDollar[4].booleanUnion(), After: yyDollar[5].colNameUnion()} } yyVAL.union = yyLOCAL - case 538: + case 539: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3007 +//line sql.y:3020 { yyLOCAL = &AlterColumn{Column: yyDollar[3].colNameUnion(), DropDefault: true} } yyVAL.union = yyLOCAL - case 539: + case 540: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3011 +//line sql.y:3024 { yyLOCAL = &AlterColumn{Column: yyDollar[3].colNameUnion(), DropDefault: false, DefaultVal: yyDollar[6].exprUnion(), DefaultLiteral: true} } yyVAL.union = yyLOCAL - case 540: + case 541: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3015 +//line sql.y:3028 { yyLOCAL = &AlterColumn{Column: yyDollar[3].colNameUnion(), DropDefault: false, DefaultVal: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 541: + case 542: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3019 +//line sql.y:3032 { yyLOCAL = &AlterColumn{Column: yyDollar[3].colNameUnion(), Invisible: ptr.Of(false)} } yyVAL.union = yyLOCAL - case 542: + case 543: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3023 +//line sql.y:3036 { yyLOCAL = &AlterColumn{Column: yyDollar[3].colNameUnion(), Invisible: ptr.Of(true)} } yyVAL.union = yyLOCAL - case 543: + case 544: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3027 +//line sql.y:3040 { yyLOCAL = &AlterCheck{Name: yyDollar[3].identifierCI, Enforced: yyDollar[4].booleanUnion()} } yyVAL.union = yyLOCAL - case 544: + case 545: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3031 +//line sql.y:3044 { yyLOCAL = &AlterIndex{Name: yyDollar[3].identifierCI, Invisible: false} } yyVAL.union = yyLOCAL - case 545: + case 546: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3035 +//line sql.y:3048 { yyLOCAL = &AlterIndex{Name: yyDollar[3].identifierCI, Invisible: true} } yyVAL.union = yyLOCAL - case 546: + case 547: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3039 +//line sql.y:3052 { yyLOCAL = &ChangeColumn{OldColumn: yyDollar[3].colNameUnion(), NewColDefinition: yyDollar[4].columnDefinitionUnion(), First: yyDollar[5].booleanUnion(), After: yyDollar[6].colNameUnion()} } yyVAL.union = yyLOCAL - case 547: + case 548: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3043 +//line sql.y:3056 { yyLOCAL = &ModifyColumn{NewColDefinition: yyDollar[3].columnDefinitionUnion(), First: yyDollar[4].booleanUnion(), After: yyDollar[5].colNameUnion()} } yyVAL.union = yyLOCAL - case 548: + case 549: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3047 +//line sql.y:3060 { yyLOCAL = &RenameColumn{OldName: yyDollar[3].colNameUnion(), NewName: yyDollar[5].colNameUnion()} } yyVAL.union = yyLOCAL - case 549: + case 550: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3051 +//line sql.y:3064 { yyLOCAL = &AlterCharset{CharacterSet: yyDollar[4].str, Collate: yyDollar[5].str} } yyVAL.union = yyLOCAL - case 550: + case 551: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3055 +//line sql.y:3068 { yyLOCAL = &KeyState{Enable: false} } yyVAL.union = yyLOCAL - case 551: + case 552: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3059 +//line sql.y:3072 { yyLOCAL = &KeyState{Enable: true} } yyVAL.union = yyLOCAL - case 552: + case 553: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3063 +//line sql.y:3076 { yyLOCAL = &TablespaceOperation{Import: false} } yyVAL.union = yyLOCAL - case 553: + case 554: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3067 +//line sql.y:3080 { yyLOCAL = &TablespaceOperation{Import: true} } yyVAL.union = yyLOCAL - case 554: + case 555: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3071 +//line sql.y:3084 { yyLOCAL = &DropColumn{Name: yyDollar[3].colNameUnion()} } yyVAL.union = yyLOCAL - case 555: + case 556: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3075 +//line sql.y:3088 { yyLOCAL = &DropKey{Type: NormalKeyType, Name: yyDollar[3].identifierCI} } yyVAL.union = yyLOCAL - case 556: + case 557: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3079 +//line sql.y:3092 { yyLOCAL = &DropKey{Type: PrimaryKeyType} } yyVAL.union = yyLOCAL - case 557: + case 558: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3083 +//line sql.y:3096 { yyLOCAL = &DropKey{Type: ForeignKeyType, Name: yyDollar[4].identifierCI} } yyVAL.union = yyLOCAL - case 558: + case 559: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3087 +//line sql.y:3100 { yyLOCAL = &DropKey{Type: CheckKeyType, Name: yyDollar[3].identifierCI} } yyVAL.union = yyLOCAL - case 559: + case 560: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3091 +//line sql.y:3104 { yyLOCAL = &DropKey{Type: CheckKeyType, Name: yyDollar[3].identifierCI} } yyVAL.union = yyLOCAL - case 560: + case 561: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3095 +//line sql.y:3108 { yyLOCAL = &Force{} } yyVAL.union = yyLOCAL - case 561: + case 562: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3099 +//line sql.y:3112 { yyLOCAL = &RenameTableName{Table: yyDollar[3].tableName} } yyVAL.union = yyLOCAL - case 562: + case 563: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3103 +//line sql.y:3116 { yyLOCAL = &RenameIndex{OldName: yyDollar[3].identifierCI, NewName: yyDollar[5].identifierCI} } yyVAL.union = yyLOCAL - case 563: + case 564: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:3109 +//line sql.y:3122 { yyLOCAL = []AlterOption{yyDollar[1].alterOptionUnion()} } yyVAL.union = yyLOCAL - case 564: + case 565: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3113 +//line sql.y:3126 { yySLICE := (*[]AlterOption)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].alterOptionUnion()) } - case 565: + case 566: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3119 +//line sql.y:3132 { yyLOCAL = AlgorithmValue(string(yyDollar[3].str)) } yyVAL.union = yyLOCAL - case 566: + case 567: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3123 +//line sql.y:3136 { yyLOCAL = AlgorithmValue(string(yyDollar[3].str)) } yyVAL.union = yyLOCAL - case 567: + case 568: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3127 +//line sql.y:3140 { yyLOCAL = AlgorithmValue(string(yyDollar[3].str)) } yyVAL.union = yyLOCAL - case 568: + case 569: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3131 +//line sql.y:3144 { yyLOCAL = AlgorithmValue(string(yyDollar[3].str)) } yyVAL.union = yyLOCAL - case 569: + case 570: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3135 +//line sql.y:3148 { yyLOCAL = &LockOption{Type: DefaultType} } yyVAL.union = yyLOCAL - case 570: + case 571: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3139 +//line sql.y:3152 { yyLOCAL = &LockOption{Type: NoneType} } yyVAL.union = yyLOCAL - case 571: + case 572: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3143 +//line sql.y:3156 { yyLOCAL = &LockOption{Type: SharedType} } yyVAL.union = yyLOCAL - case 572: + case 573: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3147 +//line sql.y:3160 { yyLOCAL = &LockOption{Type: ExclusiveType} } yyVAL.union = yyLOCAL - case 573: + case 574: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3151 +//line sql.y:3164 { yyLOCAL = &Validation{With: true} } yyVAL.union = yyLOCAL - case 574: + case 575: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL AlterOption -//line sql.y:3155 +//line sql.y:3168 { yyLOCAL = &Validation{With: false} } yyVAL.union = yyLOCAL - case 575: + case 576: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:3161 +//line sql.y:3174 { yyDollar[1].alterTableUnion().FullyParsed = true yyDollar[1].alterTableUnion().AlterOptions = yyDollar[2].alterOptionsUnion() @@ -14181,10 +14227,10 @@ yydefault: yyLOCAL = yyDollar[1].alterTableUnion() } yyVAL.union = yyLOCAL - case 576: + case 577: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:3168 +//line sql.y:3181 { yyDollar[1].alterTableUnion().FullyParsed = true yyDollar[1].alterTableUnion().AlterOptions = yyDollar[2].alterOptionsUnion() @@ -14192,10 +14238,10 @@ yydefault: yyLOCAL = yyDollar[1].alterTableUnion() } yyVAL.union = yyLOCAL - case 577: + case 578: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:3175 +//line sql.y:3188 { yyDollar[1].alterTableUnion().FullyParsed = true yyDollar[1].alterTableUnion().AlterOptions = yyDollar[2].alterOptionsUnion() @@ -14203,28 +14249,28 @@ yydefault: yyLOCAL = yyDollar[1].alterTableUnion() } yyVAL.union = yyLOCAL - case 578: + case 579: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:3182 +//line sql.y:3195 { yyDollar[1].alterTableUnion().FullyParsed = true yyDollar[1].alterTableUnion().PartitionSpec = yyDollar[2].partSpecUnion() yyLOCAL = yyDollar[1].alterTableUnion() } yyVAL.union = yyLOCAL - case 579: + case 580: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL Statement -//line sql.y:3188 +//line sql.y:3201 { 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].selStmtUnion(), CheckOption: yyDollar[11].str} } yyVAL.union = yyLOCAL - case 580: + case 581: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:3198 +//line sql.y:3211 { yyDollar[1].alterDatabaseUnion().FullyParsed = true yyDollar[1].alterDatabaseUnion().DBName = yyDollar[2].identifierCS @@ -14232,10 +14278,10 @@ yydefault: yyLOCAL = yyDollar[1].alterDatabaseUnion() } yyVAL.union = yyLOCAL - case 581: + case 582: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:3205 +//line sql.y:3218 { yyDollar[1].alterDatabaseUnion().FullyParsed = true yyDollar[1].alterDatabaseUnion().DBName = yyDollar[2].identifierCS @@ -14243,10 +14289,10 @@ yydefault: yyLOCAL = yyDollar[1].alterDatabaseUnion() } yyVAL.union = yyLOCAL - case 582: + case 583: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Statement -//line sql.y:3212 +//line sql.y:3225 { yyLOCAL = &AlterVschema{ Action: CreateVindexDDLAction, @@ -14259,10 +14305,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 583: + case 584: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:3224 +//line sql.y:3237 { yyLOCAL = &AlterVschema{ Action: DropVindexDDLAction, @@ -14273,26 +14319,26 @@ yydefault: } } yyVAL.union = yyLOCAL - case 584: + case 585: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:3234 +//line sql.y:3247 { yyLOCAL = &AlterVschema{Action: AddVschemaTableDDLAction, Table: yyDollar[6].tableName} } yyVAL.union = yyLOCAL - case 585: + case 586: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:3238 +//line sql.y:3251 { yyLOCAL = &AlterVschema{Action: DropVschemaTableDDLAction, Table: yyDollar[6].tableName} } yyVAL.union = yyLOCAL - case 586: + case 587: yyDollar = yyS[yypt-13 : yypt+1] var yyLOCAL Statement -//line sql.y:3242 +//line sql.y:3255 { yyLOCAL = &AlterVschema{ Action: AddColVindexDDLAction, @@ -14306,10 +14352,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 587: + case 588: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Statement -//line sql.y:3255 +//line sql.y:3268 { yyLOCAL = &AlterVschema{ Action: DropColVindexDDLAction, @@ -14320,26 +14366,26 @@ yydefault: } } yyVAL.union = yyLOCAL - case 588: + case 589: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:3265 +//line sql.y:3278 { yyLOCAL = &AlterVschema{Action: AddSequenceDDLAction, Table: yyDollar[6].tableName} } yyVAL.union = yyLOCAL - case 589: + case 590: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:3269 +//line sql.y:3282 { yyLOCAL = &AlterVschema{Action: DropSequenceDDLAction, Table: yyDollar[6].tableName} } yyVAL.union = yyLOCAL - case 590: + case 591: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL Statement -//line sql.y:3273 +//line sql.y:3286 { yyLOCAL = &AlterVschema{ Action: AddAutoIncDDLAction, @@ -14351,10 +14397,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 591: + case 592: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:3284 +//line sql.y:3297 { yyLOCAL = &AlterVschema{ Action: DropAutoIncDDLAction, @@ -14362,10 +14408,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 592: + case 593: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3291 +//line sql.y:3304 { yyLOCAL = &AlterMigration{ Type: RetryMigrationType, @@ -14373,10 +14419,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 593: + case 594: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3298 +//line sql.y:3311 { yyLOCAL = &AlterMigration{ Type: CleanupMigrationType, @@ -14384,10 +14430,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 594: + case 595: + yyDollar = yyS[yypt-5 : yypt+1] + var yyLOCAL Statement +//line sql.y:3318 + { + yyLOCAL = &AlterMigration{ + Type: CleanupAllMigrationType, + } + } + yyVAL.union = yyLOCAL + case 596: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3305 +//line sql.y:3324 { yyLOCAL = &AlterMigration{ Type: LaunchMigrationType, @@ -14395,10 +14451,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 595: + case 597: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:3312 +//line sql.y:3331 { yyLOCAL = &AlterMigration{ Type: LaunchMigrationType, @@ -14407,20 +14463,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 596: + case 598: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3320 +//line sql.y:3339 { yyLOCAL = &AlterMigration{ Type: LaunchAllMigrationType, } } yyVAL.union = yyLOCAL - case 597: + case 599: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3326 +//line sql.y:3345 { yyLOCAL = &AlterMigration{ Type: CompleteMigrationType, @@ -14428,20 +14484,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 598: + case 600: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3333 +//line sql.y:3352 { yyLOCAL = &AlterMigration{ Type: CompleteAllMigrationType, } } yyVAL.union = yyLOCAL - case 599: + case 601: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3339 +//line sql.y:3358 { yyLOCAL = &AlterMigration{ Type: CancelMigrationType, @@ -14449,20 +14505,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 600: + case 602: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3346 +//line sql.y:3365 { yyLOCAL = &AlterMigration{ Type: CancelAllMigrationType, } } yyVAL.union = yyLOCAL - case 601: + case 603: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:3352 +//line sql.y:3371 { yyLOCAL = &AlterMigration{ Type: ThrottleMigrationType, @@ -14472,10 +14528,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 602: + case 604: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:3361 +//line sql.y:3380 { yyLOCAL = &AlterMigration{ Type: ThrottleAllMigrationType, @@ -14484,10 +14540,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 603: + case 605: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3369 +//line sql.y:3388 { yyLOCAL = &AlterMigration{ Type: UnthrottleMigrationType, @@ -14495,20 +14551,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 604: + case 606: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3376 +//line sql.y:3395 { yyLOCAL = &AlterMigration{ Type: UnthrottleAllMigrationType, } } yyVAL.union = yyLOCAL - case 605: + case 607: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3382 +//line sql.y:3401 { yyLOCAL = &AlterMigration{ Type: ForceCutOverMigrationType, @@ -14516,28 +14572,28 @@ yydefault: } } yyVAL.union = yyLOCAL - case 606: + case 608: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3389 +//line sql.y:3408 { yyLOCAL = &AlterMigration{ Type: ForceCutOverAllMigrationType, } } yyVAL.union = yyLOCAL - case 607: + case 609: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *PartitionOption -//line sql.y:3396 +//line sql.y:3415 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 608: + case 610: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *PartitionOption -//line sql.y:3400 +//line sql.y:3419 { yyDollar[3].partitionOptionUnion().Partitions = yyDollar[4].integerUnion() yyDollar[3].partitionOptionUnion().SubPartition = yyDollar[5].subPartitionUnion() @@ -14545,10 +14601,10 @@ yydefault: yyLOCAL = yyDollar[3].partitionOptionUnion() } yyVAL.union = yyLOCAL - case 609: + case 611: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *PartitionOption -//line sql.y:3409 +//line sql.y:3428 { yyLOCAL = &PartitionOption{ IsLinear: yyDollar[1].booleanUnion(), @@ -14557,10 +14613,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 610: + case 612: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *PartitionOption -//line sql.y:3417 +//line sql.y:3436 { yyLOCAL = &PartitionOption{ IsLinear: yyDollar[1].booleanUnion(), @@ -14570,10 +14626,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 611: + case 613: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *PartitionOption -//line sql.y:3426 +//line sql.y:3445 { yyLOCAL = &PartitionOption{ Type: yyDollar[1].partitionByTypeUnion(), @@ -14581,10 +14637,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 612: + case 614: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *PartitionOption -//line sql.y:3433 +//line sql.y:3452 { yyLOCAL = &PartitionOption{ Type: yyDollar[1].partitionByTypeUnion(), @@ -14592,18 +14648,18 @@ yydefault: } } yyVAL.union = yyLOCAL - case 613: + case 615: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *SubPartition -//line sql.y:3441 +//line sql.y:3460 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 614: + case 616: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *SubPartition -//line sql.y:3445 +//line sql.y:3464 { yyLOCAL = &SubPartition{ IsLinear: yyDollar[3].booleanUnion(), @@ -14613,10 +14669,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 615: + case 617: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL *SubPartition -//line sql.y:3454 +//line sql.y:3473 { yyLOCAL = &SubPartition{ IsLinear: yyDollar[3].booleanUnion(), @@ -14627,678 +14683,678 @@ yydefault: } } yyVAL.union = yyLOCAL - case 616: + case 618: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*PartitionDefinition -//line sql.y:3465 +//line sql.y:3484 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 617: + case 619: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*PartitionDefinition -//line sql.y:3469 +//line sql.y:3488 { yyLOCAL = yyDollar[2].partDefsUnion() } yyVAL.union = yyLOCAL - case 618: + case 620: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:3474 +//line sql.y:3493 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 619: + case 621: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:3478 +//line sql.y:3497 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 620: + case 622: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int -//line sql.y:3483 +//line sql.y:3502 { yyLOCAL = 0 } yyVAL.union = yyLOCAL - case 621: + case 623: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int -//line sql.y:3487 +//line sql.y:3506 { yyLOCAL = convertStringToInt(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 622: + case 624: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL TableExpr -//line sql.y:3493 +//line sql.y:3512 { yyLOCAL = &JSONTableExpr{Expr: yyDollar[3].exprUnion(), Filter: yyDollar[5].exprUnion(), Columns: yyDollar[6].jtColumnListUnion(), Alias: yyDollar[8].identifierCS} } yyVAL.union = yyLOCAL - case 623: + case 625: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL []*JtColumnDefinition -//line sql.y:3499 +//line sql.y:3518 { yyLOCAL = yyDollar[3].jtColumnListUnion() } yyVAL.union = yyLOCAL - case 624: + case 626: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*JtColumnDefinition -//line sql.y:3505 +//line sql.y:3524 { yyLOCAL = []*JtColumnDefinition{yyDollar[1].jtColumnDefinitionUnion()} } yyVAL.union = yyLOCAL - case 625: + case 627: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3509 +//line sql.y:3528 { yySLICE := (*[]*JtColumnDefinition)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].jtColumnDefinitionUnion()) } - case 626: + case 628: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *JtColumnDefinition -//line sql.y:3515 +//line sql.y:3534 { yyLOCAL = &JtColumnDefinition{JtOrdinal: &JtOrdinalColDef{Name: yyDollar[1].identifierCI}} } yyVAL.union = yyLOCAL - case 627: + case 629: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *JtColumnDefinition -//line sql.y:3519 +//line sql.y:3538 { 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 628: + case 630: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *JtColumnDefinition -//line sql.y:3525 +//line sql.y:3544 { 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 629: + case 631: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *JtColumnDefinition -//line sql.y:3531 +//line sql.y:3550 { 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 630: + case 632: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *JtColumnDefinition -//line sql.y:3537 +//line sql.y:3556 { 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 631: + case 633: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *JtColumnDefinition -//line sql.y:3543 +//line sql.y:3562 { jtNestedPath := &JtNestedPathColDef{Path: yyDollar[3].exprUnion(), Columns: yyDollar[4].jtColumnListUnion()} yyLOCAL = &JtColumnDefinition{JtNestedPath: jtNestedPath} } yyVAL.union = yyLOCAL - case 632: + case 634: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:3549 +//line sql.y:3568 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 633: + case 635: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:3553 +//line sql.y:3572 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 634: + case 636: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:3557 +//line sql.y:3576 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 635: + case 637: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:3561 +//line sql.y:3580 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 636: + case 638: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *JtOnResponse -//line sql.y:3567 +//line sql.y:3586 { yyLOCAL = yyDollar[1].jtOnResponseUnion() } yyVAL.union = yyLOCAL - case 637: + case 639: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *JtOnResponse -//line sql.y:3573 +//line sql.y:3592 { yyLOCAL = yyDollar[1].jtOnResponseUnion() } yyVAL.union = yyLOCAL - case 638: + case 640: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *JtOnResponse -//line sql.y:3579 +//line sql.y:3598 { yyLOCAL = &JtOnResponse{ResponseType: ErrorJSONType} } yyVAL.union = yyLOCAL - case 639: + case 641: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *JtOnResponse -//line sql.y:3583 +//line sql.y:3602 { yyLOCAL = &JtOnResponse{ResponseType: NullJSONType} } yyVAL.union = yyLOCAL - case 640: + case 642: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *JtOnResponse -//line sql.y:3587 +//line sql.y:3606 { yyLOCAL = &JtOnResponse{ResponseType: DefaultJSONType, Expr: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 641: + case 643: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL PartitionByType -//line sql.y:3593 +//line sql.y:3612 { yyLOCAL = RangeType } yyVAL.union = yyLOCAL - case 642: + case 644: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL PartitionByType -//line sql.y:3597 +//line sql.y:3616 { yyLOCAL = ListType } yyVAL.union = yyLOCAL - case 643: + case 645: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int -//line sql.y:3602 +//line sql.y:3621 { yyLOCAL = -1 } yyVAL.union = yyLOCAL - case 644: + case 646: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL int -//line sql.y:3606 +//line sql.y:3625 { yyLOCAL = convertStringToInt(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 645: + case 647: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int -//line sql.y:3611 +//line sql.y:3630 { yyLOCAL = -1 } yyVAL.union = yyLOCAL - case 646: + case 648: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL int -//line sql.y:3615 +//line sql.y:3634 { yyLOCAL = convertStringToInt(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 647: + case 649: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3621 +//line sql.y:3640 { yyLOCAL = &PartitionSpec{Action: AddAction, Definitions: []*PartitionDefinition{yyDollar[4].partDefUnion()}} } yyVAL.union = yyLOCAL - case 648: + case 650: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3625 +//line sql.y:3644 { yyLOCAL = &PartitionSpec{Action: DropAction, Names: yyDollar[3].partitionsUnion()} } yyVAL.union = yyLOCAL - case 649: + case 651: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3629 +//line sql.y:3648 { yyLOCAL = &PartitionSpec{Action: ReorganizeAction, Names: yyDollar[3].partitionsUnion(), Definitions: yyDollar[6].partDefsUnion()} } yyVAL.union = yyLOCAL - case 650: + case 652: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3633 +//line sql.y:3652 { yyLOCAL = &PartitionSpec{Action: DiscardAction, Names: yyDollar[3].partitionsUnion()} } yyVAL.union = yyLOCAL - case 651: + case 653: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3637 +//line sql.y:3656 { yyLOCAL = &PartitionSpec{Action: DiscardAction, IsAll: true} } yyVAL.union = yyLOCAL - case 652: + case 654: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3641 +//line sql.y:3660 { yyLOCAL = &PartitionSpec{Action: ImportAction, Names: yyDollar[3].partitionsUnion()} } yyVAL.union = yyLOCAL - case 653: + case 655: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3645 +//line sql.y:3664 { yyLOCAL = &PartitionSpec{Action: ImportAction, IsAll: true} } yyVAL.union = yyLOCAL - case 654: + case 656: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3649 +//line sql.y:3668 { yyLOCAL = &PartitionSpec{Action: TruncateAction, Names: yyDollar[3].partitionsUnion()} } yyVAL.union = yyLOCAL - case 655: + case 657: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3653 +//line sql.y:3672 { yyLOCAL = &PartitionSpec{Action: TruncateAction, IsAll: true} } yyVAL.union = yyLOCAL - case 656: + case 658: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3657 +//line sql.y:3676 { yyLOCAL = &PartitionSpec{Action: CoalesceAction, Number: NewIntLiteral(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 657: + case 659: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3661 +//line sql.y:3680 { yyLOCAL = &PartitionSpec{Action: ExchangeAction, Names: Partitions{yyDollar[3].identifierCI}, TableName: yyDollar[6].tableName, WithoutValidation: yyDollar[7].booleanUnion()} } yyVAL.union = yyLOCAL - case 658: + case 660: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3665 +//line sql.y:3684 { yyLOCAL = &PartitionSpec{Action: AnalyzeAction, Names: yyDollar[3].partitionsUnion()} } yyVAL.union = yyLOCAL - case 659: + case 661: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3669 +//line sql.y:3688 { yyLOCAL = &PartitionSpec{Action: AnalyzeAction, IsAll: true} } yyVAL.union = yyLOCAL - case 660: + case 662: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3673 +//line sql.y:3692 { yyLOCAL = &PartitionSpec{Action: CheckAction, Names: yyDollar[3].partitionsUnion()} } yyVAL.union = yyLOCAL - case 661: + case 663: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3677 +//line sql.y:3696 { yyLOCAL = &PartitionSpec{Action: CheckAction, IsAll: true} } yyVAL.union = yyLOCAL - case 662: + case 664: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3681 +//line sql.y:3700 { yyLOCAL = &PartitionSpec{Action: OptimizeAction, Names: yyDollar[3].partitionsUnion()} } yyVAL.union = yyLOCAL - case 663: + case 665: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3685 +//line sql.y:3704 { yyLOCAL = &PartitionSpec{Action: OptimizeAction, IsAll: true} } yyVAL.union = yyLOCAL - case 664: + case 666: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3689 +//line sql.y:3708 { yyLOCAL = &PartitionSpec{Action: RebuildAction, Names: yyDollar[3].partitionsUnion()} } yyVAL.union = yyLOCAL - case 665: + case 667: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3693 +//line sql.y:3712 { yyLOCAL = &PartitionSpec{Action: RebuildAction, IsAll: true} } yyVAL.union = yyLOCAL - case 666: + case 668: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3697 +//line sql.y:3716 { yyLOCAL = &PartitionSpec{Action: RepairAction, Names: yyDollar[3].partitionsUnion()} } yyVAL.union = yyLOCAL - case 667: + case 669: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3701 +//line sql.y:3720 { yyLOCAL = &PartitionSpec{Action: RepairAction, IsAll: true} } yyVAL.union = yyLOCAL - case 668: + case 670: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionSpec -//line sql.y:3705 +//line sql.y:3724 { yyLOCAL = &PartitionSpec{Action: UpgradeAction} } yyVAL.union = yyLOCAL - case 669: + case 671: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:3710 +//line sql.y:3729 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 670: + case 672: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:3714 +//line sql.y:3733 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 671: + case 673: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:3718 +//line sql.y:3737 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 672: + case 674: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*PartitionDefinition -//line sql.y:3724 +//line sql.y:3743 { yyLOCAL = []*PartitionDefinition{yyDollar[1].partDefUnion()} } yyVAL.union = yyLOCAL - case 673: + case 675: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3728 +//line sql.y:3747 { yySLICE := (*[]*PartitionDefinition)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].partDefUnion()) } - case 674: + case 676: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3734 +//line sql.y:3753 { yyVAL.partDefUnion().Options = yyDollar[2].partitionDefinitionOptionsUnion() } - case 675: + case 677: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *PartitionDefinitionOptions -//line sql.y:3739 +//line sql.y:3758 { yyLOCAL = &PartitionDefinitionOptions{} } yyVAL.union = yyLOCAL - case 676: + case 678: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionDefinitionOptions -//line sql.y:3743 +//line sql.y:3762 { yyDollar[1].partitionDefinitionOptionsUnion().ValueRange = yyDollar[2].partitionValueRangeUnion() yyLOCAL = yyDollar[1].partitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 677: + case 679: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionDefinitionOptions -//line sql.y:3748 +//line sql.y:3767 { yyDollar[1].partitionDefinitionOptionsUnion().Comment = yyDollar[2].literalUnion() yyLOCAL = yyDollar[1].partitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 678: + case 680: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionDefinitionOptions -//line sql.y:3753 +//line sql.y:3772 { yyDollar[1].partitionDefinitionOptionsUnion().Engine = yyDollar[2].partitionEngineUnion() yyLOCAL = yyDollar[1].partitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 679: + case 681: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionDefinitionOptions -//line sql.y:3758 +//line sql.y:3777 { yyDollar[1].partitionDefinitionOptionsUnion().DataDirectory = yyDollar[2].literalUnion() yyLOCAL = yyDollar[1].partitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 680: + case 682: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionDefinitionOptions -//line sql.y:3763 +//line sql.y:3782 { yyDollar[1].partitionDefinitionOptionsUnion().IndexDirectory = yyDollar[2].literalUnion() yyLOCAL = yyDollar[1].partitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 681: + case 683: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionDefinitionOptions -//line sql.y:3768 +//line sql.y:3787 { yyDollar[1].partitionDefinitionOptionsUnion().MaxRows = ptr.Of(yyDollar[2].integerUnion()) yyLOCAL = yyDollar[1].partitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 682: + case 684: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionDefinitionOptions -//line sql.y:3773 +//line sql.y:3792 { yyDollar[1].partitionDefinitionOptionsUnion().MinRows = ptr.Of(yyDollar[2].integerUnion()) yyLOCAL = yyDollar[1].partitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 683: + case 685: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionDefinitionOptions -//line sql.y:3778 +//line sql.y:3797 { yyDollar[1].partitionDefinitionOptionsUnion().TableSpace = yyDollar[2].str yyLOCAL = yyDollar[1].partitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 684: + case 686: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionDefinitionOptions -//line sql.y:3783 +//line sql.y:3802 { yyDollar[1].partitionDefinitionOptionsUnion().SubPartitionDefinitions = yyDollar[2].subPartitionDefinitionsUnion() yyLOCAL = yyDollar[1].partitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 685: + case 687: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SubPartitionDefinitions -//line sql.y:3789 +//line sql.y:3808 { yyLOCAL = yyDollar[2].subPartitionDefinitionsUnion() } yyVAL.union = yyLOCAL - case 686: + case 688: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL SubPartitionDefinitions -//line sql.y:3795 +//line sql.y:3814 { yyLOCAL = SubPartitionDefinitions{yyDollar[1].subPartitionDefinitionUnion()} } yyVAL.union = yyLOCAL - case 687: + case 689: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3799 +//line sql.y:3818 { yySLICE := (*SubPartitionDefinitions)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].subPartitionDefinitionUnion()) } - case 688: + case 690: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *SubPartitionDefinition -//line sql.y:3805 +//line sql.y:3824 { yyLOCAL = &SubPartitionDefinition{Name: yyDollar[2].identifierCI, Options: yyDollar[3].subPartitionDefinitionOptionsUnion()} } yyVAL.union = yyLOCAL - case 689: + case 691: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *SubPartitionDefinitionOptions -//line sql.y:3810 +//line sql.y:3829 { yyLOCAL = &SubPartitionDefinitionOptions{} } yyVAL.union = yyLOCAL - case 690: + case 692: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *SubPartitionDefinitionOptions -//line sql.y:3814 +//line sql.y:3833 { yyDollar[1].subPartitionDefinitionOptionsUnion().Comment = yyDollar[2].literalUnion() yyLOCAL = yyDollar[1].subPartitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 691: + case 693: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *SubPartitionDefinitionOptions -//line sql.y:3819 +//line sql.y:3838 { yyDollar[1].subPartitionDefinitionOptionsUnion().Engine = yyDollar[2].partitionEngineUnion() yyLOCAL = yyDollar[1].subPartitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 692: + case 694: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *SubPartitionDefinitionOptions -//line sql.y:3824 +//line sql.y:3843 { yyDollar[1].subPartitionDefinitionOptionsUnion().DataDirectory = yyDollar[2].literalUnion() yyLOCAL = yyDollar[1].subPartitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 693: + case 695: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *SubPartitionDefinitionOptions -//line sql.y:3829 +//line sql.y:3848 { yyDollar[1].subPartitionDefinitionOptionsUnion().IndexDirectory = yyDollar[2].literalUnion() yyLOCAL = yyDollar[1].subPartitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 694: + case 696: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *SubPartitionDefinitionOptions -//line sql.y:3834 +//line sql.y:3853 { yyDollar[1].subPartitionDefinitionOptionsUnion().MaxRows = ptr.Of(yyDollar[2].integerUnion()) yyLOCAL = yyDollar[1].subPartitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 695: + case 697: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *SubPartitionDefinitionOptions -//line sql.y:3839 +//line sql.y:3858 { yyDollar[1].subPartitionDefinitionOptionsUnion().MinRows = ptr.Of(yyDollar[2].integerUnion()) yyLOCAL = yyDollar[1].subPartitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 696: + case 698: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *SubPartitionDefinitionOptions -//line sql.y:3844 +//line sql.y:3863 { yyDollar[1].subPartitionDefinitionOptionsUnion().TableSpace = yyDollar[2].str yyLOCAL = yyDollar[1].subPartitionDefinitionOptionsUnion() } yyVAL.union = yyLOCAL - case 697: + case 699: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *PartitionValueRange -//line sql.y:3851 +//line sql.y:3870 { yyLOCAL = &PartitionValueRange{ Type: LessThanType, @@ -15306,10 +15362,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 698: + case 700: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *PartitionValueRange -//line sql.y:3858 +//line sql.y:3877 { yyLOCAL = &PartitionValueRange{ Type: LessThanType, @@ -15317,10 +15373,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 699: + case 701: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *PartitionValueRange -//line sql.y:3865 +//line sql.y:3884 { yyLOCAL = &PartitionValueRange{ Type: InType, @@ -15328,131 +15384,131 @@ yydefault: } } yyVAL.union = yyLOCAL - case 700: + case 702: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:3873 +//line sql.y:3892 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 701: + case 703: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:3877 +//line sql.y:3896 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 702: + case 704: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *PartitionEngine -//line sql.y:3883 +//line sql.y:3902 { yyLOCAL = &PartitionEngine{Storage: yyDollar[1].booleanUnion(), Name: yyDollar[4].identifierCS.String()} } yyVAL.union = yyLOCAL - case 703: + case 705: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *Literal -//line sql.y:3889 +//line sql.y:3908 { yyLOCAL = NewStrLiteral(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 704: + case 706: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *Literal -//line sql.y:3895 +//line sql.y:3914 { yyLOCAL = NewStrLiteral(yyDollar[4].str) } yyVAL.union = yyLOCAL - case 705: + case 707: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *Literal -//line sql.y:3901 +//line sql.y:3920 { yyLOCAL = NewStrLiteral(yyDollar[4].str) } yyVAL.union = yyLOCAL - case 706: + case 708: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int -//line sql.y:3907 +//line sql.y:3926 { yyLOCAL = convertStringToInt(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 707: + case 709: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int -//line sql.y:3913 +//line sql.y:3932 { yyLOCAL = convertStringToInt(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 708: + case 710: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3919 +//line sql.y:3938 { yyVAL.str = yyDollar[3].identifierCS.String() } - case 709: + case 711: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *PartitionDefinition -//line sql.y:3925 +//line sql.y:3944 { yyLOCAL = &PartitionDefinition{Name: yyDollar[2].identifierCI} } yyVAL.union = yyLOCAL - case 710: + case 712: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3931 +//line sql.y:3950 { yyVAL.str = "" } - case 711: + case 713: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3935 +//line sql.y:3954 { yyVAL.str = "" } - case 712: + case 714: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:3941 +//line sql.y:3960 { yyLOCAL = &RenameTable{TablePairs: yyDollar[3].renameTablePairsUnion()} } yyVAL.union = yyLOCAL - case 713: + case 715: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*RenameTablePair -//line sql.y:3947 +//line sql.y:3966 { yyLOCAL = []*RenameTablePair{{FromTable: yyDollar[1].tableName, ToTable: yyDollar[3].tableName}} } yyVAL.union = yyLOCAL - case 714: + case 716: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:3951 +//line sql.y:3970 { yySLICE := (*[]*RenameTablePair)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, &RenameTablePair{FromTable: yyDollar[3].tableName, ToTable: yyDollar[5].tableName}) } - case 715: + case 717: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:3957 +//line sql.y:3976 { yyLOCAL = &DropTable{FromTables: yyDollar[6].tableNamesUnion(), IfExists: yyDollar[5].booleanUnion(), Comments: Comments(yyDollar[2].strs).Parsed(), Temp: yyDollar[3].booleanUnion()} } yyVAL.union = yyLOCAL - case 716: + case 718: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:3961 +//line sql.y:3980 { // Change this to an alter statement if yyDollar[4].identifierCI.Lowered() == "primary" { @@ -15462,1327 +15518,1345 @@ yydefault: } } yyVAL.union = yyLOCAL - case 717: + case 719: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:3970 +//line sql.y:3989 { yyLOCAL = &DropView{FromTables: yyDollar[5].tableNamesUnion(), Comments: Comments(yyDollar[2].strs).Parsed(), IfExists: yyDollar[4].booleanUnion()} } yyVAL.union = yyLOCAL - case 718: + case 720: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3974 +//line sql.y:3993 { yyLOCAL = &DropDatabase{Comments: Comments(yyDollar[2].strs).Parsed(), DBName: yyDollar[5].identifierCS, IfExists: yyDollar[4].booleanUnion()} } yyVAL.union = yyLOCAL - case 719: + case 721: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:3980 +//line sql.y:3999 { yyLOCAL = &TruncateTable{Table: yyDollar[3].tableName} } yyVAL.union = yyLOCAL - case 720: + case 722: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:3984 +//line sql.y:4003 { yyLOCAL = &TruncateTable{Table: yyDollar[2].tableName} } yyVAL.union = yyLOCAL - case 721: + case 723: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:3990 +//line sql.y:4009 { yyLOCAL = &Analyze{IsLocal: yyDollar[2].booleanUnion(), Table: yyDollar[4].tableName} } yyVAL.union = yyLOCAL - case 722: + case 724: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:3996 +//line sql.y:4015 { yyLOCAL = &PurgeBinaryLogs{To: string(yyDollar[5].str)} } yyVAL.union = yyLOCAL - case 723: + case 725: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:4000 +//line sql.y:4019 { yyLOCAL = &PurgeBinaryLogs{Before: string(yyDollar[5].str)} } yyVAL.union = yyLOCAL - case 724: + case 726: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4006 +//line sql.y:4025 { yyLOCAL = &Show{&ShowBasic{Command: Charset, Filter: yyDollar[3].showFilterUnion()}} } yyVAL.union = yyLOCAL - case 725: + case 727: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4010 +//line sql.y:4029 { yyLOCAL = &Show{&ShowBasic{Command: Collation, Filter: yyDollar[3].showFilterUnion()}} } yyVAL.union = yyLOCAL - case 726: + case 728: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:4014 +//line sql.y:4033 { 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 727: + case 729: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4018 +//line sql.y:4037 { yyLOCAL = &Show{&ShowBasic{Command: Database, Filter: yyDollar[3].showFilterUnion()}} } yyVAL.union = yyLOCAL - case 728: + case 730: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4022 +//line sql.y:4041 { yyLOCAL = &Show{&ShowBasic{Command: Database, Filter: yyDollar[3].showFilterUnion()}} } yyVAL.union = yyLOCAL - case 729: + case 731: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4026 +//line sql.y:4045 { yyLOCAL = &Show{&ShowBasic{Command: Keyspace, Filter: yyDollar[3].showFilterUnion()}} } yyVAL.union = yyLOCAL - case 730: + case 732: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4030 +//line sql.y:4049 { yyLOCAL = &Show{&ShowBasic{Command: Keyspace, Filter: yyDollar[3].showFilterUnion()}} } yyVAL.union = yyLOCAL - case 731: + case 733: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4034 +//line sql.y:4053 { yyLOCAL = &Show{&ShowBasic{Command: Function, Filter: yyDollar[4].showFilterUnion()}} } yyVAL.union = yyLOCAL - case 732: + case 734: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:4038 +//line sql.y:4057 { yyLOCAL = &Show{&ShowBasic{Command: Index, Tbl: yyDollar[5].tableName, DbName: yyDollar[6].identifierCS, Filter: yyDollar[7].showFilterUnion()}} } yyVAL.union = yyLOCAL - case 733: + case 735: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:4042 +//line sql.y:4061 { yyLOCAL = &Show{&ShowBasic{Command: OpenTable, DbName: yyDollar[4].identifierCS, Filter: yyDollar[5].showFilterUnion()}} } yyVAL.union = yyLOCAL - case 734: + case 736: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4046 +//line sql.y:4065 { yyLOCAL = &Show{&ShowBasic{Command: Privilege}} } yyVAL.union = yyLOCAL - case 735: + case 737: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4050 +//line sql.y:4069 { yyLOCAL = &Show{&ShowBasic{Command: Procedure, Filter: yyDollar[4].showFilterUnion()}} } yyVAL.union = yyLOCAL - case 736: + case 738: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4054 +//line sql.y:4073 { yyLOCAL = &Show{&ShowBasic{Command: StatusSession, Filter: yyDollar[4].showFilterUnion()}} } yyVAL.union = yyLOCAL - case 737: + case 739: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4058 +//line sql.y:4077 { yyLOCAL = &Show{&ShowBasic{Command: StatusGlobal, Filter: yyDollar[4].showFilterUnion()}} } yyVAL.union = yyLOCAL - case 738: + case 740: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4062 +//line sql.y:4081 { yyLOCAL = &Show{&ShowBasic{Command: VariableSession, Filter: yyDollar[4].showFilterUnion()}} } yyVAL.union = yyLOCAL - case 739: + case 741: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4066 +//line sql.y:4085 { yyLOCAL = &Show{&ShowBasic{Command: VariableGlobal, Filter: yyDollar[4].showFilterUnion()}} } yyVAL.union = yyLOCAL - case 740: + case 742: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:4070 +//line sql.y:4089 { yyLOCAL = &Show{&ShowBasic{Command: TableStatus, DbName: yyDollar[4].identifierCS, Filter: yyDollar[5].showFilterUnion()}} } yyVAL.union = yyLOCAL - case 741: + case 743: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:4074 +//line sql.y:4093 { yyLOCAL = &Show{&ShowBasic{Command: Table, Full: yyDollar[2].booleanUnion(), DbName: yyDollar[4].identifierCS, Filter: yyDollar[5].showFilterUnion()}} } yyVAL.union = yyLOCAL - case 742: + case 744: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4078 +//line sql.y:4097 { yyLOCAL = &Show{&ShowBasic{Command: Trigger, DbName: yyDollar[3].identifierCS, Filter: yyDollar[4].showFilterUnion()}} } yyVAL.union = yyLOCAL - case 743: + case 745: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4082 +//line sql.y:4101 { yyLOCAL = &Show{&ShowCreate{Command: CreateDb, Op: yyDollar[4].tableName}} } yyVAL.union = yyLOCAL - case 744: + case 746: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4086 +//line sql.y:4105 { yyLOCAL = &Show{&ShowCreate{Command: CreateE, Op: yyDollar[4].tableName}} } yyVAL.union = yyLOCAL - case 745: + case 747: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4090 +//line sql.y:4109 { yyLOCAL = &Show{&ShowCreate{Command: CreateF, Op: yyDollar[4].tableName}} } yyVAL.union = yyLOCAL - case 746: + case 748: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4094 +//line sql.y:4113 { yyLOCAL = &Show{&ShowCreate{Command: CreateProc, Op: yyDollar[4].tableName}} } yyVAL.union = yyLOCAL - case 747: + case 749: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4098 +//line sql.y:4117 { yyLOCAL = &Show{&ShowCreate{Command: CreateTbl, Op: yyDollar[4].tableName}} } yyVAL.union = yyLOCAL - case 748: + case 750: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4102 +//line sql.y:4121 { yyLOCAL = &Show{&ShowCreate{Command: CreateTr, Op: yyDollar[4].tableName}} } yyVAL.union = yyLOCAL - case 749: + case 751: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4106 +//line sql.y:4125 { yyLOCAL = &Show{&ShowCreate{Command: CreateV, Op: yyDollar[4].tableName}} } yyVAL.union = yyLOCAL - case 750: + case 752: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4110 +//line sql.y:4129 { yyLOCAL = &Show{&ShowBasic{Command: Engines}} } yyVAL.union = yyLOCAL - case 751: + case 753: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4114 +//line sql.y:4133 { yyLOCAL = &Show{&ShowBasic{Command: Plugins}} } yyVAL.union = yyLOCAL - case 752: + case 754: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4118 +//line sql.y:4137 { yyLOCAL = &Show{&ShowBasic{Command: GtidExecGlobal, DbName: yyDollar[4].identifierCS}} } yyVAL.union = yyLOCAL - case 753: + case 755: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4122 +//line sql.y:4141 { yyLOCAL = &Show{&ShowBasic{Command: VGtidExecGlobal, DbName: yyDollar[4].identifierCS}} } yyVAL.union = yyLOCAL - case 754: + case 756: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4126 +//line sql.y:4145 { yyLOCAL = &Show{&ShowBasic{Command: VitessVariables, Filter: yyDollar[4].showFilterUnion()}} } yyVAL.union = yyLOCAL - case 755: + case 757: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4130 +//line sql.y:4149 { yyLOCAL = &Show{&ShowBasic{Command: VitessMigrations, Filter: yyDollar[4].showFilterUnion(), DbName: yyDollar[3].identifierCS}} } yyVAL.union = yyLOCAL - case 756: + case 758: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4134 +//line sql.y:4153 { yyLOCAL = &ShowMigrationLogs{UUID: string(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 757: + case 759: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4138 +//line sql.y:4157 { yyLOCAL = &ShowThrottledApps{} } yyVAL.union = yyLOCAL - case 758: + case 760: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4142 +//line sql.y:4161 { yyLOCAL = &Show{&ShowBasic{Command: VitessReplicationStatus, Filter: yyDollar[3].showFilterUnion()}} } yyVAL.union = yyLOCAL - case 759: + case 761: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4146 +//line sql.y:4165 { yyLOCAL = &ShowThrottlerStatus{} } yyVAL.union = yyLOCAL - case 760: + case 762: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4150 +//line sql.y:4169 { yyLOCAL = &Show{&ShowBasic{Command: VschemaTables}} } yyVAL.union = yyLOCAL - case 761: + case 763: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4154 +//line sql.y:4173 { yyLOCAL = &Show{&ShowBasic{Command: VschemaKeyspaces}} } yyVAL.union = yyLOCAL - case 762: + case 764: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4158 +//line sql.y:4177 { yyLOCAL = &Show{&ShowBasic{Command: VschemaVindexes}} } yyVAL.union = yyLOCAL - case 763: + case 765: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:4162 +//line sql.y:4181 { yyLOCAL = &Show{&ShowBasic{Command: VschemaVindexes, Tbl: yyDollar[5].tableName}} } yyVAL.union = yyLOCAL - case 764: + case 766: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4166 +//line sql.y:4185 { yyLOCAL = &Show{&ShowBasic{Command: Warnings}} } yyVAL.union = yyLOCAL - case 765: + case 767: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4170 +//line sql.y:4189 { yyLOCAL = &Show{&ShowBasic{Command: VitessShards, Filter: yyDollar[3].showFilterUnion()}} } yyVAL.union = yyLOCAL - case 766: + case 768: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4174 +//line sql.y:4193 { yyLOCAL = &Show{&ShowBasic{Command: VitessTablets, Filter: yyDollar[3].showFilterUnion()}} } yyVAL.union = yyLOCAL - case 767: + case 769: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4178 +//line sql.y:4197 { yyLOCAL = &Show{&ShowBasic{Command: VitessTarget}} } yyVAL.union = yyLOCAL - case 768: + case 770: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4185 +//line sql.y:4204 { yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[2].identifierCI.String())}} } yyVAL.union = yyLOCAL - case 769: + case 771: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4189 +//line sql.y:4208 { yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[2].str) + " " + string(yyDollar[3].str)}} } yyVAL.union = yyLOCAL - case 770: + case 772: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4193 +//line sql.y:4212 { yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[2].str) + " " + yyDollar[3].identifierCI.String()}} } yyVAL.union = yyLOCAL - case 771: + case 773: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4197 +//line sql.y:4216 { yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[2].str) + " " + string(yyDollar[3].str)}} } yyVAL.union = yyLOCAL - case 772: + case 774: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4201 +//line sql.y:4220 { yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[2].str)}} } yyVAL.union = yyLOCAL - case 773: + case 775: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4205 +//line sql.y:4224 { yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[2].str) + " " + string(yyDollar[3].str) + " " + String(yyDollar[4].tableName)}} } yyVAL.union = yyLOCAL - case 774: + case 776: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4209 +//line sql.y:4228 { yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[2].str) + " " + string(yyDollar[3].str) + " " + String(yyDollar[4].tableName)}} } yyVAL.union = yyLOCAL - case 775: + case 777: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:4213 +//line sql.y:4232 { yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[3].str)}} } yyVAL.union = yyLOCAL - case 776: + case 778: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4217 +//line sql.y:4236 { yyLOCAL = &Show{&ShowOther{Command: string(yyDollar[2].str)}} } yyVAL.union = yyLOCAL - case 777: + case 779: + yyDollar = yyS[yypt-5 : yypt+1] + var yyLOCAL Statement +//line sql.y:4240 + { + yyLOCAL = &Show{&ShowTransactionStatus{TransactionID: string(yyDollar[5].str)}} + } + yyVAL.union = yyLOCAL + case 780: + yyDollar = yyS[yypt-0 : yypt+1] +//line sql.y:4245 + { + } + case 781: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:4247 + { + } + case 782: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4223 +//line sql.y:4251 { yyVAL.str = "" } - case 778: + case 783: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4227 +//line sql.y:4255 { yyVAL.str = "extended " } - case 779: + case 784: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:4233 +//line sql.y:4261 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 780: + case 785: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:4237 +//line sql.y:4265 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 781: + case 786: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4243 +//line sql.y:4271 { yyVAL.str = string(yyDollar[1].str) } - case 782: + case 787: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4247 +//line sql.y:4275 { yyVAL.str = string(yyDollar[1].str) } - case 783: + case 788: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4253 +//line sql.y:4281 { yyVAL.identifierCS = NewIdentifierCS("") } - case 784: + case 789: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4257 +//line sql.y:4285 { yyVAL.identifierCS = yyDollar[2].identifierCS } - case 785: + case 790: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4261 +//line sql.y:4289 { yyVAL.identifierCS = yyDollar[2].identifierCS } - case 786: + case 791: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ShowFilter -//line sql.y:4267 +//line sql.y:4295 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 787: + case 792: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ShowFilter -//line sql.y:4271 +//line sql.y:4299 { yyLOCAL = &ShowFilter{Like: string(yyDollar[2].str)} } yyVAL.union = yyLOCAL - case 788: + case 793: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ShowFilter -//line sql.y:4275 +//line sql.y:4303 { yyLOCAL = &ShowFilter{Filter: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 789: + case 794: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ShowFilter -//line sql.y:4281 +//line sql.y:4309 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 790: + case 795: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ShowFilter -//line sql.y:4285 +//line sql.y:4313 { yyLOCAL = &ShowFilter{Like: string(yyDollar[2].str)} } yyVAL.union = yyLOCAL - case 791: + case 796: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4291 +//line sql.y:4319 { yyVAL.empty = struct{}{} } - case 792: + case 797: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4295 +//line sql.y:4323 { yyVAL.empty = struct{}{} } - case 793: + case 798: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4299 +//line sql.y:4327 { yyVAL.empty = struct{}{} } - case 794: + case 799: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4305 +//line sql.y:4333 { yyVAL.str = string(yyDollar[1].str) } - case 795: + case 800: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4309 +//line sql.y:4337 { yyVAL.str = string(yyDollar[1].str) } - case 796: + case 801: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4315 +//line sql.y:4343 { yyLOCAL = &Use{DBName: yyDollar[2].identifierCS} } yyVAL.union = yyLOCAL - case 797: + case 802: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4319 +//line sql.y:4347 { yyLOCAL = &Use{DBName: IdentifierCS{v: ""}} } yyVAL.union = yyLOCAL - case 798: + case 803: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4323 +//line sql.y:4351 { yyLOCAL = &Use{DBName: NewIdentifierCS(yyDollar[2].identifierCS.String() + "@" + string(yyDollar[3].str))} } yyVAL.union = yyLOCAL - case 799: + case 804: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4330 +//line sql.y:4358 { yyVAL.identifierCS = NewIdentifierCS(string(yyDollar[1].str)) } - case 800: + case 805: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4334 +//line sql.y:4362 { yyVAL.identifierCS = NewIdentifierCS("@" + string(yyDollar[1].str)) } - case 801: + case 806: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4338 +//line sql.y:4366 { yyVAL.identifierCS = NewIdentifierCS("@@" + string(yyDollar[1].str)) } - case 802: + case 807: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4342 +//line sql.y:4370 { yyVAL.identifierCS = NewIdentifierCS(string(yyDollar[1].str)) } - case 803: + case 808: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4349 +//line sql.y:4377 { yyLOCAL = &Begin{} } yyVAL.union = yyLOCAL - case 804: + case 809: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4353 +//line sql.y:4381 { yyLOCAL = &Begin{TxAccessModes: yyDollar[3].txAccessModesUnion()} } yyVAL.union = yyLOCAL - case 805: + case 810: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []TxAccessMode -//line sql.y:4358 +//line sql.y:4386 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 806: + case 811: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []TxAccessMode -//line sql.y:4362 +//line sql.y:4390 { yyLOCAL = yyDollar[1].txAccessModesUnion() } yyVAL.union = yyLOCAL - case 807: + case 812: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []TxAccessMode -//line sql.y:4368 +//line sql.y:4396 { yyLOCAL = []TxAccessMode{yyDollar[1].txAccessModeUnion()} } yyVAL.union = yyLOCAL - case 808: + case 813: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4372 +//line sql.y:4400 { yySLICE := (*[]TxAccessMode)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].txAccessModeUnion()) } - case 809: + case 814: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL TxAccessMode -//line sql.y:4378 +//line sql.y:4406 { yyLOCAL = WithConsistentSnapshot } yyVAL.union = yyLOCAL - case 810: + case 815: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL TxAccessMode -//line sql.y:4382 +//line sql.y:4410 { yyLOCAL = ReadWrite } yyVAL.union = yyLOCAL - case 811: + case 816: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL TxAccessMode -//line sql.y:4386 +//line sql.y:4414 { yyLOCAL = ReadOnly } yyVAL.union = yyLOCAL - case 812: + case 817: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4393 +//line sql.y:4421 { yyLOCAL = &Commit{} } yyVAL.union = yyLOCAL - case 813: + case 818: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4399 +//line sql.y:4427 { yyLOCAL = &Rollback{} } yyVAL.union = yyLOCAL - case 814: + case 819: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:4403 +//line sql.y:4431 { yyLOCAL = &SRollback{Name: yyDollar[5].identifierCI} } yyVAL.union = yyLOCAL - case 815: + case 820: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4408 +//line sql.y:4436 { yyVAL.empty = struct{}{} } - case 816: + case 821: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4410 +//line sql.y:4438 { yyVAL.empty = struct{}{} } - case 817: + case 822: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4413 +//line sql.y:4441 { yyVAL.empty = struct{}{} } - case 818: + case 823: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4415 +//line sql.y:4443 { yyVAL.empty = struct{}{} } - case 819: + case 824: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4419 +//line sql.y:4447 { yyLOCAL = &Savepoint{Name: yyDollar[2].identifierCI} } yyVAL.union = yyLOCAL - case 820: + case 825: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4425 +//line sql.y:4453 { yyLOCAL = &Release{Name: yyDollar[3].identifierCI} } yyVAL.union = yyLOCAL - case 821: + case 826: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL ExplainType -//line sql.y:4430 +//line sql.y:4458 { yyLOCAL = EmptyType } yyVAL.union = yyLOCAL - case 822: + case 827: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL ExplainType -//line sql.y:4434 +//line sql.y:4462 { yyLOCAL = JSONType } yyVAL.union = yyLOCAL - case 823: + case 828: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL ExplainType -//line sql.y:4438 +//line sql.y:4466 { yyLOCAL = TreeType } yyVAL.union = yyLOCAL - case 824: + case 829: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL ExplainType -//line sql.y:4442 +//line sql.y:4470 { yyLOCAL = TraditionalType } yyVAL.union = yyLOCAL - case 825: + case 830: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ExplainType -//line sql.y:4446 +//line sql.y:4474 { yyLOCAL = AnalyzeType } yyVAL.union = yyLOCAL - case 826: + case 831: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL VExplainType -//line sql.y:4451 +//line sql.y:4479 { yyLOCAL = PlanVExplainType } yyVAL.union = yyLOCAL - case 827: + case 832: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL VExplainType -//line sql.y:4455 +//line sql.y:4483 { yyLOCAL = PlanVExplainType } yyVAL.union = yyLOCAL - case 828: + case 833: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL VExplainType -//line sql.y:4459 +//line sql.y:4487 { yyLOCAL = AllVExplainType } yyVAL.union = yyLOCAL - case 829: + case 834: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL VExplainType -//line sql.y:4463 +//line sql.y:4491 { yyLOCAL = QueriesVExplainType } yyVAL.union = yyLOCAL - case 830: + case 835: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4469 +//line sql.y:4497 { yyVAL.str = yyDollar[1].str } - case 831: + case 836: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4473 +//line sql.y:4501 { yyVAL.str = yyDollar[1].str } - case 832: + case 837: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4477 +//line sql.y:4505 { yyVAL.str = yyDollar[1].str } - case 833: + case 838: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4483 +//line sql.y:4511 { yyLOCAL = yyDollar[1].selStmtUnion() } yyVAL.union = yyLOCAL - case 834: + case 839: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4487 +//line sql.y:4515 { yyLOCAL = yyDollar[1].statementUnion() } yyVAL.union = yyLOCAL - case 835: + case 840: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4491 +//line sql.y:4519 { yyLOCAL = yyDollar[1].statementUnion() } yyVAL.union = yyLOCAL - case 836: + case 841: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Statement -//line sql.y:4495 +//line sql.y:4523 { yyLOCAL = yyDollar[1].statementUnion() } yyVAL.union = yyLOCAL - case 837: + case 842: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4500 +//line sql.y:4528 { yyVAL.str = "" } - case 838: + case 843: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4504 +//line sql.y:4532 { yyVAL.str = yyDollar[1].identifierCI.val } - case 839: + case 844: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4508 +//line sql.y:4536 { yyVAL.str = encodeSQLString(yyDollar[1].str) } - case 840: + case 845: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4514 +//line sql.y:4542 { yyLOCAL = &ExplainTab{Table: yyDollar[3].tableName, Wild: yyDollar[4].str} } yyVAL.union = yyLOCAL - case 841: + case 846: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4518 +//line sql.y:4546 { yyLOCAL = &ExplainStmt{Type: yyDollar[3].explainTypeUnion(), Statement: yyDollar[4].statementUnion(), Comments: Comments(yyDollar[2].strs).Parsed()} } yyVAL.union = yyLOCAL - case 842: + case 847: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4524 +//line sql.y:4552 { yyLOCAL = &VExplainStmt{Type: yyDollar[3].vexplainTypeUnion(), Statement: yyDollar[4].statementUnion(), Comments: Comments(yyDollar[2].strs).Parsed()} } yyVAL.union = yyLOCAL - case 843: + case 848: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4530 +//line sql.y:4558 { yyLOCAL = &OtherAdmin{} } yyVAL.union = yyLOCAL - case 844: + case 849: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4534 +//line sql.y:4562 { yyLOCAL = &OtherAdmin{} } yyVAL.union = yyLOCAL - case 845: + case 850: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4540 +//line sql.y:4568 { yyLOCAL = &LockTables{Tables: yyDollar[3].tableAndLockTypesUnion()} } yyVAL.union = yyLOCAL - case 846: + case 851: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableAndLockTypes -//line sql.y:4546 +//line sql.y:4574 { yyLOCAL = TableAndLockTypes{yyDollar[1].tableAndLockTypeUnion()} } yyVAL.union = yyLOCAL - case 847: + case 852: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4550 +//line sql.y:4578 { yySLICE := (*TableAndLockTypes)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].tableAndLockTypeUnion()) } - case 848: + case 853: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *TableAndLockType -//line sql.y:4556 +//line sql.y:4584 { yyLOCAL = &TableAndLockType{Table: yyDollar[1].aliasedTableNameUnion(), Lock: yyDollar[2].lockTypeUnion()} } yyVAL.union = yyLOCAL - case 849: + case 854: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL LockType -//line sql.y:4562 +//line sql.y:4590 { yyLOCAL = Read } yyVAL.union = yyLOCAL - case 850: + case 855: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL LockType -//line sql.y:4566 +//line sql.y:4594 { yyLOCAL = ReadLocal } yyVAL.union = yyLOCAL - case 851: + case 856: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL LockType -//line sql.y:4570 +//line sql.y:4598 { yyLOCAL = Write } yyVAL.union = yyLOCAL - case 852: + case 857: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL LockType -//line sql.y:4574 +//line sql.y:4602 { yyLOCAL = LowPriorityWrite } yyVAL.union = yyLOCAL - case 853: + case 858: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Statement -//line sql.y:4580 +//line sql.y:4608 { yyLOCAL = &UnlockTables{} } yyVAL.union = yyLOCAL - case 854: + case 859: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4586 +//line sql.y:4614 { yyLOCAL = &RevertMigration{Comments: Comments(yyDollar[2].strs).Parsed(), UUID: string(yyDollar[4].str)} } yyVAL.union = yyLOCAL - case 855: + case 860: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4592 +//line sql.y:4620 { yyLOCAL = &Flush{IsLocal: yyDollar[2].booleanUnion(), FlushOptions: yyDollar[3].strs} } yyVAL.union = yyLOCAL - case 856: + case 861: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:4596 +//line sql.y:4624 { yyLOCAL = &Flush{IsLocal: yyDollar[2].booleanUnion()} } yyVAL.union = yyLOCAL - case 857: + case 862: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:4600 +//line sql.y:4628 { yyLOCAL = &Flush{IsLocal: yyDollar[2].booleanUnion(), WithLock: true} } yyVAL.union = yyLOCAL - case 858: + case 863: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4604 +//line sql.y:4632 { yyLOCAL = &Flush{IsLocal: yyDollar[2].booleanUnion(), TableNames: yyDollar[4].tableNamesUnion()} } yyVAL.union = yyLOCAL - case 859: + case 864: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Statement -//line sql.y:4608 +//line sql.y:4636 { yyLOCAL = &Flush{IsLocal: yyDollar[2].booleanUnion(), TableNames: yyDollar[4].tableNamesUnion(), WithLock: true} } yyVAL.union = yyLOCAL - case 860: + case 865: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Statement -//line sql.y:4612 +//line sql.y:4640 { yyLOCAL = &Flush{IsLocal: yyDollar[2].booleanUnion(), TableNames: yyDollar[4].tableNamesUnion(), ForExport: true} } yyVAL.union = yyLOCAL - case 861: + case 866: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4618 +//line sql.y:4646 { yyVAL.strs = []string{yyDollar[1].str} } - case 862: + case 867: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4622 +//line sql.y:4650 { yyVAL.strs = append(yyDollar[1].strs, yyDollar[3].str) } - case 863: + case 868: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4628 +//line sql.y:4656 { yyVAL.str = string(yyDollar[1].str) + " " + string(yyDollar[2].str) } - case 864: + case 869: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4632 +//line sql.y:4660 { yyVAL.str = string(yyDollar[1].str) + " " + string(yyDollar[2].str) } - case 865: + case 870: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4636 +//line sql.y:4664 { yyVAL.str = string(yyDollar[1].str) + " " + string(yyDollar[2].str) } - case 866: + case 871: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4640 +//line sql.y:4668 { yyVAL.str = string(yyDollar[1].str) + " " + string(yyDollar[2].str) } - case 867: + case 872: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4644 +//line sql.y:4672 { yyVAL.str = string(yyDollar[1].str) } - case 868: + case 873: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4648 +//line sql.y:4676 { yyVAL.str = string(yyDollar[1].str) } - case 869: + case 874: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4652 +//line sql.y:4680 { yyVAL.str = string(yyDollar[1].str) } - case 870: + case 875: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4656 +//line sql.y:4684 { yyVAL.str = string(yyDollar[1].str) + " " + string(yyDollar[2].str) + yyDollar[3].str } - case 871: + case 876: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4660 +//line sql.y:4688 { yyVAL.str = string(yyDollar[1].str) + " " + string(yyDollar[2].str) } - case 872: + case 877: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4664 +//line sql.y:4692 { yyVAL.str = string(yyDollar[1].str) } - case 873: + case 878: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4668 +//line sql.y:4696 { yyVAL.str = string(yyDollar[1].str) } - case 874: + case 879: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4672 +//line sql.y:4700 { yyVAL.str = string(yyDollar[1].str) } - case 875: + case 880: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:4677 +//line sql.y:4705 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 876: + case 881: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:4681 +//line sql.y:4709 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 877: + case 882: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:4685 +//line sql.y:4713 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 878: + case 883: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4690 +//line sql.y:4718 { yyVAL.str = "" } - case 879: + case 884: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4694 +//line sql.y:4722 { yyVAL.str = " " + string(yyDollar[1].str) + " " + string(yyDollar[2].str) + " " + yyDollar[3].identifierCI.String() } - case 880: + case 885: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4699 +//line sql.y:4727 { setAllowComments(yylex, true) } - case 881: + case 886: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4703 +//line sql.y:4731 { yyVAL.strs = yyDollar[2].strs setAllowComments(yylex, false) } - case 882: + case 887: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4709 +//line sql.y:4737 { yyVAL.strs = nil } - case 883: + case 888: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4713 +//line sql.y:4741 { yyVAL.strs = append(yyDollar[1].strs, yyDollar[2].str) } - case 884: + case 889: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:4719 +//line sql.y:4747 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 885: + case 890: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:4723 +//line sql.y:4751 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 886: + case 891: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:4727 +//line sql.y:4755 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 887: + case 892: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4732 +//line sql.y:4760 { yyVAL.str = "" } - case 888: + case 893: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4736 +//line sql.y:4764 { yyVAL.str = SQLNoCacheStr } - case 889: + case 894: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4740 +//line sql.y:4768 { yyVAL.str = SQLCacheStr } - case 890: + case 895: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:4745 +//line sql.y:4773 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 891: + case 896: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:4749 +//line sql.y:4777 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 892: + case 897: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:4753 +//line sql.y:4781 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 893: + case 898: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:4759 +//line sql.y:4787 { yyLOCAL = &PrepareStmt{Name: yyDollar[3].identifierCI, Comments: Comments(yyDollar[2].strs).Parsed(), Statement: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 894: + case 899: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:4763 +//line sql.y:4791 { yyLOCAL = &PrepareStmt{ Name: yyDollar[3].identifierCI, @@ -16791,573 +16865,597 @@ yydefault: } } yyVAL.union = yyLOCAL - case 895: + case 900: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4773 +//line sql.y:4801 { yyLOCAL = &ExecuteStmt{Name: yyDollar[3].identifierCI, Comments: Comments(yyDollar[2].strs).Parsed(), Arguments: yyDollar[4].variablesUnion()} } yyVAL.union = yyLOCAL - case 896: + case 901: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*Variable -//line sql.y:4778 +//line sql.y:4806 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 897: + case 902: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []*Variable -//line sql.y:4782 +//line sql.y:4810 { yyLOCAL = yyDollar[2].variablesUnion() } yyVAL.union = yyLOCAL - case 898: + case 903: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4788 +//line sql.y:4816 { yyLOCAL = &DeallocateStmt{Comments: Comments(yyDollar[2].strs).Parsed(), Name: yyDollar[4].identifierCI} } yyVAL.union = yyLOCAL - case 899: + case 904: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Statement -//line sql.y:4792 +//line sql.y:4820 { yyLOCAL = &DeallocateStmt{Comments: Comments(yyDollar[2].strs).Parsed(), Name: yyDollar[4].identifierCI} } yyVAL.union = yyLOCAL - case 900: + case 905: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4797 +//line sql.y:4825 { yyVAL.strs = nil } - case 901: + case 906: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4801 +//line sql.y:4829 { yyVAL.strs = yyDollar[1].strs } - case 902: + case 907: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4807 +//line sql.y:4835 { yyVAL.strs = []string{yyDollar[1].str} } - case 903: + case 908: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4811 +//line sql.y:4839 { yyVAL.strs = append(yyDollar[1].strs, yyDollar[2].str) } - case 904: + case 909: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4817 +//line sql.y:4845 { yyVAL.str = SQLNoCacheStr } - case 905: + case 910: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4821 +//line sql.y:4849 { yyVAL.str = SQLCacheStr } - case 906: + case 911: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4825 +//line sql.y:4853 { yyVAL.str = DistinctStr } - case 907: + case 912: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4829 +//line sql.y:4857 { yyVAL.str = DistinctStr } - case 908: + case 913: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:4861 + { + yyVAL.str = HighPriorityStr + } + case 914: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4833 +//line sql.y:4865 { yyVAL.str = StraightJoinHint } - case 909: + case 915: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:4869 + { + yyVAL.str = SQLBufferResultStr + } + case 916: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:4873 + { + yyVAL.str = SQLSmallResultStr + } + case 917: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:4877 + { + yyVAL.str = SQLBigResultStr + } + case 918: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4837 +//line sql.y:4881 { yyVAL.str = SQLCalcFoundRowsStr } - case 910: + case 919: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4841 +//line sql.y:4885 { 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 911: + case 920: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL SelectExprs -//line sql.y:4847 +//line sql.y:4891 { yyLOCAL = SelectExprs{yyDollar[1].selectExprUnion()} } yyVAL.union = yyLOCAL - case 912: + case 921: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4851 +//line sql.y:4895 { yySLICE := (*SelectExprs)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].selectExprUnion()) } - case 913: + case 922: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL SelectExpr -//line sql.y:4857 +//line sql.y:4901 { yyLOCAL = &StarExpr{} } yyVAL.union = yyLOCAL - case 914: + case 923: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL SelectExpr -//line sql.y:4861 +//line sql.y:4905 { yyLOCAL = &AliasedExpr{Expr: yyDollar[1].exprUnion(), As: yyDollar[2].identifierCI} } yyVAL.union = yyLOCAL - case 915: + case 924: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL SelectExpr -//line sql.y:4865 +//line sql.y:4909 { yyLOCAL = &StarExpr{TableName: TableName{Name: yyDollar[1].identifierCS}} } yyVAL.union = yyLOCAL - case 916: + case 925: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL SelectExpr -//line sql.y:4869 +//line sql.y:4913 { yyLOCAL = &StarExpr{TableName: TableName{Qualifier: yyDollar[1].identifierCS, Name: yyDollar[3].identifierCS}} } yyVAL.union = yyLOCAL - case 917: + case 926: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4874 +//line sql.y:4918 { yyVAL.identifierCI = IdentifierCI{} } - case 918: + case 927: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4878 +//line sql.y:4922 { yyVAL.identifierCI = yyDollar[1].identifierCI } - case 919: + case 928: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4882 +//line sql.y:4926 { yyVAL.identifierCI = yyDollar[2].identifierCI } - case 921: + case 930: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4889 +//line sql.y:4933 { yyVAL.identifierCI = NewIdentifierCI(string(yyDollar[1].str)) } - case 922: + case 931: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL TableExprs -//line sql.y:4894 +//line sql.y:4938 { yyLOCAL = TableExprs{&AliasedTableExpr{Expr: TableName{Name: NewIdentifierCS("dual")}}} } yyVAL.union = yyLOCAL - case 923: + case 932: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableExprs -//line sql.y:4898 +//line sql.y:4942 { yyLOCAL = yyDollar[1].tableExprsUnion() } yyVAL.union = yyLOCAL - case 924: + case 933: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL TableExprs -//line sql.y:4904 +//line sql.y:4948 { yyLOCAL = yyDollar[2].tableExprsUnion() } yyVAL.union = yyLOCAL - case 925: + case 934: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableExprs -//line sql.y:4910 +//line sql.y:4954 { yyLOCAL = TableExprs{yyDollar[1].tableExprUnion()} } yyVAL.union = yyLOCAL - case 926: + case 935: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4914 +//line sql.y:4958 { yySLICE := (*TableExprs)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].tableExprUnion()) } - case 929: + case 938: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableExpr -//line sql.y:4924 +//line sql.y:4968 { yyLOCAL = yyDollar[1].aliasedTableNameUnion() } yyVAL.union = yyLOCAL - case 930: + case 939: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL TableExpr -//line sql.y:4928 +//line sql.y:4972 { yyLOCAL = &AliasedTableExpr{Expr: yyDollar[1].derivedTableUnion(), As: yyDollar[3].identifierCS, Columns: yyDollar[4].columnsUnion()} } yyVAL.union = yyLOCAL - case 931: + case 940: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL TableExpr -//line sql.y:4932 +//line sql.y:4976 { yyLOCAL = &ParenTableExpr{Exprs: yyDollar[2].tableExprsUnion()} } yyVAL.union = yyLOCAL - case 932: + case 941: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TableExpr -//line sql.y:4936 +//line sql.y:4980 { yyLOCAL = yyDollar[1].tableExprUnion() } yyVAL.union = yyLOCAL - case 933: + case 942: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *DerivedTable -//line sql.y:4942 +//line sql.y:4986 { yyLOCAL = &DerivedTable{Lateral: false, Select: yyDollar[1].selStmtUnion()} } yyVAL.union = yyLOCAL - case 934: + case 943: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *DerivedTable -//line sql.y:4946 +//line sql.y:4990 { yyLOCAL = &DerivedTable{Lateral: true, Select: yyDollar[2].selStmtUnion()} } yyVAL.union = yyLOCAL - case 935: + case 944: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *AliasedTableExpr -//line sql.y:4952 +//line sql.y:4996 { yyLOCAL = &AliasedTableExpr{Expr: yyDollar[1].tableName, As: yyDollar[2].identifierCS, Hints: yyDollar[3].indexHintsUnion()} } yyVAL.union = yyLOCAL - case 936: + case 945: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *AliasedTableExpr -//line sql.y:4956 +//line sql.y:5000 { yyLOCAL = &AliasedTableExpr{Expr: yyDollar[1].tableName, Partitions: yyDollar[4].partitionsUnion(), As: yyDollar[6].identifierCS, Hints: yyDollar[7].indexHintsUnion()} } yyVAL.union = yyLOCAL - case 937: + case 946: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Columns -//line sql.y:4961 +//line sql.y:5005 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 938: + case 947: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Columns -//line sql.y:4965 +//line sql.y:5009 { yyLOCAL = yyDollar[2].columnsUnion() } yyVAL.union = yyLOCAL - case 939: + case 948: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Columns -//line sql.y:4970 +//line sql.y:5014 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 940: + case 949: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Columns -//line sql.y:4974 +//line sql.y:5018 { yyLOCAL = yyDollar[1].columnsUnion() } yyVAL.union = yyLOCAL - case 941: + case 950: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Columns -//line sql.y:4980 +//line sql.y:5024 { yyLOCAL = Columns{yyDollar[1].identifierCI} } yyVAL.union = yyLOCAL - case 942: + case 951: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4984 +//line sql.y:5028 { yySLICE := (*Columns)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].identifierCI) } - case 943: + case 952: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*Variable -//line sql.y:4990 +//line sql.y:5034 { yyLOCAL = []*Variable{yyDollar[1].variableUnion()} } yyVAL.union = yyLOCAL - case 944: + case 953: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4994 +//line sql.y:5038 { yySLICE := (*[]*Variable)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].variableUnion()) } - case 945: + case 954: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Columns -//line sql.y:5000 +//line sql.y:5044 { yyLOCAL = Columns{yyDollar[1].identifierCI} } yyVAL.union = yyLOCAL - case 946: + case 955: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Columns -//line sql.y:5004 +//line sql.y:5048 { yyLOCAL = Columns{NewIdentifierCI(string(yyDollar[1].str))} } yyVAL.union = yyLOCAL - case 947: + case 956: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5008 +//line sql.y:5052 { yySLICE := (*Columns)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].identifierCI) } - case 948: + case 957: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5012 +//line sql.y:5056 { yySLICE := (*Columns)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, NewIdentifierCI(string(yyDollar[3].str))) } - case 949: + case 958: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Partitions -//line sql.y:5018 +//line sql.y:5062 { yyLOCAL = Partitions{yyDollar[1].identifierCI} } yyVAL.union = yyLOCAL - case 950: + case 959: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5022 +//line sql.y:5066 { yySLICE := (*Partitions)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].identifierCI) } - case 951: + case 960: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL TableExpr -//line sql.y:5035 +//line sql.y:5079 { yyLOCAL = &JoinTableExpr{LeftExpr: yyDollar[1].tableExprUnion(), Join: yyDollar[2].joinTypeUnion(), RightExpr: yyDollar[3].tableExprUnion(), Condition: yyDollar[4].joinCondition} } yyVAL.union = yyLOCAL - case 952: + case 961: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL TableExpr -//line sql.y:5039 +//line sql.y:5083 { yyLOCAL = &JoinTableExpr{LeftExpr: yyDollar[1].tableExprUnion(), Join: yyDollar[2].joinTypeUnion(), RightExpr: yyDollar[3].tableExprUnion(), Condition: yyDollar[4].joinCondition} } yyVAL.union = yyLOCAL - case 953: + case 962: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL TableExpr -//line sql.y:5043 +//line sql.y:5087 { yyLOCAL = &JoinTableExpr{LeftExpr: yyDollar[1].tableExprUnion(), Join: yyDollar[2].joinTypeUnion(), RightExpr: yyDollar[3].tableExprUnion(), Condition: yyDollar[4].joinCondition} } yyVAL.union = yyLOCAL - case 954: + case 963: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL TableExpr -//line sql.y:5047 +//line sql.y:5091 { yyLOCAL = &JoinTableExpr{LeftExpr: yyDollar[1].tableExprUnion(), Join: yyDollar[2].joinTypeUnion(), RightExpr: yyDollar[3].tableExprUnion()} } yyVAL.union = yyLOCAL - case 955: + case 964: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:5053 +//line sql.y:5097 { yyVAL.joinCondition = &JoinCondition{On: yyDollar[2].exprUnion()} } - case 956: + case 965: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:5055 +//line sql.y:5099 { yyVAL.joinCondition = &JoinCondition{Using: yyDollar[3].columnsUnion()} } - case 957: + case 966: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:5059 +//line sql.y:5103 { yyVAL.joinCondition = &JoinCondition{} } - case 958: + case 967: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5061 +//line sql.y:5105 { yyVAL.joinCondition = yyDollar[1].joinCondition } - case 959: + case 968: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:5065 +//line sql.y:5109 { yyVAL.joinCondition = &JoinCondition{} } - case 960: + case 969: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:5067 +//line sql.y:5111 { yyVAL.joinCondition = &JoinCondition{On: yyDollar[2].exprUnion()} } - case 961: + case 970: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:5070 +//line sql.y:5114 { yyVAL.empty = struct{}{} } - case 962: + case 971: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5072 +//line sql.y:5116 { yyVAL.empty = struct{}{} } - case 963: + case 972: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:5075 +//line sql.y:5119 { yyVAL.identifierCS = NewIdentifierCS("") } - case 964: + case 973: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5079 +//line sql.y:5123 { yyVAL.identifierCS = yyDollar[1].identifierCS } - case 965: + case 974: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:5083 +//line sql.y:5127 { yyVAL.identifierCS = yyDollar[2].identifierCS } - case 967: + case 976: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5090 +//line sql.y:5134 { yyVAL.identifierCS = NewIdentifierCS(string(yyDollar[1].str)) } - case 968: + case 977: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL JoinType -//line sql.y:5096 +//line sql.y:5140 { yyLOCAL = NormalJoinType } yyVAL.union = yyLOCAL - case 969: + case 978: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL JoinType -//line sql.y:5100 +//line sql.y:5144 { yyLOCAL = NormalJoinType } yyVAL.union = yyLOCAL - case 970: + case 979: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL JoinType -//line sql.y:5104 +//line sql.y:5148 { yyLOCAL = NormalJoinType } yyVAL.union = yyLOCAL - case 971: + case 980: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL JoinType -//line sql.y:5110 +//line sql.y:5154 { yyLOCAL = StraightJoinType } yyVAL.union = yyLOCAL - case 972: + case 981: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL JoinType -//line sql.y:5116 +//line sql.y:5160 { yyLOCAL = LeftJoinType } yyVAL.union = yyLOCAL - case 973: + case 982: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL JoinType -//line sql.y:5120 +//line sql.y:5164 { yyLOCAL = LeftJoinType } yyVAL.union = yyLOCAL - case 974: + case 983: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL JoinType -//line sql.y:5124 +//line sql.y:5168 { yyLOCAL = RightJoinType } yyVAL.union = yyLOCAL - case 975: + case 984: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL JoinType -//line sql.y:5128 +//line sql.y:5172 { yyLOCAL = RightJoinType } yyVAL.union = yyLOCAL - case 976: + case 985: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL JoinType -//line sql.y:5134 +//line sql.y:5178 { yyLOCAL = NaturalJoinType } yyVAL.union = yyLOCAL - case 977: + case 986: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL JoinType -//line sql.y:5138 +//line sql.y:5182 { if yyDollar[2].joinTypeUnion() == LeftJoinType { yyLOCAL = NaturalLeftJoinType @@ -17366,667 +17464,667 @@ yydefault: } } yyVAL.union = yyLOCAL - case 978: + case 987: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:5148 +//line sql.y:5192 { yyVAL.tableName = yyDollar[2].tableName } - case 979: + case 988: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5152 +//line sql.y:5196 { yyVAL.tableName = yyDollar[1].tableName } - case 980: + case 989: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5158 +//line sql.y:5202 { yyVAL.tableName = TableName{Name: yyDollar[1].identifierCS} } - case 981: + case 990: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5162 +//line sql.y:5206 { yyVAL.tableName = TableName{Qualifier: yyDollar[1].identifierCS, Name: yyDollar[3].identifierCS} } - case 982: + case 991: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5168 +//line sql.y:5212 { yyVAL.tableName = TableName{Name: yyDollar[1].identifierCS} } - case 983: + case 992: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL IndexHints -//line sql.y:5173 +//line sql.y:5217 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 984: + case 993: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IndexHints -//line sql.y:5177 +//line sql.y:5221 { yyLOCAL = yyDollar[1].indexHintsUnion() } yyVAL.union = yyLOCAL - case 985: + case 994: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IndexHints -//line sql.y:5183 +//line sql.y:5227 { yyLOCAL = IndexHints{yyDollar[1].indexHintUnion()} } yyVAL.union = yyLOCAL - case 986: + case 995: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:5187 +//line sql.y:5231 { yySLICE := (*IndexHints)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[2].indexHintUnion()) } - case 987: + case 996: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *IndexHint -//line sql.y:5193 +//line sql.y:5237 { yyLOCAL = &IndexHint{Type: UseOp, ForType: yyDollar[3].indexHintForTypeUnion(), Indexes: yyDollar[5].columnsUnion()} } yyVAL.union = yyLOCAL - case 988: + case 997: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *IndexHint -//line sql.y:5197 +//line sql.y:5241 { yyLOCAL = &IndexHint{Type: UseOp, ForType: yyDollar[3].indexHintForTypeUnion()} } yyVAL.union = yyLOCAL - case 989: + case 998: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *IndexHint -//line sql.y:5201 +//line sql.y:5245 { yyLOCAL = &IndexHint{Type: IgnoreOp, ForType: yyDollar[3].indexHintForTypeUnion(), Indexes: yyDollar[5].columnsUnion()} } yyVAL.union = yyLOCAL - case 990: + case 999: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *IndexHint -//line sql.y:5205 +//line sql.y:5249 { yyLOCAL = &IndexHint{Type: ForceOp, ForType: yyDollar[3].indexHintForTypeUnion(), Indexes: yyDollar[5].columnsUnion()} } yyVAL.union = yyLOCAL - case 991: + case 1000: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *IndexHint -//line sql.y:5209 +//line sql.y:5253 { yyLOCAL = &IndexHint{Type: UseVindexOp, Indexes: yyDollar[4].columnsUnion()} } yyVAL.union = yyLOCAL - case 992: + case 1001: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *IndexHint -//line sql.y:5213 +//line sql.y:5257 { yyLOCAL = &IndexHint{Type: IgnoreVindexOp, Indexes: yyDollar[4].columnsUnion()} } yyVAL.union = yyLOCAL - case 993: + case 1002: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL IndexHintForType -//line sql.y:5218 +//line sql.y:5262 { yyLOCAL = NoForType } yyVAL.union = yyLOCAL - case 994: + case 1003: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL IndexHintForType -//line sql.y:5222 +//line sql.y:5266 { yyLOCAL = JoinForType } yyVAL.union = yyLOCAL - case 995: + case 1004: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL IndexHintForType -//line sql.y:5226 +//line sql.y:5270 { yyLOCAL = OrderByForType } yyVAL.union = yyLOCAL - case 996: + case 1005: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL IndexHintForType -//line sql.y:5230 +//line sql.y:5274 { yyLOCAL = GroupByForType } yyVAL.union = yyLOCAL - case 997: + case 1006: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Expr -//line sql.y:5236 +//line sql.y:5280 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 998: + case 1007: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5240 +//line sql.y:5284 { yyLOCAL = yyDollar[2].exprUnion() } yyVAL.union = yyLOCAL - case 999: + case 1008: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5247 +//line sql.y:5291 { yyLOCAL = &OrExpr{Left: yyDollar[1].exprUnion(), Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1000: + case 1009: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5251 +//line sql.y:5295 { yyLOCAL = &XorExpr{Left: yyDollar[1].exprUnion(), Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1001: + case 1010: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5255 +//line sql.y:5299 { yyLOCAL = &AndExpr{Left: yyDollar[1].exprUnion(), Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1002: + case 1011: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5259 +//line sql.y:5303 { yyLOCAL = &NotExpr{Expr: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 1003: + case 1012: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5263 +//line sql.y:5307 { yyLOCAL = &IsExpr{Left: yyDollar[1].exprUnion(), Right: yyDollar[3].isExprOperatorUnion()} } yyVAL.union = yyLOCAL - case 1004: + case 1013: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5267 +//line sql.y:5311 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1005: + case 1014: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5271 +//line sql.y:5315 { yyLOCAL = &AssignmentExpr{Left: yyDollar[1].variableUnion(), Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1006: + case 1015: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5275 +//line sql.y:5319 { yyLOCAL = &MemberOfExpr{Value: yyDollar[1].exprUnion(), JSONArr: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1007: + case 1016: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5281 +//line sql.y:5325 { } - case 1008: + case 1017: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5284 +//line sql.y:5328 { } - case 1009: + case 1018: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5289 +//line sql.y:5333 { yyLOCAL = &IsExpr{Left: yyDollar[1].exprUnion(), Right: IsNullOp} } yyVAL.union = yyLOCAL - case 1010: + case 1019: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5293 +//line sql.y:5337 { yyLOCAL = &IsExpr{Left: yyDollar[1].exprUnion(), Right: IsNotNullOp} } yyVAL.union = yyLOCAL - case 1011: + case 1020: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5297 +//line sql.y:5341 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: yyDollar[2].comparisonExprOperatorUnion(), Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1012: + case 1021: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5301 +//line sql.y:5345 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: yyDollar[2].comparisonExprOperatorUnion(), Modifier: Any, Right: yyDollar[4].subqueryUnion()} } yyVAL.union = yyLOCAL - case 1013: + case 1022: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5305 +//line sql.y:5349 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: yyDollar[2].comparisonExprOperatorUnion(), Modifier: Any, Right: yyDollar[4].subqueryUnion()} } yyVAL.union = yyLOCAL - case 1014: + case 1023: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5309 +//line sql.y:5353 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: yyDollar[2].comparisonExprOperatorUnion(), Modifier: All, Right: yyDollar[4].subqueryUnion()} } yyVAL.union = yyLOCAL - case 1015: + case 1024: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5313 +//line sql.y:5357 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1016: + case 1025: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5319 +//line sql.y:5363 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: InOp, Right: yyDollar[3].colTupleUnion()} } yyVAL.union = yyLOCAL - case 1017: + case 1026: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5323 +//line sql.y:5367 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: NotInOp, Right: yyDollar[4].colTupleUnion()} } yyVAL.union = yyLOCAL - case 1018: + case 1027: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:5327 +//line sql.y:5371 { yyLOCAL = &BetweenExpr{Left: yyDollar[1].exprUnion(), IsBetween: true, From: yyDollar[3].exprUnion(), To: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1019: + case 1028: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5331 +//line sql.y:5375 { yyLOCAL = &BetweenExpr{Left: yyDollar[1].exprUnion(), IsBetween: false, From: yyDollar[4].exprUnion(), To: yyDollar[6].exprUnion()} } yyVAL.union = yyLOCAL - case 1020: + case 1029: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5335 +//line sql.y:5379 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: LikeOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1021: + case 1030: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5339 +//line sql.y:5383 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: NotLikeOp, Right: yyDollar[4].exprUnion()} } yyVAL.union = yyLOCAL - case 1022: + case 1031: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:5343 +//line sql.y:5387 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: LikeOp, Right: yyDollar[3].exprUnion(), Escape: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1023: + case 1032: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5347 +//line sql.y:5391 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: NotLikeOp, Right: yyDollar[4].exprUnion(), Escape: yyDollar[6].exprUnion()} } yyVAL.union = yyLOCAL - case 1024: + case 1033: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5351 +//line sql.y:5395 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: RegexpOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1025: + case 1034: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5355 +//line sql.y:5399 { yyLOCAL = &ComparisonExpr{Left: yyDollar[1].exprUnion(), Operator: NotRegexpOp, Right: yyDollar[4].exprUnion()} } yyVAL.union = yyLOCAL - case 1026: + case 1035: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5359 +//line sql.y:5403 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1027: + case 1036: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5365 +//line sql.y:5409 { } - case 1028: + case 1037: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5368 +//line sql.y:5412 { } - case 1029: + case 1038: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5374 +//line sql.y:5418 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: BitOrOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1030: + case 1039: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5378 +//line sql.y:5422 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: BitAndOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1031: + case 1040: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5382 +//line sql.y:5426 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: ShiftLeftOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1032: + case 1041: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5386 +//line sql.y:5430 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: ShiftRightOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1033: + case 1042: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5390 +//line sql.y:5434 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: PlusOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1034: + case 1043: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5394 +//line sql.y:5438 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: MinusOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1035: + case 1044: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:5398 +//line sql.y:5442 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprBinaryAdd, Date: yyDollar[1].exprUnion(), Unit: yyDollar[5].intervalTypeUnion(), Interval: yyDollar[4].exprUnion()} } yyVAL.union = yyLOCAL - case 1036: + case 1045: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:5402 +//line sql.y:5446 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprBinarySub, Date: yyDollar[1].exprUnion(), Unit: yyDollar[5].intervalTypeUnion(), Interval: yyDollar[4].exprUnion()} } yyVAL.union = yyLOCAL - case 1037: + case 1046: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5406 +//line sql.y:5450 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: MultOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1038: + case 1047: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5410 +//line sql.y:5454 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: DivOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1039: + case 1048: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5414 +//line sql.y:5458 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: ModOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1040: + case 1049: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5418 +//line sql.y:5462 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: IntDivOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1041: + case 1050: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5422 +//line sql.y:5466 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: ModOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1042: + case 1051: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5426 +//line sql.y:5470 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: BitXorOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1043: + case 1052: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5430 +//line sql.y:5474 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1044: + case 1053: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5436 +//line sql.y:5480 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1045: + case 1054: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5440 +//line sql.y:5484 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1046: + case 1055: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5444 +//line sql.y:5488 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1047: + case 1056: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5448 +//line sql.y:5492 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1048: + case 1057: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5452 +//line sql.y:5496 { yyLOCAL = &CollateExpr{Expr: yyDollar[1].exprUnion(), Collation: yyDollar[3].str} } yyVAL.union = yyLOCAL - case 1049: + case 1058: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5456 +//line sql.y:5500 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1050: + case 1059: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5460 +//line sql.y:5504 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1051: + case 1060: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5464 +//line sql.y:5508 { yyLOCAL = yyDollar[1].variableUnion() } yyVAL.union = yyLOCAL - case 1052: + case 1061: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5468 +//line sql.y:5512 { yyLOCAL = yyDollar[2].exprUnion() // TODO: do we really want to ignore unary '+' before any kind of literals? } yyVAL.union = yyLOCAL - case 1053: + case 1062: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5472 +//line sql.y:5516 { yyLOCAL = &UnaryExpr{Operator: UMinusOp, Expr: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 1054: + case 1063: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5476 +//line sql.y:5520 { yyLOCAL = &UnaryExpr{Operator: TildaOp, Expr: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 1055: + case 1064: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5480 +//line sql.y:5524 { yyLOCAL = &UnaryExpr{Operator: BangOp, Expr: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 1056: + case 1065: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5484 +//line sql.y:5528 { yyLOCAL = yyDollar[1].subqueryUnion() } yyVAL.union = yyLOCAL - case 1057: + case 1066: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5488 +//line sql.y:5532 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1058: + case 1067: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5492 +//line sql.y:5536 { yyLOCAL = &ExistsExpr{Subquery: yyDollar[2].subqueryUnion()} } yyVAL.union = yyLOCAL - case 1059: + case 1068: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Expr -//line sql.y:5496 +//line sql.y:5540 { yyLOCAL = &MatchExpr{Columns: yyDollar[2].colNamesUnion(), Expr: yyDollar[5].exprUnion(), Option: yyDollar[6].matchExprOptionUnion()} } yyVAL.union = yyLOCAL - case 1060: + case 1069: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Expr -//line sql.y:5500 +//line sql.y:5544 { yyLOCAL = &CastExpr{Expr: yyDollar[3].exprUnion(), Type: yyDollar[5].convertTypeUnion(), Array: yyDollar[6].booleanUnion()} } yyVAL.union = yyLOCAL - case 1061: + case 1070: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5504 +//line sql.y:5548 { yyLOCAL = &ConvertExpr{Expr: yyDollar[3].exprUnion(), Type: yyDollar[5].convertTypeUnion()} } yyVAL.union = yyLOCAL - case 1062: + case 1071: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5508 +//line sql.y:5552 { yyLOCAL = &ConvertUsingExpr{Expr: yyDollar[3].exprUnion(), Type: yyDollar[5].str} } yyVAL.union = yyLOCAL - case 1063: + case 1072: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5512 +//line sql.y:5556 { // 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: @@ -18035,3202 +18133,3218 @@ yydefault: yyLOCAL = &ConvertExpr{Expr: yyDollar[2].exprUnion(), Type: &ConvertType{Type: yyDollar[1].str}} } yyVAL.union = yyLOCAL - case 1064: + case 1073: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5520 +//line sql.y:5564 { yyLOCAL = &Default{ColName: yyDollar[2].str} } yyVAL.union = yyLOCAL - case 1065: + case 1074: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:5524 +//line sql.y:5568 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprBinaryAddLeft, Date: yyDollar[5].exprUnion(), Unit: yyDollar[3].intervalTypeUnion(), Interval: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 1066: + case 1075: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5528 +//line sql.y:5572 { yyLOCAL = &IntervalFuncExpr{Expr: yyDollar[3].exprUnion(), Exprs: yyDollar[5].exprsUnion()} } yyVAL.union = yyLOCAL - case 1067: + case 1076: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5532 +//line sql.y:5576 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: JSONExtractOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1068: + case 1077: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:5536 +//line sql.y:5580 { yyLOCAL = &BinaryExpr{Left: yyDollar[1].exprUnion(), Operator: JSONUnquoteExtractOp, Right: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1069: + case 1078: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*ColName -//line sql.y:5542 +//line sql.y:5586 { yyLOCAL = yyDollar[1].colNamesUnion() } yyVAL.union = yyLOCAL - case 1070: + case 1079: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*ColName -//line sql.y:5546 +//line sql.y:5590 { yyLOCAL = yyDollar[2].colNamesUnion() } yyVAL.union = yyLOCAL - case 1071: + case 1080: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*ColName -//line sql.y:5552 +//line sql.y:5596 { yyLOCAL = []*ColName{yyDollar[1].colNameUnion()} } yyVAL.union = yyLOCAL - case 1072: + case 1081: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5556 +//line sql.y:5600 { yySLICE := (*[]*ColName)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].colNameUnion()) } - case 1073: + case 1082: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TrimType -//line sql.y:5562 +//line sql.y:5606 { yyLOCAL = BothTrimType } yyVAL.union = yyLOCAL - case 1074: + case 1083: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TrimType -//line sql.y:5566 +//line sql.y:5610 { yyLOCAL = LeadingTrimType } yyVAL.union = yyLOCAL - case 1075: + case 1084: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL TrimType -//line sql.y:5570 +//line sql.y:5614 { yyLOCAL = TrailingTrimType } yyVAL.union = yyLOCAL - case 1076: + case 1085: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL FrameUnitType -//line sql.y:5576 +//line sql.y:5620 { yyLOCAL = FrameRowsType } yyVAL.union = yyLOCAL - case 1077: + case 1086: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL FrameUnitType -//line sql.y:5580 +//line sql.y:5624 { yyLOCAL = FrameRangeType } yyVAL.union = yyLOCAL - case 1078: + case 1087: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ArgumentLessWindowExprType -//line sql.y:5587 +//line sql.y:5631 { yyLOCAL = CumeDistExprType } yyVAL.union = yyLOCAL - case 1079: + case 1088: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ArgumentLessWindowExprType -//line sql.y:5591 +//line sql.y:5635 { yyLOCAL = DenseRankExprType } yyVAL.union = yyLOCAL - case 1080: + case 1089: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ArgumentLessWindowExprType -//line sql.y:5595 +//line sql.y:5639 { yyLOCAL = PercentRankExprType } yyVAL.union = yyLOCAL - case 1081: + case 1090: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ArgumentLessWindowExprType -//line sql.y:5599 +//line sql.y:5643 { yyLOCAL = RankExprType } yyVAL.union = yyLOCAL - case 1082: + case 1091: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ArgumentLessWindowExprType -//line sql.y:5603 +//line sql.y:5647 { yyLOCAL = RowNumberExprType } yyVAL.union = yyLOCAL - case 1083: + case 1092: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *FramePoint -//line sql.y:5609 +//line sql.y:5653 { yyLOCAL = &FramePoint{Type: CurrentRowType} } yyVAL.union = yyLOCAL - case 1084: + case 1093: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *FramePoint -//line sql.y:5613 +//line sql.y:5657 { yyLOCAL = &FramePoint{Type: UnboundedPrecedingType} } yyVAL.union = yyLOCAL - case 1085: + case 1094: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *FramePoint -//line sql.y:5617 +//line sql.y:5661 { yyLOCAL = &FramePoint{Type: UnboundedFollowingType} } yyVAL.union = yyLOCAL - case 1086: + case 1095: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *FramePoint -//line sql.y:5621 +//line sql.y:5665 { yyLOCAL = &FramePoint{Type: ExprPrecedingType, Expr: yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1087: + case 1096: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *FramePoint -//line sql.y:5625 +//line sql.y:5669 { yyLOCAL = &FramePoint{Type: ExprPrecedingType, Expr: yyDollar[2].exprUnion(), Unit: yyDollar[3].intervalTypeUnion()} } yyVAL.union = yyLOCAL - case 1088: + case 1097: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *FramePoint -//line sql.y:5629 +//line sql.y:5673 { yyLOCAL = &FramePoint{Type: ExprFollowingType, Expr: yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1089: + case 1098: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *FramePoint -//line sql.y:5633 +//line sql.y:5677 { yyLOCAL = &FramePoint{Type: ExprFollowingType, Expr: yyDollar[2].exprUnion(), Unit: yyDollar[3].intervalTypeUnion()} } yyVAL.union = yyLOCAL - case 1090: + case 1099: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *FrameClause -//line sql.y:5638 +//line sql.y:5682 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1091: + case 1100: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *FrameClause -//line sql.y:5642 +//line sql.y:5686 { yyLOCAL = yyDollar[1].frameClauseUnion() } yyVAL.union = yyLOCAL - case 1092: + case 1101: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *FrameClause -//line sql.y:5648 +//line sql.y:5692 { yyLOCAL = &FrameClause{Unit: yyDollar[1].frameUnitTypeUnion(), Start: yyDollar[2].framePointUnion()} } yyVAL.union = yyLOCAL - case 1093: + case 1102: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *FrameClause -//line sql.y:5652 +//line sql.y:5696 { yyLOCAL = &FrameClause{Unit: yyDollar[1].frameUnitTypeUnion(), Start: yyDollar[3].framePointUnion(), End: yyDollar[5].framePointUnion()} } yyVAL.union = yyLOCAL - case 1094: + case 1103: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Exprs -//line sql.y:5657 +//line sql.y:5701 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1095: + case 1104: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Exprs -//line sql.y:5661 +//line sql.y:5705 { yyLOCAL = yyDollar[3].exprsUnion() } yyVAL.union = yyLOCAL - case 1096: + case 1105: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:5666 +//line sql.y:5710 { yyVAL.identifierCI = IdentifierCI{} } - case 1097: + case 1106: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:5670 +//line sql.y:5714 { yyVAL.identifierCI = yyDollar[1].identifierCI } - case 1098: + case 1107: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *WindowSpecification -//line sql.y:5676 +//line sql.y:5720 { yyLOCAL = &WindowSpecification{Name: yyDollar[1].identifierCI, PartitionClause: yyDollar[2].exprsUnion(), OrderClause: yyDollar[3].orderByUnion(), FrameClause: yyDollar[4].frameClauseUnion()} } yyVAL.union = yyLOCAL - case 1099: + case 1108: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *OverClause -//line sql.y:5682 +//line sql.y:5726 { yyLOCAL = &OverClause{WindowSpec: yyDollar[3].windowSpecificationUnion()} } yyVAL.union = yyLOCAL - case 1100: + case 1109: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *OverClause -//line sql.y:5686 +//line sql.y:5730 { yyLOCAL = &OverClause{WindowName: yyDollar[2].identifierCI} } yyVAL.union = yyLOCAL - case 1101: + case 1110: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *OverClause -//line sql.y:5692 +//line sql.y:5736 { yyLOCAL = yyDollar[1].overClauseUnion() } yyVAL.union = yyLOCAL - case 1102: + case 1111: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *OverClause -//line sql.y:5696 +//line sql.y:5740 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1103: + case 1112: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *NullTreatmentClause -//line sql.y:5701 +//line sql.y:5745 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1105: + case 1114: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *NullTreatmentClause -//line sql.y:5708 +//line sql.y:5752 { yyLOCAL = &NullTreatmentClause{yyDollar[1].nullTreatmentTypeUnion()} } yyVAL.union = yyLOCAL - case 1106: + case 1115: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL NullTreatmentType -//line sql.y:5714 +//line sql.y:5758 { yyLOCAL = RespectNullsType } yyVAL.union = yyLOCAL - case 1107: + case 1116: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL NullTreatmentType -//line sql.y:5718 +//line sql.y:5762 { yyLOCAL = IgnoreNullsType } yyVAL.union = yyLOCAL - case 1108: + case 1117: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL FirstOrLastValueExprType -//line sql.y:5724 +//line sql.y:5768 { yyLOCAL = FirstValueExprType } yyVAL.union = yyLOCAL - case 1109: + case 1118: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL FirstOrLastValueExprType -//line sql.y:5728 +//line sql.y:5772 { yyLOCAL = LastValueExprType } yyVAL.union = yyLOCAL - case 1110: + case 1119: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL FromFirstLastType -//line sql.y:5734 +//line sql.y:5778 { yyLOCAL = FromFirstType } yyVAL.union = yyLOCAL - case 1111: + case 1120: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL FromFirstLastType -//line sql.y:5738 +//line sql.y:5782 { yyLOCAL = FromLastType } yyVAL.union = yyLOCAL - case 1112: + case 1121: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *FromFirstLastClause -//line sql.y:5743 +//line sql.y:5787 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1114: + case 1123: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *FromFirstLastClause -//line sql.y:5750 +//line sql.y:5794 { yyLOCAL = &FromFirstLastClause{yyDollar[1].fromFirstLastTypeUnion()} } yyVAL.union = yyLOCAL - case 1115: + case 1124: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL LagLeadExprType -//line sql.y:5756 +//line sql.y:5800 { yyLOCAL = LagExprType } yyVAL.union = yyLOCAL - case 1116: + case 1125: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL LagLeadExprType -//line sql.y:5760 +//line sql.y:5804 { yyLOCAL = LeadExprType } yyVAL.union = yyLOCAL - case 1117: + case 1126: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *WindowDefinition -//line sql.y:5766 +//line sql.y:5810 { yyLOCAL = &WindowDefinition{Name: yyDollar[1].identifierCI, WindowSpec: yyDollar[4].windowSpecificationUnion()} } yyVAL.union = yyLOCAL - case 1118: + case 1127: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL WindowDefinitions -//line sql.y:5772 +//line sql.y:5816 { yyLOCAL = WindowDefinitions{yyDollar[1].windowDefinitionUnion()} } yyVAL.union = yyLOCAL - case 1119: + case 1128: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5776 +//line sql.y:5820 { yySLICE := (*WindowDefinitions)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].windowDefinitionUnion()) } - case 1120: + case 1129: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:5782 +//line sql.y:5826 { yyVAL.str = "" } - case 1121: + case 1130: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5786 +//line sql.y:5830 { yyVAL.str = string(yyDollar[2].identifierCI.String()) } - case 1122: + case 1131: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL BoolVal -//line sql.y:5792 +//line sql.y:5836 { yyLOCAL = BoolVal(true) } yyVAL.union = yyLOCAL - case 1123: + case 1132: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL BoolVal -//line sql.y:5796 +//line sql.y:5840 { yyLOCAL = BoolVal(false) } yyVAL.union = yyLOCAL - case 1124: + case 1133: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IsExprOperator -//line sql.y:5803 +//line sql.y:5847 { yyLOCAL = IsTrueOp } yyVAL.union = yyLOCAL - case 1125: + case 1134: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL IsExprOperator -//line sql.y:5807 +//line sql.y:5851 { yyLOCAL = IsNotTrueOp } yyVAL.union = yyLOCAL - case 1126: + case 1135: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IsExprOperator -//line sql.y:5811 +//line sql.y:5855 { yyLOCAL = IsFalseOp } yyVAL.union = yyLOCAL - case 1127: + case 1136: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL IsExprOperator -//line sql.y:5815 +//line sql.y:5859 { yyLOCAL = IsNotFalseOp } yyVAL.union = yyLOCAL - case 1128: + case 1137: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:5821 +//line sql.y:5865 { yyLOCAL = yyDollar[1].comparisonExprOperatorUnion() } yyVAL.union = yyLOCAL - case 1129: + case 1138: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:5825 +//line sql.y:5869 { yyLOCAL = NullSafeEqualOp } yyVAL.union = yyLOCAL - case 1130: + case 1139: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:5831 +//line sql.y:5875 { yyLOCAL = EqualOp } yyVAL.union = yyLOCAL - case 1131: + case 1140: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:5835 +//line sql.y:5879 { yyLOCAL = LessThanOp } yyVAL.union = yyLOCAL - case 1132: + case 1141: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:5839 +//line sql.y:5883 { yyLOCAL = GreaterThanOp } yyVAL.union = yyLOCAL - case 1133: + case 1142: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:5843 +//line sql.y:5887 { yyLOCAL = LessEqualOp } yyVAL.union = yyLOCAL - case 1134: + case 1143: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:5847 +//line sql.y:5891 { yyLOCAL = GreaterEqualOp } yyVAL.union = yyLOCAL - case 1135: + case 1144: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ComparisonExprOperator -//line sql.y:5851 +//line sql.y:5895 { yyLOCAL = NotEqualOp } yyVAL.union = yyLOCAL - case 1136: + case 1145: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColTuple -//line sql.y:5857 +//line sql.y:5901 { yyLOCAL = yyDollar[1].valTupleUnion() } yyVAL.union = yyLOCAL - case 1137: + case 1146: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColTuple -//line sql.y:5861 +//line sql.y:5905 { yyLOCAL = yyDollar[1].subqueryUnion() } yyVAL.union = yyLOCAL - case 1138: + case 1147: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ColTuple -//line sql.y:5865 +//line sql.y:5909 { yyLOCAL = ListArg(yyDollar[1].str[2:]) markBindVariable(yylex, yyDollar[1].str[2:]) } yyVAL.union = yyLOCAL - case 1139: + case 1148: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Subquery -//line sql.y:5872 +//line sql.y:5916 { yyLOCAL = &Subquery{yyDollar[1].selStmtUnion()} } yyVAL.union = yyLOCAL - case 1140: + case 1149: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Exprs -//line sql.y:5878 +//line sql.y:5922 { yyLOCAL = Exprs{yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1141: + case 1150: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:5882 +//line sql.y:5926 { yySLICE := (*Exprs)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].exprUnion()) } - case 1142: + case 1151: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5892 +//line sql.y:5936 { yyLOCAL = &FuncExpr{Name: yyDollar[1].identifierCI, Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1143: + case 1152: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5896 +//line sql.y:5940 { yyLOCAL = &FuncExpr{Qualifier: yyDollar[1].identifierCS, Name: yyDollar[3].identifierCI, Exprs: yyDollar[5].exprsUnion()} } yyVAL.union = yyLOCAL - case 1144: + case 1153: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5906 +//line sql.y:5950 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("left"), Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1145: + case 1154: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5910 +//line sql.y:5954 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("right"), Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1146: + case 1155: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:5914 +//line sql.y:5958 { yyLOCAL = &SubstrExpr{Name: yyDollar[3].exprUnion(), From: yyDollar[5].exprUnion(), To: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1147: + case 1156: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:5918 +//line sql.y:5962 { yyLOCAL = &SubstrExpr{Name: yyDollar[3].exprUnion(), From: yyDollar[5].exprUnion(), To: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1148: + case 1157: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5922 +//line sql.y:5966 { yyLOCAL = &SubstrExpr{Name: yyDollar[3].exprUnion(), From: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1149: + case 1158: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:5926 +//line sql.y:5970 { yyLOCAL = &SubstrExpr{Name: yyDollar[3].exprUnion(), From: yyDollar[5].exprUnion(), To: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1150: + case 1159: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5930 +//line sql.y:5974 { yyLOCAL = &SubstrExpr{Name: yyDollar[3].exprUnion(), From: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1151: + case 1160: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:5934 +//line sql.y:5978 { yyLOCAL = &CaseExpr{Expr: yyDollar[2].exprUnion(), Whens: yyDollar[3].whensUnion(), Else: yyDollar[4].exprUnion()} } yyVAL.union = yyLOCAL - case 1152: + case 1161: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:5938 +//line sql.y:5982 { yyLOCAL = &ValuesFuncExpr{Name: yyDollar[3].colNameUnion()} } yyVAL.union = yyLOCAL - case 1153: + case 1162: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL Expr -//line sql.y:5942 +//line sql.y:5986 { yyLOCAL = &InsertExpr{Str: yyDollar[3].exprUnion(), Pos: yyDollar[5].exprUnion(), Len: yyDollar[7].exprUnion(), NewStr: yyDollar[9].exprUnion()} } yyVAL.union = yyLOCAL - case 1154: + case 1163: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5946 +//line sql.y:5990 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1155: + case 1164: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5957 +//line sql.y:6001 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("utc_date")} } yyVAL.union = yyLOCAL - case 1156: + case 1165: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:5961 +//line sql.y:6005 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1157: + case 1166: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5967 +//line sql.y:6011 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("current_date")} } yyVAL.union = yyLOCAL - case 1158: + case 1167: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5971 +//line sql.y:6015 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("curdate")} } yyVAL.union = yyLOCAL - case 1159: + case 1168: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5975 +//line sql.y:6019 { yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("utc_time"), Fsp: yyDollar[2].integerUnion()} } yyVAL.union = yyLOCAL - case 1160: + case 1169: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5980 +//line sql.y:6024 { yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("curtime"), Fsp: yyDollar[2].integerUnion()} } yyVAL.union = yyLOCAL - case 1161: + case 1170: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:5985 +//line sql.y:6029 { yyLOCAL = &CurTimeFuncExpr{Name: NewIdentifierCI("current_time"), Fsp: yyDollar[2].integerUnion()} } yyVAL.union = yyLOCAL - case 1162: + case 1171: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:5989 +//line sql.y:6033 { yyLOCAL = &CountStar{OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1163: + case 1172: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5993 +//line sql.y:6037 { yyLOCAL = &Count{Distinct: yyDollar[3].booleanUnion(), Args: yyDollar[4].exprsUnion(), OverClause: yyDollar[6].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1164: + case 1173: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:5997 +//line sql.y:6041 { yyLOCAL = &Max{Distinct: yyDollar[3].booleanUnion(), Arg: yyDollar[4].exprUnion(), OverClause: yyDollar[6].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1165: + case 1174: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6001 +//line sql.y:6045 { yyLOCAL = &Min{Distinct: yyDollar[3].booleanUnion(), Arg: yyDollar[4].exprUnion(), OverClause: yyDollar[6].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1166: + case 1175: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6005 +//line sql.y:6049 { yyLOCAL = &Sum{Distinct: yyDollar[3].booleanUnion(), Arg: yyDollar[4].exprUnion(), OverClause: yyDollar[6].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1167: + case 1176: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6009 +//line sql.y:6053 { yyLOCAL = &Avg{Distinct: yyDollar[3].booleanUnion(), Arg: yyDollar[4].exprUnion(), OverClause: yyDollar[6].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1168: + case 1177: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6013 +//line sql.y:6057 { yyLOCAL = &BitAnd{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1169: + case 1178: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6017 +//line sql.y:6061 { yyLOCAL = &BitOr{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1170: + case 1179: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6021 +//line sql.y:6065 { yyLOCAL = &BitXor{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1171: + case 1180: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6025 +//line sql.y:6069 { yyLOCAL = &Std{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1172: + case 1181: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6029 +//line sql.y:6073 { yyLOCAL = &StdDev{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1173: + case 1182: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6033 +//line sql.y:6077 { yyLOCAL = &StdPop{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1174: + case 1183: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6037 +//line sql.y:6081 { yyLOCAL = &StdSamp{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1175: + case 1184: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6041 +//line sql.y:6085 { yyLOCAL = &VarPop{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1176: + case 1185: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6045 +//line sql.y:6089 { yyLOCAL = &VarSamp{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1177: + case 1186: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6049 +//line sql.y:6093 { yyLOCAL = &Variance{Arg: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1178: + case 1187: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6053 +//line sql.y:6097 { 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 1179: + case 1188: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6057 +//line sql.y:6101 { yyLOCAL = &AnyValue{Arg: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1180: + case 1189: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6061 +//line sql.y:6105 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprTimestampadd, Date: yyDollar[7].exprUnion(), Interval: yyDollar[5].exprUnion(), Unit: yyDollar[3].intervalTypeUnion()} } yyVAL.union = yyLOCAL - case 1181: + case 1190: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6065 +//line sql.y:6109 { yyLOCAL = &TimestampDiffExpr{Unit: yyDollar[3].intervalTypeUnion(), Expr1: yyDollar[5].exprUnion(), Expr2: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1182: + case 1191: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6069 +//line sql.y:6113 { yyLOCAL = &ExtractFuncExpr{IntervalType: yyDollar[3].intervalTypeUnion(), Expr: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1183: + case 1192: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6073 +//line sql.y:6117 { yyLOCAL = &WeightStringFuncExpr{Expr: yyDollar[3].exprUnion(), As: yyDollar[4].convertTypeUnion()} } yyVAL.union = yyLOCAL - case 1184: + case 1193: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6077 +//line sql.y:6121 { yyLOCAL = &JSONPrettyExpr{JSONVal: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1185: + case 1194: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6081 +//line sql.y:6125 { yyLOCAL = &JSONStorageFreeExpr{JSONVal: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1186: + case 1195: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6085 +//line sql.y:6129 + { + yyLOCAL = &JSONStorageSizeExpr{JSONVal: yyDollar[3].exprUnion()} + } + yyVAL.union = yyLOCAL + case 1196: + yyDollar = yyS[yypt-5 : yypt+1] + var yyLOCAL Expr +//line sql.y:6133 + { + yyLOCAL = &JSONArrayAgg{Expr: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} + } + yyVAL.union = yyLOCAL + case 1197: + yyDollar = yyS[yypt-7 : yypt+1] + var yyLOCAL Expr +//line sql.y:6137 { - yyLOCAL = &JSONStorageSizeExpr{JSONVal: yyDollar[3].exprUnion()} + yyLOCAL = &JSONObjectAgg{Key: yyDollar[3].exprUnion(), Value: yyDollar[5].exprUnion(), OverClause: yyDollar[7].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1187: + case 1198: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6089 +//line sql.y:6141 { yyLOCAL = &TrimFuncExpr{TrimFuncType: LTrimType, Type: LeadingTrimType, StringArg: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1188: + case 1199: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6093 +//line sql.y:6145 { yyLOCAL = &TrimFuncExpr{TrimFuncType: RTrimType, Type: TrailingTrimType, StringArg: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1189: + case 1200: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Expr -//line sql.y:6097 +//line sql.y:6149 { yyLOCAL = &TrimFuncExpr{Type: yyDollar[3].trimTypeUnion(), TrimArg: yyDollar[4].exprUnion(), StringArg: yyDollar[6].exprUnion()} } yyVAL.union = yyLOCAL - case 1190: + case 1201: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6101 +//line sql.y:6153 { yyLOCAL = &TrimFuncExpr{StringArg: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1191: + case 1202: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6105 +//line sql.y:6157 { yyLOCAL = &CharExpr{Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1192: + case 1203: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6109 +//line sql.y:6161 { yyLOCAL = &CharExpr{Exprs: yyDollar[3].exprsUnion(), Charset: yyDollar[5].str} } yyVAL.union = yyLOCAL - case 1193: + case 1204: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6113 +//line sql.y:6165 { yyLOCAL = &TrimFuncExpr{TrimArg: yyDollar[3].exprUnion(), StringArg: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1194: + case 1205: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6117 +//line sql.y:6169 { yyLOCAL = &LocateExpr{SubStr: yyDollar[3].exprUnion(), Str: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1195: + case 1206: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6121 +//line sql.y:6173 { yyLOCAL = &LocateExpr{SubStr: yyDollar[3].exprUnion(), Str: yyDollar[5].exprUnion(), Pos: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1196: + case 1207: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6125 +//line sql.y:6177 { yyLOCAL = &LocateExpr{SubStr: yyDollar[3].exprUnion(), Str: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1197: + case 1208: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6129 +//line sql.y:6181 { yyLOCAL = &LockingFunc{Type: GetLock, Name: yyDollar[3].exprUnion(), Timeout: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1198: + case 1209: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6133 +//line sql.y:6185 { yyLOCAL = &LockingFunc{Type: IsFreeLock, Name: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1199: + case 1210: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6137 +//line sql.y:6189 { yyLOCAL = &LockingFunc{Type: IsUsedLock, Name: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1200: + case 1211: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:6141 +//line sql.y:6193 { yyLOCAL = &LockingFunc{Type: ReleaseAllLocks} } yyVAL.union = yyLOCAL - case 1201: + case 1212: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6145 +//line sql.y:6197 { yyLOCAL = &LockingFunc{Type: ReleaseLock, Name: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1202: + case 1213: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6149 +//line sql.y:6201 { yyLOCAL = &JSONSchemaValidFuncExpr{Schema: yyDollar[3].exprUnion(), Document: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1203: + case 1214: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6153 +//line sql.y:6205 { yyLOCAL = &JSONSchemaValidationReportFuncExpr{Schema: yyDollar[3].exprUnion(), Document: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1204: + case 1215: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6157 +//line sql.y:6209 { yyLOCAL = &JSONArrayExpr{Params: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1205: + case 1216: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6161 +//line sql.y:6213 { yyLOCAL = &GeomFormatExpr{FormatType: BinaryFormat, Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1206: + case 1217: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6165 +//line sql.y:6217 { yyLOCAL = &GeomFormatExpr{FormatType: BinaryFormat, Geom: yyDollar[3].exprUnion(), AxisOrderOpt: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1207: + case 1218: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6169 +//line sql.y:6221 { yyLOCAL = &GeomFormatExpr{FormatType: TextFormat, Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1208: + case 1219: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6173 +//line sql.y:6225 { yyLOCAL = &GeomFormatExpr{FormatType: TextFormat, Geom: yyDollar[3].exprUnion(), AxisOrderOpt: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1209: + case 1220: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6177 +//line sql.y:6229 { yyLOCAL = &GeomPropertyFuncExpr{Property: IsEmpty, Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1210: + case 1221: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6181 +//line sql.y:6233 { yyLOCAL = &GeomPropertyFuncExpr{Property: IsSimple, Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1211: + case 1222: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6185 +//line sql.y:6237 { yyLOCAL = &GeomPropertyFuncExpr{Property: Dimension, Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1212: + case 1223: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6189 +//line sql.y:6241 { yyLOCAL = &GeomPropertyFuncExpr{Property: Envelope, Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1213: + case 1224: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6193 +//line sql.y:6245 { yyLOCAL = &GeomPropertyFuncExpr{Property: GeometryType, Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1214: + case 1225: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6197 +//line sql.y:6249 { yyLOCAL = &PointPropertyFuncExpr{Property: Latitude, Point: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1215: + case 1226: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6201 +//line sql.y:6253 { yyLOCAL = &PointPropertyFuncExpr{Property: Latitude, Point: yyDollar[3].exprUnion(), ValueToSet: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1216: + case 1227: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6205 +//line sql.y:6257 { yyLOCAL = &PointPropertyFuncExpr{Property: Longitude, Point: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1217: + case 1228: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6209 +//line sql.y:6261 { yyLOCAL = &PointPropertyFuncExpr{Property: Longitude, Point: yyDollar[3].exprUnion(), ValueToSet: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1218: + case 1229: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6213 +//line sql.y:6265 { yyLOCAL = &LinestrPropertyFuncExpr{Property: EndPoint, Linestring: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1219: + case 1230: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6217 +//line sql.y:6269 { yyLOCAL = &LinestrPropertyFuncExpr{Property: IsClosed, Linestring: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1220: + case 1231: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6221 +//line sql.y:6273 { yyLOCAL = &LinestrPropertyFuncExpr{Property: Length, Linestring: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1221: + case 1232: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6225 +//line sql.y:6277 { yyLOCAL = &LinestrPropertyFuncExpr{Property: Length, Linestring: yyDollar[3].exprUnion(), PropertyDefArg: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1222: + case 1233: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6229 +//line sql.y:6281 { yyLOCAL = &LinestrPropertyFuncExpr{Property: NumPoints, Linestring: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1223: + case 1234: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6233 +//line sql.y:6285 { yyLOCAL = &LinestrPropertyFuncExpr{Property: PointN, Linestring: yyDollar[3].exprUnion(), PropertyDefArg: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1224: + case 1235: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6237 +//line sql.y:6289 { yyLOCAL = &LinestrPropertyFuncExpr{Property: StartPoint, Linestring: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1225: + case 1236: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6241 +//line sql.y:6293 { yyLOCAL = &PointPropertyFuncExpr{Property: XCordinate, Point: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1226: + case 1237: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6245 +//line sql.y:6297 { yyLOCAL = &PointPropertyFuncExpr{Property: XCordinate, Point: yyDollar[3].exprUnion(), ValueToSet: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1227: + case 1238: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6249 +//line sql.y:6301 { yyLOCAL = &PointPropertyFuncExpr{Property: YCordinate, Point: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1228: + case 1239: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6253 +//line sql.y:6305 { yyLOCAL = &PointPropertyFuncExpr{Property: YCordinate, Point: yyDollar[3].exprUnion(), ValueToSet: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1229: + case 1240: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6257 +//line sql.y:6309 { yyLOCAL = &GeomFromTextExpr{Type: GeometryFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1230: + case 1241: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6261 +//line sql.y:6313 { yyLOCAL = &GeomFromTextExpr{Type: GeometryFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1231: + case 1242: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6265 +//line sql.y:6317 { yyLOCAL = &GeomFromTextExpr{Type: GeometryFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1232: + case 1243: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6269 +//line sql.y:6321 { yyLOCAL = &GeomFromTextExpr{Type: GeometryCollectionFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1233: + case 1244: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6273 +//line sql.y:6325 { yyLOCAL = &GeomFromTextExpr{Type: GeometryCollectionFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1234: + case 1245: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6277 +//line sql.y:6329 { yyLOCAL = &GeomFromTextExpr{Type: GeometryCollectionFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1235: + case 1246: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6281 +//line sql.y:6333 { yyLOCAL = &GeomFromTextExpr{Type: LineStringFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1236: + case 1247: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6285 +//line sql.y:6337 { yyLOCAL = &GeomFromTextExpr{Type: LineStringFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1237: + case 1248: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6289 +//line sql.y:6341 { yyLOCAL = &GeomFromTextExpr{Type: LineStringFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1238: + case 1249: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6293 +//line sql.y:6345 { yyLOCAL = &GeomFromTextExpr{Type: MultiLinestringFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1239: + case 1250: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6297 +//line sql.y:6349 { yyLOCAL = &GeomFromTextExpr{Type: MultiLinestringFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1240: + case 1251: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6301 +//line sql.y:6353 { yyLOCAL = &GeomFromTextExpr{Type: MultiLinestringFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1241: + case 1252: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6305 +//line sql.y:6357 { yyLOCAL = &GeomFromTextExpr{Type: MultiPointFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1242: + case 1253: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6309 +//line sql.y:6361 { yyLOCAL = &GeomFromTextExpr{Type: MultiPointFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1243: + case 1254: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6313 +//line sql.y:6365 { yyLOCAL = &GeomFromTextExpr{Type: MultiPointFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1244: + case 1255: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6317 +//line sql.y:6369 { yyLOCAL = &GeomFromTextExpr{Type: MultiPolygonFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1245: + case 1256: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6321 +//line sql.y:6373 { yyLOCAL = &GeomFromTextExpr{Type: MultiPolygonFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1246: + case 1257: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6325 +//line sql.y:6377 { yyLOCAL = &GeomFromTextExpr{Type: MultiPolygonFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1247: + case 1258: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6329 +//line sql.y:6381 { yyLOCAL = &GeomFromTextExpr{Type: PointFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1248: + case 1259: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6333 +//line sql.y:6385 { yyLOCAL = &GeomFromTextExpr{Type: PointFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1249: + case 1260: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6337 +//line sql.y:6389 { yyLOCAL = &GeomFromTextExpr{Type: PointFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1250: + case 1261: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6341 +//line sql.y:6393 { yyLOCAL = &GeomFromTextExpr{Type: PolygonFromText, WktText: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1251: + case 1262: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6345 +//line sql.y:6397 { yyLOCAL = &GeomFromTextExpr{Type: PolygonFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1252: + case 1263: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6349 +//line sql.y:6401 { yyLOCAL = &GeomFromTextExpr{Type: PolygonFromText, WktText: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1253: + case 1264: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6353 +//line sql.y:6405 { yyLOCAL = &GeomFromWKBExpr{Type: GeometryFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1254: + case 1265: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6357 +//line sql.y:6409 { yyLOCAL = &GeomFromWKBExpr{Type: GeometryFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1255: + case 1266: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6361 +//line sql.y:6413 { yyLOCAL = &GeomFromWKBExpr{Type: GeometryFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1256: + case 1267: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6365 +//line sql.y:6417 { yyLOCAL = &GeomFromWKBExpr{Type: GeometryCollectionFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1257: + case 1268: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6369 +//line sql.y:6421 { yyLOCAL = &GeomFromWKBExpr{Type: GeometryCollectionFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1258: + case 1269: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6373 +//line sql.y:6425 { yyLOCAL = &GeomFromWKBExpr{Type: GeometryCollectionFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1259: + case 1270: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6377 +//line sql.y:6429 { yyLOCAL = &GeomFromWKBExpr{Type: LineStringFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1260: + case 1271: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6381 +//line sql.y:6433 { yyLOCAL = &GeomFromWKBExpr{Type: LineStringFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1261: + case 1272: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6385 +//line sql.y:6437 { yyLOCAL = &GeomFromWKBExpr{Type: LineStringFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1262: + case 1273: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6389 +//line sql.y:6441 { yyLOCAL = &GeomFromWKBExpr{Type: MultiLinestringFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1263: + case 1274: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6393 +//line sql.y:6445 { yyLOCAL = &GeomFromWKBExpr{Type: MultiLinestringFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1264: + case 1275: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6397 +//line sql.y:6449 { yyLOCAL = &GeomFromWKBExpr{Type: MultiLinestringFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1265: + case 1276: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6401 +//line sql.y:6453 { yyLOCAL = &GeomFromWKBExpr{Type: MultiPointFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1266: + case 1277: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6405 +//line sql.y:6457 { yyLOCAL = &GeomFromWKBExpr{Type: MultiPointFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1267: + case 1278: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6409 +//line sql.y:6461 { yyLOCAL = &GeomFromWKBExpr{Type: MultiPointFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1268: + case 1279: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6413 +//line sql.y:6465 { yyLOCAL = &GeomFromWKBExpr{Type: MultiPolygonFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1269: + case 1280: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6417 +//line sql.y:6469 { yyLOCAL = &GeomFromWKBExpr{Type: MultiPolygonFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1270: + case 1281: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6421 +//line sql.y:6473 { yyLOCAL = &GeomFromWKBExpr{Type: MultiPolygonFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1271: + case 1282: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6425 +//line sql.y:6477 { yyLOCAL = &GeomFromWKBExpr{Type: PointFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1272: + case 1283: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6429 +//line sql.y:6481 { yyLOCAL = &GeomFromWKBExpr{Type: PointFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1273: + case 1284: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6433 +//line sql.y:6485 { yyLOCAL = &GeomFromWKBExpr{Type: PointFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1274: + case 1285: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6437 +//line sql.y:6489 { yyLOCAL = &GeomFromWKBExpr{Type: PolygonFromWKB, WkbBlob: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1275: + case 1286: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6441 +//line sql.y:6493 { yyLOCAL = &GeomFromWKBExpr{Type: PolygonFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1276: + case 1287: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6445 +//line sql.y:6497 { yyLOCAL = &GeomFromWKBExpr{Type: PolygonFromWKB, WkbBlob: yyDollar[3].exprUnion(), Srid: yyDollar[5].exprUnion(), AxisOrderOpt: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1277: + case 1288: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6449 +//line sql.y:6501 { yyLOCAL = &PolygonPropertyFuncExpr{Property: Area, Polygon: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1278: + case 1289: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6453 +//line sql.y:6505 { yyLOCAL = &PolygonPropertyFuncExpr{Property: Centroid, Polygon: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1279: + case 1290: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6457 +//line sql.y:6509 { yyLOCAL = &PolygonPropertyFuncExpr{Property: ExteriorRing, Polygon: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1280: + case 1291: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6461 +//line sql.y:6513 { yyLOCAL = &PolygonPropertyFuncExpr{Property: InteriorRingN, Polygon: yyDollar[3].exprUnion(), PropertyDefArg: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1281: + case 1292: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6465 +//line sql.y:6517 { yyLOCAL = &PolygonPropertyFuncExpr{Property: NumInteriorRings, Polygon: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1282: + case 1293: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6469 +//line sql.y:6521 { yyLOCAL = &GeomCollPropertyFuncExpr{Property: GeometryN, GeomColl: yyDollar[3].exprUnion(), PropertyDefArg: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1283: + case 1294: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6473 +//line sql.y:6525 { yyLOCAL = &GeomCollPropertyFuncExpr{Property: NumGeometries, GeomColl: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1284: + case 1295: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6477 +//line sql.y:6529 { yyLOCAL = &GeoHashFromLatLongExpr{Longitude: yyDollar[3].exprUnion(), Latitude: yyDollar[5].exprUnion(), MaxLength: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1285: + case 1296: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6481 +//line sql.y:6533 { yyLOCAL = &GeoHashFromPointExpr{Point: yyDollar[3].exprUnion(), MaxLength: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1286: + case 1297: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6485 +//line sql.y:6537 { yyLOCAL = &GeomFromGeoHashExpr{GeomType: LatitudeFromHash, GeoHash: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1287: + case 1298: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6489 +//line sql.y:6541 { yyLOCAL = &GeomFromGeoHashExpr{GeomType: LongitudeFromHash, GeoHash: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1288: + case 1299: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6493 +//line sql.y:6545 { yyLOCAL = &GeomFromGeoHashExpr{GeomType: PointFromHash, GeoHash: yyDollar[3].exprUnion(), SridOpt: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1289: + case 1300: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6497 +//line sql.y:6549 { yyLOCAL = &GeomFromGeoJSONExpr{GeoJSON: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1290: + case 1301: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6501 +//line sql.y:6553 { yyLOCAL = &GeomFromGeoJSONExpr{GeoJSON: yyDollar[3].exprUnion(), HigherDimHandlerOpt: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1291: + case 1302: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6505 +//line sql.y:6557 { yyLOCAL = &GeomFromGeoJSONExpr{GeoJSON: yyDollar[3].exprUnion(), HigherDimHandlerOpt: yyDollar[5].exprUnion(), Srid: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1292: + case 1303: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6509 +//line sql.y:6561 { yyLOCAL = &GeoJSONFromGeomExpr{Geom: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1293: + case 1304: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6513 +//line sql.y:6565 { yyLOCAL = &GeoJSONFromGeomExpr{Geom: yyDollar[3].exprUnion(), MaxDecimalDigits: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1294: + case 1305: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6517 +//line sql.y:6569 { yyLOCAL = &GeoJSONFromGeomExpr{Geom: yyDollar[3].exprUnion(), MaxDecimalDigits: yyDollar[5].exprUnion(), Bitmask: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1295: + case 1306: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6521 +//line sql.y:6573 { yyLOCAL = &JSONObjectExpr{Params: yyDollar[3].jsonObjectParamsUnion()} } yyVAL.union = yyLOCAL - case 1296: + case 1307: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6525 +//line sql.y:6577 { yyLOCAL = &JSONQuoteExpr{StringArg: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1297: + case 1308: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6529 +//line sql.y:6581 { yyLOCAL = &JSONContainsExpr{Target: yyDollar[3].exprUnion(), Candidate: yyDollar[5].exprsUnion()[0], PathList: yyDollar[5].exprsUnion()[1:]} } yyVAL.union = yyLOCAL - case 1298: + case 1309: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6533 +//line sql.y:6585 { yyLOCAL = &JSONContainsPathExpr{JSONDoc: yyDollar[3].exprUnion(), OneOrAll: yyDollar[5].exprUnion(), PathList: yyDollar[7].exprsUnion()} } yyVAL.union = yyLOCAL - case 1299: + case 1310: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6537 +//line sql.y:6589 { yyLOCAL = &JSONExtractExpr{JSONDoc: yyDollar[3].exprUnion(), PathList: yyDollar[5].exprsUnion()} } yyVAL.union = yyLOCAL - case 1300: + case 1311: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6541 +//line sql.y:6593 { yyLOCAL = &JSONKeysExpr{JSONDoc: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1301: + case 1312: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6545 +//line sql.y:6597 { yyLOCAL = &JSONKeysExpr{JSONDoc: yyDollar[3].exprUnion(), Path: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1302: + case 1313: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6549 +//line sql.y:6601 { yyLOCAL = &JSONOverlapsExpr{JSONDoc1: yyDollar[3].exprUnion(), JSONDoc2: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1303: + case 1314: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6553 +//line sql.y:6605 { yyLOCAL = &JSONSearchExpr{JSONDoc: yyDollar[3].exprUnion(), OneOrAll: yyDollar[5].exprUnion(), SearchStr: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1304: + case 1315: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL Expr -//line sql.y:6557 +//line sql.y:6609 { 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 1305: + case 1316: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL Expr -//line sql.y:6561 +//line sql.y:6613 { yyLOCAL = &JSONValueExpr{JSONDoc: yyDollar[3].exprUnion(), Path: yyDollar[5].exprUnion(), ReturningType: yyDollar[6].convertTypeUnion()} } yyVAL.union = yyLOCAL - case 1306: + case 1317: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6565 +//line sql.y:6617 { yyLOCAL = &JSONValueExpr{JSONDoc: yyDollar[3].exprUnion(), Path: yyDollar[5].exprUnion(), ReturningType: yyDollar[6].convertTypeUnion(), EmptyOnResponse: yyDollar[7].jtOnResponseUnion()} } yyVAL.union = yyLOCAL - case 1307: + case 1318: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6569 +//line sql.y:6621 { yyLOCAL = &JSONValueExpr{JSONDoc: yyDollar[3].exprUnion(), Path: yyDollar[5].exprUnion(), ReturningType: yyDollar[6].convertTypeUnion(), ErrorOnResponse: yyDollar[7].jtOnResponseUnion()} } yyVAL.union = yyLOCAL - case 1308: + case 1319: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL Expr -//line sql.y:6573 +//line sql.y:6625 { 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 1309: + case 1320: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6577 +//line sql.y:6629 { yyLOCAL = &JSONAttributesExpr{Type: DepthAttributeType, JSONDoc: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1310: + case 1321: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6581 +//line sql.y:6633 { yyLOCAL = &JSONAttributesExpr{Type: ValidAttributeType, JSONDoc: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1311: + case 1322: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6585 +//line sql.y:6637 { yyLOCAL = &JSONAttributesExpr{Type: TypeAttributeType, JSONDoc: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1312: + case 1323: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6589 +//line sql.y:6641 { yyLOCAL = &JSONAttributesExpr{Type: LengthAttributeType, JSONDoc: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1313: + case 1324: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6593 +//line sql.y:6645 { yyLOCAL = &JSONAttributesExpr{Type: LengthAttributeType, JSONDoc: yyDollar[3].exprUnion(), Path: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1314: + case 1325: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6597 +//line sql.y:6649 { yyLOCAL = &JSONValueModifierExpr{Type: JSONArrayAppendType, JSONDoc: yyDollar[3].exprUnion(), Params: yyDollar[5].jsonObjectParamsUnion()} } yyVAL.union = yyLOCAL - case 1315: + case 1326: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6601 +//line sql.y:6653 { yyLOCAL = &JSONValueModifierExpr{Type: JSONArrayInsertType, JSONDoc: yyDollar[3].exprUnion(), Params: yyDollar[5].jsonObjectParamsUnion()} } yyVAL.union = yyLOCAL - case 1316: + case 1327: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6605 +//line sql.y:6657 { yyLOCAL = &JSONValueModifierExpr{Type: JSONInsertType, JSONDoc: yyDollar[3].exprUnion(), Params: yyDollar[5].jsonObjectParamsUnion()} } yyVAL.union = yyLOCAL - case 1317: + case 1328: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6609 +//line sql.y:6661 { yyLOCAL = &JSONValueModifierExpr{Type: JSONReplaceType, JSONDoc: yyDollar[3].exprUnion(), Params: yyDollar[5].jsonObjectParamsUnion()} } yyVAL.union = yyLOCAL - case 1318: + case 1329: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6613 +//line sql.y:6665 { yyLOCAL = &JSONValueModifierExpr{Type: JSONSetType, JSONDoc: yyDollar[3].exprUnion(), Params: yyDollar[5].jsonObjectParamsUnion()} } yyVAL.union = yyLOCAL - case 1319: + case 1330: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6617 +//line sql.y:6669 { yyLOCAL = &JSONValueMergeExpr{Type: JSONMergeType, JSONDoc: yyDollar[3].exprUnion(), JSONDocList: yyDollar[5].exprsUnion()} } yyVAL.union = yyLOCAL - case 1320: + case 1331: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6621 +//line sql.y:6673 { yyLOCAL = &JSONValueMergeExpr{Type: JSONMergePatchType, JSONDoc: yyDollar[3].exprUnion(), JSONDocList: yyDollar[5].exprsUnion()} } yyVAL.union = yyLOCAL - case 1321: + case 1332: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6625 +//line sql.y:6677 { yyLOCAL = &JSONValueMergeExpr{Type: JSONMergePreserveType, JSONDoc: yyDollar[3].exprUnion(), JSONDocList: yyDollar[5].exprsUnion()} } yyVAL.union = yyLOCAL - case 1322: + case 1333: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6629 +//line sql.y:6681 { yyLOCAL = &JSONRemoveExpr{JSONDoc: yyDollar[3].exprUnion(), PathList: yyDollar[5].exprsUnion()} } yyVAL.union = yyLOCAL - case 1323: + case 1334: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6633 +//line sql.y:6685 { yyLOCAL = &JSONUnquoteExpr{JSONValue: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1324: + case 1335: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6637 +//line sql.y:6689 { yyLOCAL = &MultiPolygonExpr{PolygonParams: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1325: + case 1336: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6641 +//line sql.y:6693 { yyLOCAL = &MultiPointExpr{PointParams: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1326: + case 1337: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6645 +//line sql.y:6697 { yyLOCAL = &MultiLinestringExpr{LinestringParams: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1327: + case 1338: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6649 +//line sql.y:6701 { yyLOCAL = &PolygonExpr{LinestringParams: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1328: + case 1339: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6653 +//line sql.y:6705 { yyLOCAL = &LineStringExpr{PointParams: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1329: + case 1340: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6657 +//line sql.y:6709 { yyLOCAL = &PointExpr{XCordinate: yyDollar[3].exprUnion(), YCordinate: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1330: + case 1341: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6661 +//line sql.y:6713 { yyLOCAL = &ArgumentLessWindowExpr{Type: yyDollar[1].argumentLessWindowExprTypeUnion(), OverClause: yyDollar[4].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1331: + case 1342: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6665 +//line sql.y:6717 { yyLOCAL = &FirstOrLastValueExpr{Type: yyDollar[1].firstOrLastValueExprTypeUnion(), Expr: yyDollar[3].exprUnion(), NullTreatmentClause: yyDollar[5].nullTreatmentClauseUnion(), OverClause: yyDollar[6].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1332: + case 1343: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Expr -//line sql.y:6669 +//line sql.y:6721 { yyLOCAL = &NtileExpr{N: yyDollar[3].exprUnion(), OverClause: yyDollar[5].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1333: + case 1344: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL Expr -//line sql.y:6673 +//line sql.y:6725 { 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 1334: + case 1345: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6677 +//line sql.y:6729 { yyLOCAL = &LagLeadExpr{Type: yyDollar[1].lagLeadExprTypeUnion(), Expr: yyDollar[3].exprUnion(), NullTreatmentClause: yyDollar[5].nullTreatmentClauseUnion(), OverClause: yyDollar[6].overClauseUnion()} } yyVAL.union = yyLOCAL - case 1335: + case 1346: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL Expr -//line sql.y:6681 +//line sql.y:6733 { 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 1336: + case 1347: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6685 +//line sql.y:6737 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprAdddate, Date: yyDollar[3].exprUnion(), Interval: yyDollar[6].exprUnion(), Unit: yyDollar[7].intervalTypeUnion()} } yyVAL.union = yyLOCAL - case 1337: + case 1348: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6689 +//line sql.y:6741 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprAdddate, Date: yyDollar[3].exprUnion(), Interval: yyDollar[5].exprUnion(), Unit: IntervalNone} } yyVAL.union = yyLOCAL - case 1338: + case 1349: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6693 +//line sql.y:6745 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprDateAdd, Date: yyDollar[3].exprUnion(), Interval: yyDollar[6].exprUnion(), Unit: yyDollar[7].intervalTypeUnion()} } yyVAL.union = yyLOCAL - case 1339: + case 1350: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6697 +//line sql.y:6749 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprDateSub, Date: yyDollar[3].exprUnion(), Interval: yyDollar[6].exprUnion(), Unit: yyDollar[7].intervalTypeUnion()} } yyVAL.union = yyLOCAL - case 1340: + case 1351: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6701 +//line sql.y:6753 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprSubdate, Date: yyDollar[3].exprUnion(), Interval: yyDollar[6].exprUnion(), Unit: yyDollar[7].intervalTypeUnion()} } yyVAL.union = yyLOCAL - case 1341: + case 1352: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6705 +//line sql.y:6757 { yyLOCAL = &IntervalDateExpr{Syntax: IntervalDateExprSubdate, Date: yyDollar[3].exprUnion(), Interval: yyDollar[5].exprUnion(), Unit: IntervalNone} } yyVAL.union = yyLOCAL - case 1346: + case 1357: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:6715 +//line sql.y:6767 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1347: + case 1358: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:6719 +//line sql.y:6771 { yyLOCAL = NewIntLiteral(yyDollar[1].str) } yyVAL.union = yyLOCAL - case 1348: + case 1359: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:6723 +//line sql.y:6775 { yyLOCAL = yyDollar[1].variableUnion() } yyVAL.union = yyLOCAL - case 1349: + case 1360: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:6727 +//line sql.y:6779 { yyLOCAL = parseBindVariable(yylex, yyDollar[1].str[1:]) } yyVAL.union = yyLOCAL - case 1350: + case 1361: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Expr -//line sql.y:6732 +//line sql.y:6784 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1351: + case 1362: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:6736 +//line sql.y:6788 { yyLOCAL = yyDollar[2].exprUnion() } yyVAL.union = yyLOCAL - case 1352: + case 1363: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6742 +//line sql.y:6794 { yyLOCAL = &RegexpInstrExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1353: + case 1364: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6746 +//line sql.y:6798 { yyLOCAL = &RegexpInstrExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Position: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1354: + case 1365: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL Expr -//line sql.y:6750 +//line sql.y:6802 { yyLOCAL = &RegexpInstrExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Position: yyDollar[7].exprUnion(), Occurrence: yyDollar[9].exprUnion()} } yyVAL.union = yyLOCAL - case 1355: + case 1366: yyDollar = yyS[yypt-12 : yypt+1] var yyLOCAL Expr -//line sql.y:6754 +//line sql.y:6806 { 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 1356: + case 1367: yyDollar = yyS[yypt-14 : yypt+1] var yyLOCAL Expr -//line sql.y:6758 +//line sql.y:6810 { // 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 1357: + case 1368: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6763 +//line sql.y:6815 { yyLOCAL = &RegexpLikeExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1358: + case 1369: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6767 +//line sql.y:6819 { yyLOCAL = &RegexpLikeExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), MatchType: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1359: + case 1370: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6771 +//line sql.y:6823 { yyLOCAL = &RegexpReplaceExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Repl: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1360: + case 1371: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL Expr -//line sql.y:6775 +//line sql.y:6827 { yyLOCAL = &RegexpReplaceExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Repl: yyDollar[7].exprUnion(), Position: yyDollar[9].exprUnion()} } yyVAL.union = yyLOCAL - case 1361: + case 1372: yyDollar = yyS[yypt-12 : yypt+1] var yyLOCAL Expr -//line sql.y:6779 +//line sql.y:6831 { 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 1362: + case 1373: yyDollar = yyS[yypt-14 : yypt+1] var yyLOCAL Expr -//line sql.y:6783 +//line sql.y:6835 { // 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 1363: + case 1374: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6788 +//line sql.y:6840 { yyLOCAL = &RegexpSubstrExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1364: + case 1375: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6792 +//line sql.y:6844 { yyLOCAL = &RegexpSubstrExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Position: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1365: + case 1376: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL Expr -//line sql.y:6796 +//line sql.y:6848 { yyLOCAL = &RegexpSubstrExpr{Expr: yyDollar[3].exprUnion(), Pattern: yyDollar[5].exprUnion(), Position: yyDollar[7].exprUnion(), Occurrence: yyDollar[9].exprUnion()} } yyVAL.union = yyLOCAL - case 1366: + case 1377: yyDollar = yyS[yypt-12 : yypt+1] var yyLOCAL Expr -//line sql.y:6800 +//line sql.y:6852 { // 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 1367: + case 1378: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6807 +//line sql.y:6859 { yyLOCAL = &ExtractValueExpr{Fragment: yyDollar[3].exprUnion(), XPathExpr: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1368: + case 1379: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6811 +//line sql.y:6863 { yyLOCAL = &UpdateXMLExpr{Target: yyDollar[3].exprUnion(), XPathExpr: yyDollar[5].exprUnion(), NewXML: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1369: + case 1380: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6817 +//line sql.y:6869 { yyLOCAL = &PerformanceSchemaFuncExpr{Type: FormatBytesType, Argument: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1370: + case 1381: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6821 +//line sql.y:6873 { yyLOCAL = &PerformanceSchemaFuncExpr{Type: FormatPicoTimeType, Argument: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1371: + case 1382: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Expr -//line sql.y:6825 +//line sql.y:6877 { yyLOCAL = &PerformanceSchemaFuncExpr{Type: PsCurrentThreadIDType} } yyVAL.union = yyLOCAL - case 1372: + case 1383: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6829 +//line sql.y:6881 { yyLOCAL = &PerformanceSchemaFuncExpr{Type: PsThreadIDType, Argument: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1373: + case 1384: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6835 +//line sql.y:6887 { yyLOCAL = >IDFuncExpr{Type: GTIDSubsetType, Set1: yyDollar[3].exprUnion(), Set2: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1374: + case 1385: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6839 +//line sql.y:6891 { yyLOCAL = >IDFuncExpr{Type: GTIDSubtractType, Set1: yyDollar[3].exprUnion(), Set2: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1375: + case 1386: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6843 +//line sql.y:6895 { yyLOCAL = >IDFuncExpr{Type: WaitForExecutedGTIDSetType, Set1: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1376: + case 1387: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6847 +//line sql.y:6899 { yyLOCAL = >IDFuncExpr{Type: WaitForExecutedGTIDSetType, Set1: yyDollar[3].exprUnion(), Timeout: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1377: + case 1388: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:6851 +//line sql.y:6903 { yyLOCAL = >IDFuncExpr{Type: WaitUntilSQLThreadAfterGTIDSType, Set1: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1378: + case 1389: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL Expr -//line sql.y:6855 +//line sql.y:6907 { yyLOCAL = >IDFuncExpr{Type: WaitUntilSQLThreadAfterGTIDSType, Set1: yyDollar[3].exprUnion(), Timeout: yyDollar[5].exprUnion()} } yyVAL.union = yyLOCAL - case 1379: + case 1390: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL Expr -//line sql.y:6859 +//line sql.y:6911 { yyLOCAL = >IDFuncExpr{Type: WaitUntilSQLThreadAfterGTIDSType, Set1: yyDollar[3].exprUnion(), Timeout: yyDollar[5].exprUnion(), Channel: yyDollar[7].exprUnion()} } yyVAL.union = yyLOCAL - case 1380: + case 1391: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:6864 +//line sql.y:6916 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1381: + case 1392: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:6868 +//line sql.y:6920 { yyLOCAL = yyDollar[2].convertTypeUnion() } yyVAL.union = yyLOCAL - case 1382: + case 1393: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6874 +//line sql.y:6926 { yyLOCAL = IntervalDayHour } yyVAL.union = yyLOCAL - case 1383: + case 1394: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6878 +//line sql.y:6930 { yyLOCAL = IntervalDayMicrosecond } yyVAL.union = yyLOCAL - case 1384: + case 1395: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6882 +//line sql.y:6934 { yyLOCAL = IntervalDayMinute } yyVAL.union = yyLOCAL - case 1385: + case 1396: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6886 +//line sql.y:6938 { yyLOCAL = IntervalDaySecond } yyVAL.union = yyLOCAL - case 1386: + case 1397: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6890 +//line sql.y:6942 { yyLOCAL = IntervalHourMicrosecond } yyVAL.union = yyLOCAL - case 1387: + case 1398: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6894 +//line sql.y:6946 { yyLOCAL = IntervalHourMinute } yyVAL.union = yyLOCAL - case 1388: + case 1399: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6898 +//line sql.y:6950 { yyLOCAL = IntervalHourSecond } yyVAL.union = yyLOCAL - case 1389: + case 1400: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6902 +//line sql.y:6954 { yyLOCAL = IntervalMinuteMicrosecond } yyVAL.union = yyLOCAL - case 1390: + case 1401: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6906 +//line sql.y:6958 { yyLOCAL = IntervalMinuteSecond } yyVAL.union = yyLOCAL - case 1391: + case 1402: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6910 +//line sql.y:6962 { yyLOCAL = IntervalSecondMicrosecond } yyVAL.union = yyLOCAL - case 1392: + case 1403: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6914 +//line sql.y:6966 { yyLOCAL = IntervalYearMonth } yyVAL.union = yyLOCAL - case 1393: + case 1404: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6918 +//line sql.y:6970 { yyLOCAL = IntervalDay } yyVAL.union = yyLOCAL - case 1394: + case 1405: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6922 +//line sql.y:6974 { yyLOCAL = IntervalWeek } yyVAL.union = yyLOCAL - case 1395: + case 1406: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6926 +//line sql.y:6978 { yyLOCAL = IntervalHour } yyVAL.union = yyLOCAL - case 1396: + case 1407: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6930 +//line sql.y:6982 { yyLOCAL = IntervalMinute } yyVAL.union = yyLOCAL - case 1397: + case 1408: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6934 +//line sql.y:6986 { yyLOCAL = IntervalMonth } yyVAL.union = yyLOCAL - case 1398: + case 1409: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6938 +//line sql.y:6990 { yyLOCAL = IntervalQuarter } yyVAL.union = yyLOCAL - case 1399: + case 1410: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6942 +//line sql.y:6994 { yyLOCAL = IntervalSecond } yyVAL.union = yyLOCAL - case 1400: + case 1411: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6946 +//line sql.y:6998 { yyLOCAL = IntervalMicrosecond } yyVAL.union = yyLOCAL - case 1401: + case 1412: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6950 +//line sql.y:7002 { yyLOCAL = IntervalYear } yyVAL.union = yyLOCAL - case 1402: + case 1413: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6956 +//line sql.y:7008 { yyLOCAL = IntervalDay } yyVAL.union = yyLOCAL - case 1403: + case 1414: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6960 +//line sql.y:7012 { yyLOCAL = IntervalWeek } yyVAL.union = yyLOCAL - case 1404: + case 1415: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6964 +//line sql.y:7016 { yyLOCAL = IntervalHour } yyVAL.union = yyLOCAL - case 1405: + case 1416: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6968 +//line sql.y:7020 { yyLOCAL = IntervalMinute } yyVAL.union = yyLOCAL - case 1406: + case 1417: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6972 +//line sql.y:7024 { yyLOCAL = IntervalMonth } yyVAL.union = yyLOCAL - case 1407: + case 1418: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6976 +//line sql.y:7028 { yyLOCAL = IntervalQuarter } yyVAL.union = yyLOCAL - case 1408: + case 1419: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6980 +//line sql.y:7032 { yyLOCAL = IntervalSecond } yyVAL.union = yyLOCAL - case 1409: + case 1420: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6984 +//line sql.y:7036 { yyLOCAL = IntervalMicrosecond } yyVAL.union = yyLOCAL - case 1410: + case 1421: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6988 +//line sql.y:7040 { yyLOCAL = IntervalYear } yyVAL.union = yyLOCAL - case 1411: + case 1422: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6992 +//line sql.y:7044 { yyLOCAL = IntervalDay } yyVAL.union = yyLOCAL - case 1412: + case 1423: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:6996 +//line sql.y:7048 { yyLOCAL = IntervalWeek } yyVAL.union = yyLOCAL - case 1413: + case 1424: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:7000 +//line sql.y:7052 { yyLOCAL = IntervalHour } yyVAL.union = yyLOCAL - case 1414: + case 1425: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:7004 +//line sql.y:7056 { yyLOCAL = IntervalMinute } yyVAL.union = yyLOCAL - case 1415: + case 1426: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:7008 +//line sql.y:7060 { yyLOCAL = IntervalMonth } yyVAL.union = yyLOCAL - case 1416: + case 1427: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:7012 +//line sql.y:7064 { yyLOCAL = IntervalQuarter } yyVAL.union = yyLOCAL - case 1417: + case 1428: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:7016 +//line sql.y:7068 { yyLOCAL = IntervalSecond } yyVAL.union = yyLOCAL - case 1418: + case 1429: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:7020 +//line sql.y:7072 { yyLOCAL = IntervalMicrosecond } yyVAL.union = yyLOCAL - case 1419: + case 1430: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL IntervalType -//line sql.y:7024 +//line sql.y:7076 { yyLOCAL = IntervalYear } yyVAL.union = yyLOCAL - case 1422: + case 1433: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int -//line sql.y:7034 +//line sql.y:7086 { yyLOCAL = 0 } yyVAL.union = yyLOCAL - case 1423: + case 1434: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL int -//line sql.y:7038 +//line sql.y:7090 { yyLOCAL = 0 } yyVAL.union = yyLOCAL - case 1424: + case 1435: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int -//line sql.y:7042 +//line sql.y:7094 { yyLOCAL = convertStringToInt(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 1425: + case 1436: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:7052 +//line sql.y:7104 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("if"), Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1426: + case 1437: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:7056 +//line sql.y:7108 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("database"), Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1427: + case 1438: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:7060 +//line sql.y:7112 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("schema"), Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1428: + case 1439: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:7064 +//line sql.y:7116 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("mod"), Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1429: + case 1440: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Expr -//line sql.y:7068 +//line sql.y:7120 { yyLOCAL = &FuncExpr{Name: NewIdentifierCI("replace"), Exprs: yyDollar[3].exprsUnion()} } yyVAL.union = yyLOCAL - case 1430: + case 1441: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL MatchExprOption -//line sql.y:7074 +//line sql.y:7126 { yyLOCAL = NoOption } yyVAL.union = yyLOCAL - case 1431: + case 1442: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL MatchExprOption -//line sql.y:7078 +//line sql.y:7130 { yyLOCAL = BooleanModeOpt } yyVAL.union = yyLOCAL - case 1432: + case 1443: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL MatchExprOption -//line sql.y:7082 +//line sql.y:7134 { yyLOCAL = NaturalLanguageModeOpt } yyVAL.union = yyLOCAL - case 1433: + case 1444: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL MatchExprOption -//line sql.y:7086 +//line sql.y:7138 { yyLOCAL = NaturalLanguageModeWithQueryExpansionOpt } yyVAL.union = yyLOCAL - case 1434: + case 1445: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL MatchExprOption -//line sql.y:7090 +//line sql.y:7142 { yyLOCAL = QueryExpansionOpt } yyVAL.union = yyLOCAL - case 1435: + case 1446: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7096 +//line sql.y:7148 { yyVAL.str = string(yyDollar[1].identifierCI.String()) } - case 1436: + case 1447: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7100 +//line sql.y:7152 { yyVAL.str = string(yyDollar[1].str) } - case 1437: + case 1448: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7104 +//line sql.y:7156 { yyVAL.str = string(yyDollar[1].str) } - case 1438: + case 1449: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7110 +//line sql.y:7162 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1439: + case 1450: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7114 +//line sql.y:7166 { yyLOCAL = &ConvertType{Type: string(yyDollar[2].str), Length: ptr.Of(convertStringToInt(yyDollar[4].str))} } yyVAL.union = yyLOCAL - case 1440: + case 1451: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7118 +//line sql.y:7170 { yyLOCAL = &ConvertType{Type: string(yyDollar[2].str), Length: ptr.Of(convertStringToInt(yyDollar[4].str))} } yyVAL.union = yyLOCAL - case 1441: + case 1452: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7124 +//line sql.y:7176 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } yyVAL.union = yyLOCAL - case 1442: + case 1453: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7128 +//line sql.y:7180 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion(), Charset: yyDollar[3].columnCharset} } yyVAL.union = yyLOCAL - case 1443: + case 1454: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7132 +//line sql.y:7184 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1444: + case 1455: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7136 +//line sql.y:7188 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } yyVAL.union = yyLOCAL - case 1445: + case 1456: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7140 +//line sql.y:7192 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} yyLOCAL.Length = yyDollar[2].LengthScaleOption.Length yyLOCAL.Scale = yyDollar[2].LengthScaleOption.Scale } yyVAL.union = yyLOCAL - case 1446: + case 1457: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7146 +//line sql.y:7198 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1447: + case 1458: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7150 +//line sql.y:7202 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } yyVAL.union = yyLOCAL - case 1448: + case 1459: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7154 +//line sql.y:7206 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1449: + case 1460: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7158 +//line sql.y:7210 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1450: + case 1461: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7162 +//line sql.y:7214 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } yyVAL.union = yyLOCAL - case 1451: + case 1462: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7166 +//line sql.y:7218 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1452: + case 1463: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7170 +//line sql.y:7222 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1453: + case 1464: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7174 +//line sql.y:7226 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str), Length: yyDollar[2].intPtrUnion()} } yyVAL.union = yyLOCAL - case 1454: + case 1465: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7178 +//line sql.y:7230 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1455: + case 1466: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ConvertType -//line sql.y:7182 +//line sql.y:7234 { yyLOCAL = &ConvertType{Type: string(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1456: + case 1467: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:7188 +//line sql.y:7240 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1457: + case 1468: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:7192 +//line sql.y:7244 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1458: + case 1469: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Expr -//line sql.y:7197 +//line sql.y:7249 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1459: + case 1470: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7201 +//line sql.y:7253 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1460: + case 1471: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7206 +//line sql.y:7258 { yyVAL.str = string("") } - case 1461: + case 1472: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7210 +//line sql.y:7262 { yyVAL.str = encodeSQLString(yyDollar[2].str) } - case 1462: + case 1473: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*When -//line sql.y:7216 +//line sql.y:7268 { yyLOCAL = []*When{yyDollar[1].whenUnion()} } yyVAL.union = yyLOCAL - case 1463: + case 1474: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7220 +//line sql.y:7272 { yySLICE := (*[]*When)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[2].whenUnion()) } - case 1464: + case 1475: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *When -//line sql.y:7226 +//line sql.y:7278 { yyLOCAL = &When{Cond: yyDollar[2].exprUnion(), Val: yyDollar[4].exprUnion()} } yyVAL.union = yyLOCAL - case 1465: + case 1476: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Expr -//line sql.y:7231 +//line sql.y:7283 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1466: + case 1477: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:7235 +//line sql.y:7287 { yyLOCAL = yyDollar[2].exprUnion() } yyVAL.union = yyLOCAL - case 1467: + case 1478: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ColName -//line sql.y:7241 +//line sql.y:7293 { yyLOCAL = &ColName{Name: yyDollar[1].identifierCI} } yyVAL.union = yyLOCAL - case 1468: + case 1479: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *ColName -//line sql.y:7245 +//line sql.y:7297 { yyLOCAL = &ColName{Name: NewIdentifierCI(string(yyDollar[1].str))} } yyVAL.union = yyLOCAL - case 1469: + case 1480: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *ColName -//line sql.y:7249 +//line sql.y:7301 { yyLOCAL = &ColName{Qualifier: TableName{Name: yyDollar[1].identifierCS}, Name: yyDollar[3].identifierCI} } yyVAL.union = yyLOCAL - case 1470: + case 1481: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *ColName -//line sql.y:7253 +//line sql.y:7305 { yyLOCAL = &ColName{Qualifier: TableName{Qualifier: yyDollar[1].identifierCS, Name: yyDollar[3].identifierCS}, Name: yyDollar[5].identifierCI} } yyVAL.union = yyLOCAL - case 1471: + case 1482: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7259 +//line sql.y:7311 { yyLOCAL = yyDollar[1].colNameUnion() } yyVAL.union = yyLOCAL - case 1472: + case 1483: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7263 +//line sql.y:7315 { yyLOCAL = &Offset{V: convertStringToInt(yyDollar[1].str)} } yyVAL.union = yyLOCAL - case 1473: + case 1484: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7269 +//line sql.y:7321 { // TODO(sougou): Deprecate this construct. if yyDollar[1].identifierCI.Lowered() != "value" { @@ -21240,442 +21354,442 @@ yydefault: yyLOCAL = NewIntLiteral("1") } yyVAL.union = yyLOCAL - case 1474: + case 1485: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:7278 +//line sql.y:7330 { yyLOCAL = NewIntLiteral(yyDollar[1].str) } yyVAL.union = yyLOCAL - case 1475: + case 1486: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:7282 +//line sql.y:7334 { yyLOCAL = parseBindVariable(yylex, yyDollar[1].str[1:]) } yyVAL.union = yyLOCAL - case 1476: + case 1487: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *GroupBy -//line sql.y:7287 +//line sql.y:7339 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1477: + case 1488: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *GroupBy -//line sql.y:7291 +//line sql.y:7343 { yyLOCAL = &GroupBy{Exprs: yyDollar[3].exprsUnion(), WithRollup: yyDollar[4].booleanUnion()} } yyVAL.union = yyLOCAL - case 1478: + case 1489: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:7296 +//line sql.y:7348 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1479: + case 1490: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:7300 +//line sql.y:7352 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1480: + case 1491: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Expr -//line sql.y:7306 +//line sql.y:7358 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1481: + case 1492: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Expr -//line sql.y:7310 +//line sql.y:7362 { yyLOCAL = yyDollar[2].exprUnion() } yyVAL.union = yyLOCAL - case 1482: + case 1493: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *NamedWindow -//line sql.y:7316 +//line sql.y:7368 { yyLOCAL = &NamedWindow{yyDollar[2].windowDefinitionsUnion()} } yyVAL.union = yyLOCAL - case 1483: + case 1494: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL NamedWindows -//line sql.y:7322 +//line sql.y:7374 { yyLOCAL = NamedWindows{yyDollar[1].namedWindowUnion()} } yyVAL.union = yyLOCAL - case 1484: + case 1495: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7326 +//line sql.y:7378 { yySLICE := (*NamedWindows)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].namedWindowUnion()) } - case 1485: + case 1496: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL NamedWindows -//line sql.y:7331 +//line sql.y:7383 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1486: + case 1497: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL NamedWindows -//line sql.y:7335 +//line sql.y:7387 { yyLOCAL = yyDollar[1].namedWindowsUnion() } yyVAL.union = yyLOCAL - case 1487: + case 1498: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL OrderBy -//line sql.y:7340 +//line sql.y:7392 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1488: + case 1499: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL OrderBy -//line sql.y:7344 +//line sql.y:7396 { yyLOCAL = yyDollar[1].orderByUnion() } yyVAL.union = yyLOCAL - case 1489: + case 1500: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL OrderBy -//line sql.y:7350 +//line sql.y:7402 { yyLOCAL = yyDollar[3].orderByUnion() } yyVAL.union = yyLOCAL - case 1490: + case 1501: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL OrderBy -//line sql.y:7356 +//line sql.y:7408 { yyLOCAL = OrderBy{yyDollar[1].orderUnion()} } yyVAL.union = yyLOCAL - case 1491: + case 1502: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7360 +//line sql.y:7412 { yySLICE := (*OrderBy)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].orderUnion()) } - case 1492: + case 1503: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *Order -//line sql.y:7366 +//line sql.y:7418 { yyLOCAL = &Order{Expr: yyDollar[1].exprUnion(), Direction: yyDollar[2].orderDirectionUnion()} } yyVAL.union = yyLOCAL - case 1493: + case 1504: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL OrderDirection -//line sql.y:7371 +//line sql.y:7423 { yyLOCAL = AscOrder } yyVAL.union = yyLOCAL - case 1494: + case 1505: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL OrderDirection -//line sql.y:7375 +//line sql.y:7427 { yyLOCAL = AscOrder } yyVAL.union = yyLOCAL - case 1495: + case 1506: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL OrderDirection -//line sql.y:7379 +//line sql.y:7431 { yyLOCAL = DescOrder } yyVAL.union = yyLOCAL - case 1496: + case 1507: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *Limit -//line sql.y:7384 +//line sql.y:7436 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1497: + case 1508: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Limit -//line sql.y:7388 +//line sql.y:7440 { yyLOCAL = yyDollar[1].limitUnion() } yyVAL.union = yyLOCAL - case 1498: + case 1509: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *Limit -//line sql.y:7394 +//line sql.y:7446 { yyLOCAL = &Limit{Rowcount: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 1499: + case 1510: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *Limit -//line sql.y:7398 +//line sql.y:7450 { yyLOCAL = &Limit{Offset: yyDollar[2].exprUnion(), Rowcount: yyDollar[4].exprUnion()} } yyVAL.union = yyLOCAL - case 1500: + case 1511: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *Limit -//line sql.y:7402 +//line sql.y:7454 { yyLOCAL = &Limit{Offset: yyDollar[4].exprUnion(), Rowcount: yyDollar[2].exprUnion()} } yyVAL.union = yyLOCAL - case 1501: + case 1512: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:7407 +//line sql.y:7459 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1502: + case 1513: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:7411 +//line sql.y:7463 { yyLOCAL = []AlterOption{yyDollar[1].alterOptionUnion(), yyDollar[2].alterOptionUnion()} } yyVAL.union = yyLOCAL - case 1503: + case 1514: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:7415 +//line sql.y:7467 { yyLOCAL = []AlterOption{yyDollar[1].alterOptionUnion(), yyDollar[2].alterOptionUnion()} } yyVAL.union = yyLOCAL - case 1504: + case 1515: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:7419 +//line sql.y:7471 { yyLOCAL = []AlterOption{yyDollar[1].alterOptionUnion()} } yyVAL.union = yyLOCAL - case 1505: + case 1516: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []AlterOption -//line sql.y:7423 +//line sql.y:7475 { yyLOCAL = []AlterOption{yyDollar[1].alterOptionUnion()} } yyVAL.union = yyLOCAL - case 1506: + case 1517: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7430 +//line sql.y:7482 { yyLOCAL = &LockOption{Type: DefaultType} } yyVAL.union = yyLOCAL - case 1507: + case 1518: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7434 +//line sql.y:7486 { yyLOCAL = &LockOption{Type: NoneType} } yyVAL.union = yyLOCAL - case 1508: + case 1519: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7438 +//line sql.y:7490 { yyLOCAL = &LockOption{Type: SharedType} } yyVAL.union = yyLOCAL - case 1509: + case 1520: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7442 +//line sql.y:7494 { yyLOCAL = &LockOption{Type: ExclusiveType} } yyVAL.union = yyLOCAL - case 1510: + case 1521: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7448 +//line sql.y:7500 { yyLOCAL = AlgorithmValue(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1511: + case 1522: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7452 +//line sql.y:7504 { yyLOCAL = AlgorithmValue(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1512: + case 1523: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7456 +//line sql.y:7508 { yyLOCAL = AlgorithmValue(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1513: + case 1524: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL AlterOption -//line sql.y:7460 +//line sql.y:7512 { yyLOCAL = AlgorithmValue(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1514: + case 1525: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7465 +//line sql.y:7517 { yyVAL.str = "" } - case 1515: + case 1526: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7469 +//line sql.y:7521 { yyVAL.str = string(yyDollar[3].str) } - case 1516: + case 1527: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7473 +//line sql.y:7525 { yyVAL.str = string(yyDollar[3].str) } - case 1517: + case 1528: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7477 +//line sql.y:7529 { yyVAL.str = string(yyDollar[3].str) } - case 1518: + case 1529: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7482 +//line sql.y:7534 { yyVAL.str = "" } - case 1519: + case 1530: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7486 +//line sql.y:7538 { yyVAL.str = yyDollar[3].str } - case 1520: + case 1531: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7492 +//line sql.y:7544 { yyVAL.str = string(yyDollar[1].str) } - case 1521: + case 1532: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7496 +//line sql.y:7548 { yyVAL.str = string(yyDollar[1].str) } - case 1522: + case 1533: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7501 +//line sql.y:7553 { yyVAL.str = "" } - case 1523: + case 1534: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:7505 +//line sql.y:7557 { yyVAL.str = yyDollar[2].str } - case 1524: + case 1535: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7510 +//line sql.y:7562 { yyVAL.str = "cascaded" } - case 1525: + case 1536: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7514 +//line sql.y:7566 { yyVAL.str = string(yyDollar[1].str) } - case 1526: + case 1537: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7518 +//line sql.y:7570 { yyVAL.str = string(yyDollar[1].str) } - case 1527: + case 1538: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *Definer -//line sql.y:7523 +//line sql.y:7575 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1528: + case 1539: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *Definer -//line sql.y:7527 +//line sql.y:7579 { yyLOCAL = yyDollar[3].definerUnion() } yyVAL.union = yyLOCAL - case 1529: + case 1540: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Definer -//line sql.y:7533 +//line sql.y:7585 { yyLOCAL = &Definer{ Name: string(yyDollar[1].str), } } yyVAL.union = yyLOCAL - case 1530: + case 1541: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *Definer -//line sql.y:7539 +//line sql.y:7591 { yyLOCAL = &Definer{ Name: string(yyDollar[1].str), } } yyVAL.union = yyLOCAL - case 1531: + case 1542: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *Definer -//line sql.y:7545 +//line sql.y:7597 { yyLOCAL = &Definer{ Name: yyDollar[1].str, @@ -21683,433 +21797,433 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1532: + case 1543: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7554 +//line sql.y:7606 { yyVAL.str = encodeSQLString(yyDollar[1].str) } - case 1533: + case 1544: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7558 +//line sql.y:7610 { yyVAL.str = formatIdentifier(yyDollar[1].str) } - case 1534: + case 1545: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7563 +//line sql.y:7615 { yyVAL.str = "" } - case 1535: + case 1546: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7567 +//line sql.y:7619 { yyVAL.str = formatAddress(yyDollar[1].str) } - case 1536: + case 1547: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Lock -//line sql.y:7573 +//line sql.y:7625 { yyLOCAL = ForUpdateLock } yyVAL.union = yyLOCAL - case 1537: + case 1548: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Lock -//line sql.y:7577 +//line sql.y:7629 { yyLOCAL = ForUpdateLockNoWait } yyVAL.union = yyLOCAL - case 1538: + case 1549: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Lock -//line sql.y:7581 +//line sql.y:7633 { yyLOCAL = ForUpdateLockSkipLocked } yyVAL.union = yyLOCAL - case 1539: + case 1550: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL Lock -//line sql.y:7585 +//line sql.y:7637 { yyLOCAL = ForShareLock } yyVAL.union = yyLOCAL - case 1540: + case 1551: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Lock -//line sql.y:7589 +//line sql.y:7641 { yyLOCAL = ForShareLockNoWait } yyVAL.union = yyLOCAL - case 1541: + case 1552: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Lock -//line sql.y:7593 +//line sql.y:7645 { yyLOCAL = ForShareLockSkipLocked } yyVAL.union = yyLOCAL - case 1542: + case 1553: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL Lock -//line sql.y:7597 +//line sql.y:7649 { yyLOCAL = ShareModeLock } yyVAL.union = yyLOCAL - case 1543: + case 1554: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL *SelectInto -//line sql.y:7603 +//line sql.y:7655 { 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 1544: + case 1555: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *SelectInto -//line sql.y:7607 +//line sql.y:7659 { yyLOCAL = &SelectInto{Type: IntoDumpfile, FileName: encodeSQLString(yyDollar[3].str), Charset: ColumnCharset{}, FormatOption: "", ExportOption: "", Manifest: "", Overwrite: ""} } yyVAL.union = yyLOCAL - case 1545: + case 1556: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *SelectInto -//line sql.y:7611 +//line sql.y:7663 { yyLOCAL = &SelectInto{Type: IntoOutfile, FileName: encodeSQLString(yyDollar[3].str), Charset: yyDollar[4].columnCharset, FormatOption: "", ExportOption: yyDollar[5].str, Manifest: "", Overwrite: ""} } yyVAL.union = yyLOCAL - case 1546: + case 1557: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7616 +//line sql.y:7668 { yyVAL.str = "" } - case 1547: + case 1558: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7620 +//line sql.y:7672 { yyVAL.str = " format csv" + yyDollar[3].str } - case 1548: + case 1559: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7624 +//line sql.y:7676 { yyVAL.str = " format text" + yyDollar[3].str } - case 1549: + case 1560: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7629 +//line sql.y:7681 { yyVAL.str = "" } - case 1550: + case 1561: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7633 +//line sql.y:7685 { yyVAL.str = " header" } - case 1551: + case 1562: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7638 +//line sql.y:7690 { yyVAL.str = "" } - case 1552: + case 1563: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7642 +//line sql.y:7694 { yyVAL.str = " manifest on" } - case 1553: + case 1564: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7646 +//line sql.y:7698 { yyVAL.str = " manifest off" } - case 1554: + case 1565: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7651 +//line sql.y:7703 { yyVAL.str = "" } - case 1555: + case 1566: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7655 +//line sql.y:7707 { yyVAL.str = " overwrite on" } - case 1556: + case 1567: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7659 +//line sql.y:7711 { yyVAL.str = " overwrite off" } - case 1557: + case 1568: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7665 +//line sql.y:7717 { yyVAL.str = yyDollar[1].str + yyDollar[2].str } - case 1558: + case 1569: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7670 +//line sql.y:7722 { yyVAL.str = "" } - case 1559: + case 1570: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7674 +//line sql.y:7726 { yyVAL.str = " lines" + yyDollar[2].str } - case 1560: + case 1571: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7680 +//line sql.y:7732 { yyVAL.str = yyDollar[1].str } - case 1561: + case 1572: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7684 +//line sql.y:7736 { yyVAL.str = yyDollar[1].str + yyDollar[2].str } - case 1562: + case 1573: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7690 +//line sql.y:7742 { yyVAL.str = " starting by " + encodeSQLString(yyDollar[3].str) } - case 1563: + case 1574: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7694 +//line sql.y:7746 { yyVAL.str = " terminated by " + encodeSQLString(yyDollar[3].str) } - case 1564: + case 1575: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7699 +//line sql.y:7751 { yyVAL.str = "" } - case 1565: + case 1576: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7703 +//line sql.y:7755 { yyVAL.str = " " + yyDollar[1].str + yyDollar[2].str } - case 1566: + case 1577: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7709 +//line sql.y:7761 { yyVAL.str = yyDollar[1].str } - case 1567: + case 1578: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7713 +//line sql.y:7765 { yyVAL.str = yyDollar[1].str + yyDollar[2].str } - case 1568: + case 1579: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7719 +//line sql.y:7771 { yyVAL.str = " terminated by " + encodeSQLString(yyDollar[3].str) } - case 1569: + case 1580: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:7723 +//line sql.y:7775 { yyVAL.str = yyDollar[1].str + " enclosed by " + encodeSQLString(yyDollar[4].str) } - case 1570: + case 1581: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7727 +//line sql.y:7779 { yyVAL.str = " escaped by " + encodeSQLString(yyDollar[3].str) } - case 1571: + case 1582: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7732 +//line sql.y:7784 { yyVAL.str = "" } - case 1572: + case 1583: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7736 +//line sql.y:7788 { yyVAL.str = " optionally" } - case 1573: + case 1584: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *Insert -//line sql.y:7749 +//line sql.y:7801 { yyLOCAL = &Insert{Rows: yyDollar[2].valuesUnion(), RowAlias: yyDollar[3].rowAliasUnion()} } yyVAL.union = yyLOCAL - case 1574: + case 1585: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *Insert -//line sql.y:7753 +//line sql.y:7805 { yyLOCAL = &Insert{Rows: yyDollar[1].selStmtUnion()} } yyVAL.union = yyLOCAL - case 1575: + case 1586: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *Insert -//line sql.y:7757 +//line sql.y:7809 { yyLOCAL = &Insert{Columns: yyDollar[2].columnsUnion(), Rows: yyDollar[5].valuesUnion(), RowAlias: yyDollar[6].rowAliasUnion()} } yyVAL.union = yyLOCAL - case 1576: + case 1587: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *Insert -//line sql.y:7761 +//line sql.y:7813 { yyLOCAL = &Insert{Columns: []IdentifierCI{}, Rows: yyDollar[4].valuesUnion(), RowAlias: yyDollar[5].rowAliasUnion()} } yyVAL.union = yyLOCAL - case 1577: + case 1588: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *Insert -//line sql.y:7765 +//line sql.y:7817 { yyLOCAL = &Insert{Columns: yyDollar[2].columnsUnion(), Rows: yyDollar[4].selStmtUnion()} } yyVAL.union = yyLOCAL - case 1578: + case 1589: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Columns -//line sql.y:7771 +//line sql.y:7823 { yyLOCAL = Columns{yyDollar[1].identifierCI} } yyVAL.union = yyLOCAL - case 1579: + case 1590: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Columns -//line sql.y:7775 +//line sql.y:7827 { yyLOCAL = Columns{yyDollar[3].identifierCI} } yyVAL.union = yyLOCAL - case 1580: + case 1591: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7779 +//line sql.y:7831 { yySLICE := (*Columns)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].identifierCI) } - case 1581: + case 1592: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:7783 +//line sql.y:7835 { yySLICE := (*Columns)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[5].identifierCI) } - case 1582: + case 1593: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *RowAlias -//line sql.y:7788 +//line sql.y:7840 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1583: + case 1594: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *RowAlias -//line sql.y:7792 +//line sql.y:7844 { yyLOCAL = &RowAlias{TableName: yyDollar[2].identifierCS} } yyVAL.union = yyLOCAL - case 1584: + case 1595: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *RowAlias -//line sql.y:7796 +//line sql.y:7848 { yyLOCAL = &RowAlias{TableName: yyDollar[2].identifierCS, Columns: yyDollar[4].columnsUnion()} } yyVAL.union = yyLOCAL - case 1585: + case 1596: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL UpdateExprs -//line sql.y:7801 +//line sql.y:7853 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1586: + case 1597: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL UpdateExprs -//line sql.y:7805 +//line sql.y:7857 { yyLOCAL = yyDollar[5].updateExprsUnion() } yyVAL.union = yyLOCAL - case 1587: + case 1598: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Values -//line sql.y:7811 +//line sql.y:7863 { yyLOCAL = Values{yyDollar[1].valTupleUnion()} } yyVAL.union = yyLOCAL - case 1588: + case 1599: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7815 +//line sql.y:7867 { yySLICE := (*Values)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].valTupleUnion()) } - case 1589: + case 1600: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL ValTuple -//line sql.y:7821 +//line sql.y:7873 { yyLOCAL = yyDollar[1].valTupleUnion() } yyVAL.union = yyLOCAL - case 1590: + case 1601: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL ValTuple -//line sql.y:7825 +//line sql.y:7877 { yyLOCAL = ValTuple{} } yyVAL.union = yyLOCAL - case 1591: + case 1602: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL ValTuple -//line sql.y:7831 +//line sql.y:7883 { yyLOCAL = ValTuple(yyDollar[2].exprsUnion()) } yyVAL.union = yyLOCAL - case 1592: + case 1603: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL ValTuple -//line sql.y:7835 +//line sql.y:7887 { yyLOCAL = ValTuple(yyDollar[3].exprsUnion()) } yyVAL.union = yyLOCAL - case 1593: + case 1604: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7840 +//line sql.y:7892 { if len(yyDollar[1].valTupleUnion()) == 1 { yyLOCAL = yyDollar[1].valTupleUnion()[0] @@ -22118,300 +22232,300 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1594: + case 1605: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL UpdateExprs -//line sql.y:7850 +//line sql.y:7902 { yyLOCAL = UpdateExprs{yyDollar[1].updateExprUnion()} } yyVAL.union = yyLOCAL - case 1595: + case 1606: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:7854 +//line sql.y:7906 { yySLICE := (*UpdateExprs)(yyIaddr(yyVAL.union)) *yySLICE = append(*yySLICE, yyDollar[3].updateExprUnion()) } - case 1596: + case 1607: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *UpdateExpr -//line sql.y:7860 +//line sql.y:7912 { yyLOCAL = &UpdateExpr{Name: yyDollar[1].colNameUnion(), Expr: yyDollar[3].exprUnion()} } yyVAL.union = yyLOCAL - case 1598: + case 1609: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:7867 +//line sql.y:7919 { yyVAL.str = "charset" } - case 1601: + case 1612: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7877 +//line sql.y:7929 { yyLOCAL = NewStrLiteral(yyDollar[1].identifierCI.String()) } yyVAL.union = yyLOCAL - case 1602: + case 1613: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7881 +//line sql.y:7933 { yyLOCAL = NewStrLiteral(yyDollar[1].str) } yyVAL.union = yyLOCAL - case 1603: + case 1614: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Expr -//line sql.y:7885 +//line sql.y:7937 { yyLOCAL = &Default{} } yyVAL.union = yyLOCAL - case 1606: + case 1617: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:7894 +//line sql.y:7946 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1607: + case 1618: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line sql.y:7896 +//line sql.y:7948 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1608: + case 1619: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:7899 +//line sql.y:7951 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1609: + case 1620: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line sql.y:7901 +//line sql.y:7953 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1610: + case 1621: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line sql.y:7904 +//line sql.y:7956 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1611: + case 1622: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL bool -//line sql.y:7906 +//line sql.y:7958 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1612: + case 1623: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Ignore -//line sql.y:7909 +//line sql.y:7961 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1613: + case 1624: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Ignore -//line sql.y:7911 +//line sql.y:7963 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1614: + case 1625: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7914 +//line sql.y:7966 { yyVAL.empty = struct{}{} } - case 1615: + case 1626: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7916 +//line sql.y:7968 { yyVAL.empty = struct{}{} } - case 1616: + case 1627: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7918 +//line sql.y:7970 { yyVAL.empty = struct{}{} } - case 1617: + case 1628: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL Statement -//line sql.y:7922 +//line sql.y:7974 { yyLOCAL = &CallProc{Name: yyDollar[2].tableName, Params: yyDollar[4].exprsUnion()} } yyVAL.union = yyLOCAL - case 1618: + case 1629: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL Exprs -//line sql.y:7927 +//line sql.y:7979 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1619: + case 1630: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL Exprs -//line sql.y:7931 +//line sql.y:7983 { yyLOCAL = yyDollar[1].exprsUnion() } yyVAL.union = yyLOCAL - case 1620: + case 1631: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*IndexOption -//line sql.y:7936 +//line sql.y:7988 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1621: + case 1632: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*IndexOption -//line sql.y:7938 +//line sql.y:7990 { yyLOCAL = []*IndexOption{yyDollar[1].indexOptionUnion()} } yyVAL.union = yyLOCAL - case 1622: + case 1633: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *IndexOption -//line sql.y:7942 +//line sql.y:7994 { yyLOCAL = &IndexOption{Name: string(yyDollar[1].str), String: string(yyDollar[2].identifierCI.String())} } yyVAL.union = yyLOCAL - case 1623: + case 1634: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7948 +//line sql.y:8000 { yyVAL.identifierCI = yyDollar[1].identifierCI } - case 1624: + case 1635: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7952 +//line sql.y:8004 { yyVAL.identifierCI = NewIdentifierCI(string(yyDollar[1].str)) } - case 1626: + case 1637: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7959 +//line sql.y:8011 { yyVAL.identifierCI = NewIdentifierCI(string(yyDollar[1].str)) } - case 1627: + case 1638: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7965 +//line sql.y:8017 { yyVAL.identifierCS = NewIdentifierCS(string(yyDollar[1].str)) } - case 1628: + case 1639: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7969 +//line sql.y:8021 { yyVAL.identifierCS = NewIdentifierCS(string(yyDollar[1].str)) } - case 1629: + case 1640: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:7975 +//line sql.y:8027 { yyVAL.identifierCS = NewIdentifierCS("") } - case 1630: + case 1641: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7979 +//line sql.y:8031 { yyVAL.identifierCS = yyDollar[1].identifierCS } - case 1632: + case 1643: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:7986 +//line sql.y:8038 { yyVAL.identifierCS = NewIdentifierCS(string(yyDollar[1].str)) } - case 1633: + case 1644: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL Statement -//line sql.y:7992 +//line sql.y:8044 { yyLOCAL = &Kill{Type: yyDollar[2].killTypeUnion(), ProcesslistID: convertStringToUInt64(yyDollar[3].str)} } yyVAL.union = yyLOCAL - case 1634: + case 1645: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL KillType -//line sql.y:7998 +//line sql.y:8050 { yyLOCAL = ConnectionType } yyVAL.union = yyLOCAL - case 1635: + case 1646: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL KillType -//line sql.y:8002 +//line sql.y:8054 { yyLOCAL = ConnectionType } yyVAL.union = yyLOCAL - case 1636: + case 1647: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL KillType -//line sql.y:8006 +//line sql.y:8058 { yyLOCAL = QueryType } yyVAL.union = yyLOCAL - case 2257: + case 2275: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8655 +//line sql.y:8714 { } - case 2258: + case 2276: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8660 +//line sql.y:8719 { } - case 2259: + case 2277: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:8664 +//line sql.y:8723 { skipToEnd(yylex) } - case 2260: + case 2278: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:8669 +//line sql.y:8728 { skipToEnd(yylex) } - case 2261: + case 2279: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8673 +//line sql.y:8732 { skipToEnd(yylex) } - case 2262: + case 2280: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:8677 +//line sql.y:8736 { skipToEnd(yylex) } diff --git a/go/vt/sqlparser/sql.y b/go/vt/sqlparser/sql.y index ba6c2a6081b..dfbeffed71a 100644 --- a/go/vt/sqlparser/sql.y +++ b/go/vt/sqlparser/sql.y @@ -242,6 +242,12 @@ func markBindVariable(yylex yyLexer, bvar string) { // predicates as column modifiers, shifting on a '(' conflicts with reducing the keywords to a non_reserved_keyword. Since we want shifting to // take precedence, we add this precedence to the reduction rules. %nonassoc ANY_SOME +// SELECT_OPTIONS is used to resolve shift-reduce conflicts occurring due to select options that are non-reserved keywords. +// When parsing select_options_opt if we encounter a select option like `SQL_BUFFER_RESULT`, we can either reduce select_options_opt and use it as a table name +// or we can shift and use it as a select option. Since we want the latter option, we want to prioritize shifting over reducing. +// Adding no precedence also works, since shifting is the default, but it reports some conflicts +// We need to add a lower precedence to reducing the select_options_opt rule than shifting. +%nonassoc SELECT_OPTIONS %token LEX_ERROR %left UNION @@ -253,15 +259,16 @@ func markBindVariable(yylex yyLexer, bvar string) { %token DUMPFILE CSV HEADER MANIFEST OVERWRITE STARTING OPTIONALLY %token VALUES LAST_INSERT_ID %token NEXT VALUE SHARE MODE -%token SQL_NO_CACHE SQL_CACHE SQL_CALC_FOUND_ROWS +%token SQL_NO_CACHE SQL_CACHE SQL_CALC_FOUND_ROWS SQL_SMALL_RESULT SQL_BIG_RESULT HIGH_PRIORITY %left JOIN STRAIGHT_JOIN LEFT RIGHT INNER OUTER CROSS NATURAL USE FORCE %left ON USING INPLACE COPY INSTANT ALGORITHM NONE SHARED EXCLUSIVE %left SUBQUERY_AS_EXPR %left '(' ',' ')' -%nonassoc STRING +%nonassoc STRING SQL_BUFFER_RESULT %token ID AT_ID AT_AT_ID HEX NCHAR_STRING INTEGRAL FLOAT DECIMAL HEXNUM COMMENT COMMENT_KEYWORD BITNUM BIT_LITERAL COMPRESSION %token VALUE_ARG LIST_ARG OFFSET_ARG %token JSON_PRETTY JSON_STORAGE_SIZE JSON_STORAGE_FREE JSON_CONTAINS JSON_CONTAINS_PATH JSON_EXTRACT JSON_KEYS JSON_OVERLAPS JSON_SEARCH JSON_VALUE +%token JSON_ARRAYAGG JSON_OBJECTAGG %token EXTRACT %token NULL UNKNOWN TRUE FALSE OFF %token DISCARD IMPORT ENABLE DISABLE TABLESPACE @@ -340,6 +347,8 @@ func markBindVariable(yylex yyLexer, bvar string) { %token GEOMETRY POINT LINESTRING POLYGON GEOMCOLLECTION GEOMETRYCOLLECTION MULTIPOINT MULTILINESTRING MULTIPOLYGON %token ASCII UNICODE // used in CONVERT/CAST types +%nonassoc VECTOR + // Type Modifiers %token NULLX AUTO_INCREMENT APPROXNUM SIGNED UNSIGNED ZEROFILL @@ -544,7 +553,7 @@ func markBindVariable(yylex yyLexer, bvar string) { %type columns_or_fields extended_opt storage_opt %type like_or_where_opt like_opt %type exists_opt not_exists_opt enforced enforced_opt temp_opt full_opt -%type to_opt +%type to_opt for_opt %type reserved_keyword non_reserved_keyword %type sql_id sql_id_opt reserved_sql_id col_alias as_ci_opt %type charset_value @@ -2171,6 +2180,10 @@ char_type: { $$ = &ColumnType{Type: string($1), EnumValues: $3, Charset: $5} } +| VECTOR length_opt + { + $$ = &ColumnType{Type: string($1), Length: $2} + } // need set_values / SetValues ? | SET '(' enum_values ')' charset_opt { @@ -3301,6 +3314,12 @@ alter_statement: UUID: string($4), } } +| ALTER comment_opt VITESS_MIGRATION CLEANUP ALL + { + $$ = &AlterMigration{ + Type: CleanupAllMigrationType, + } + } | ALTER comment_opt VITESS_MIGRATION STRING LAUNCH { $$ = &AlterMigration{ @@ -4217,6 +4236,15 @@ show_statement: { $$ = &Show{&ShowOther{Command: string($2)}} } +| SHOW TRANSACTION STATUS for_opt STRING + { + $$ = &Show{&ShowTransactionStatus{TransactionID: string($5)}} + } + +for_opt: + {} +| FOR + {} extended_opt: /* empty */ @@ -4794,10 +4822,10 @@ deallocate_statement: } select_options_opt: - { + %prec SELECT_OPTIONS { $$ = nil } -| select_options +| select_options %prec SELECT_OPTIONS { $$ = $1 } @@ -4829,10 +4857,26 @@ select_option: { $$ = DistinctStr } +| HIGH_PRIORITY + { + $$ = HighPriorityStr + } | STRAIGHT_JOIN { $$ = StraightJoinHint } +| SQL_BUFFER_RESULT + { + $$ = SQLBufferResultStr + } +| SQL_SMALL_RESULT + { + $$ = SQLSmallResultStr + } +| SQL_BIG_RESULT + { + $$ = SQLBigResultStr + } | SQL_CALC_FOUND_ROWS { $$ = SQLCalcFoundRowsStr @@ -6085,6 +6129,14 @@ UTC_DATE func_paren_opt { $$ = &JSONStorageSizeExpr{ JSONVal: $3} } +| JSON_ARRAYAGG openb expression closeb over_clause_opt + { + $$ = &JSONArrayAgg{Expr: $3, OverClause: $5} + } +| JSON_OBJECTAGG openb expression ',' expression closeb over_clause_opt + { + $$ = &JSONObjectAgg{Key: $3, Value: $5, OverClause: $7} + } | LTRIM openb expression closeb { $$ = &TrimFuncExpr{TrimFuncType:LTrimType, Type: LeadingTrimType, StringArg: $3} @@ -8074,6 +8126,7 @@ reserved_keyword: | GROUPING | GROUPS | HAVING +| HIGH_PRIORITY | IF | IGNORE | IN @@ -8142,6 +8195,8 @@ reserved_keyword: | SET | SHOW | SPATIAL +| SQL_BIG_RESULT +| SQL_SMALL_RESULT | STORED | STRAIGHT_JOIN | SYSDATE @@ -8317,6 +8372,7 @@ non_reserved_keyword: | ISOLATION | JSON | JSON_ARRAY %prec FUNCTION_CALL_NON_KEYWORD +| JSON_ARRAYAGG %prec FUNCTION_CALL_NON_KEYWORD | JSON_ARRAY_APPEND %prec FUNCTION_CALL_NON_KEYWORD | JSON_ARRAY_INSERT %prec FUNCTION_CALL_NON_KEYWORD | JSON_CONTAINS %prec FUNCTION_CALL_NON_KEYWORD @@ -8325,6 +8381,7 @@ non_reserved_keyword: | JSON_EXTRACT %prec FUNCTION_CALL_NON_KEYWORD | JSON_INSERT %prec FUNCTION_CALL_NON_KEYWORD | JSON_KEYS %prec FUNCTION_CALL_NON_KEYWORD +| JSON_OBJECTAGG %prec FUNCTION_CALL_NON_KEYWORD | JSON_MERGE %prec FUNCTION_CALL_NON_KEYWORD | JSON_MERGE_PATCH %prec FUNCTION_CALL_NON_KEYWORD | JSON_MERGE_PRESERVE %prec FUNCTION_CALL_NON_KEYWORD @@ -8486,6 +8543,7 @@ non_reserved_keyword: | SNAPSHOT | SOME %prec ANY_SOME | SQL +| SQL_BUFFER_RESULT | SQL_TSI_DAY | SQL_TSI_HOUR | SQL_TSI_MINUTE @@ -8601,6 +8659,7 @@ non_reserved_keyword: | VARIABLES | VARIANCE %prec FUNCTION_CALL_NON_KEYWORD | VCPU +| VECTOR | VEXPLAIN | VGTID_EXECUTED | VIEW diff --git a/go/vt/sqlparser/testdata/select_cases.txt b/go/vt/sqlparser/testdata/select_cases.txt index 3edec6dae7e..157b2ebfe99 100644 --- a/go/vt/sqlparser/testdata/select_cases.txt +++ b/go/vt/sqlparser/testdata/select_cases.txt @@ -1501,8 +1501,8 @@ END INPUT select sql_big_result distinct t1.a from t1,t2; END -ERROR -syntax error at position 31 near 'distinct' +OUTPUT +select distinct sql_big_result t1.a from t1, t2 END INPUT select * from t1 where a = 'b' and a = 'b'; @@ -1921,8 +1921,8 @@ END INPUT select sql_small_result t2.id, avg(rating+0.0e0) from t2 group by t2.id; END -ERROR -syntax error at position 28 +OUTPUT +select sql_small_result t2.id, avg(rating + 0.0e0) from t2 group by t2.id END INPUT select 12 % null as 'NULL'; @@ -2317,8 +2317,8 @@ END INPUT select sql_big_result trim(t),count(t) from t1 group by t order by t limit 10; END -ERROR -syntax error at position 28 +OUTPUT +select sql_big_result trim(t), count(t) from t1 group by t order by t asc limit 10 END INPUT select cast(rtrim(' 20.06 ') as decimal(19,2)); @@ -3080,7 +3080,7 @@ INPUT select sql_big_result score,count(*) from t1 group by score order by score desc; END OUTPUT -select `sql_big_result` as score, count(*) from t1 group by score order by score desc +select sql_big_result score, count(*) from t1 group by score order by score desc END INPUT select * from information_schema.TABLE_CONSTRAINTS where TABLE_SCHEMA= "test" order by constraint_name; @@ -4022,7 +4022,7 @@ INPUT select SQL_BIG_RESULT distinct from t1, t2 order by 1, 2, 3, 4; END ERROR -syntax error at position 31 near 'distinct' +syntax error at position 36 near 'from' END INPUT select benchmark(100, (select avg(func_26093_b(a, rand())) from table_26093)); @@ -4286,7 +4286,7 @@ INPUT select * from t1 where MATCH a,b AGAINST ('"xt indexes"' IN BOOLEAN MODE); END OUTPUT -select * from t1 where match(a, b) against ('\"xt indexes\"' in boolean mode) +select * from t1 where match(a, b) against ('"xt indexes"' in boolean mode) END INPUT select max(value) from t1 AS m LEFT JOIN t2 AS c1 ON m.c1id = c1.id AND c1.active = 'Yes' LEFT JOIN t3 AS c2 ON m.c2id = c2.id AND c2.active = 'Yes' WHERE m.pid=1 AND (c1.id IS NOT NULL OR c2.id IS NOT NULL); @@ -4831,8 +4831,8 @@ END INPUT select sql_big_result trim(v),count(t) from t1 group by v order by v limit 10; END -ERROR -syntax error at position 28 +OUTPUT +select sql_big_result trim(v), count(t) from t1 group by v order by v asc limit 10 END INPUT select count(distinct x.id_aams) into not_installed from (select * from (select t1.id_aams, t2.* from t1 left join t2 on t2.code_id = vlt_code_id and t1.id_aams = t2.id_game where t1.id_aams = 1715000360 order by t2.id desc ) as g group by g.id_aams having g.id is null ) as x; @@ -5348,7 +5348,7 @@ INPUT select sql_big_result spid,sum(userid) from t1 group by spid order by spid desc; END OUTPUT -select `sql_big_result` as spid, sum(userid) from t1 group by spid order by spid desc +select sql_big_result spid, sum(userid) from t1 group by spid order by spid desc END INPUT select * from t1 where f1='test' and (f2= md5("test") or f2= md5("TEST")); @@ -5660,7 +5660,7 @@ INPUT select * from t1 where MATCH a,b AGAINST ('"text search" "now support"' IN BOOLEAN MODE); END OUTPUT -select * from t1 where match(a, b) against ('\"text search\" \"now support\"' in boolean mode) +select * from t1 where match(a, b) against ('"text search" "now support"' in boolean mode) END INPUT select insert('hello', 1, -18446744073709551616, 'hi'); @@ -6643,8 +6643,8 @@ END INPUT select SQL_BIG_RESULT t1.b from t1, t2 group by t1.b order by 1; END -ERROR -syntax error at position 26 +OUTPUT +select sql_big_result t1.b from t1, t2 group by t1.b order by 1 asc END INPUT select group_concat(c1 order by binary c1 separator '') from t1 group by c1 collate utf32_spanish_ci; @@ -7585,8 +7585,8 @@ END INPUT select sql_buffer_result max(f1) is null from t1; END -ERROR -syntax error at position 30 +OUTPUT +select sql_buffer_result max(f1) is null from t1 END INPUT select substring('hello', -1, -1); @@ -8048,7 +8048,7 @@ INPUT select * from t1 where MATCH a,b AGAINST ('"text i"' IN BOOLEAN MODE); END OUTPUT -select * from t1 where match(a, b) against ('\"text i\"' in boolean mode) +select * from t1 where match(a, b) against ('"text i"' in boolean mode) END INPUT select column_name,data_type,CHARACTER_OCTET_LENGTH, CHARACTER_MAXIMUM_LENGTH from information_schema.columns where table_name='t1' order by column_name; @@ -8144,7 +8144,7 @@ INPUT select * from t1 where MATCH a,b AGAINST ('"support now"' IN BOOLEAN MODE); END OUTPUT -select * from t1 where match(a, b) against ('\"support now\"' in boolean mode) +select * from t1 where match(a, b) against ('"support now"' in boolean mode) END INPUT select hex(inet_aton('127.1.1')); @@ -10640,7 +10640,7 @@ INPUT select sql_big_result c,count(t) from t1 group by c order by c limit 10; END OUTPUT -select `sql_big_result` as c, count(t) from t1 group by c order by c asc limit 10 +select sql_big_result c, count(t) from t1 group by c order by c asc limit 10 END INPUT select * from t3 where b in (select a from t1); @@ -12007,8 +12007,8 @@ END INPUT select sql_small_result t2.id, avg(rating) from t2 group by t2.id; END -ERROR -syntax error at position 28 +OUTPUT +select sql_small_result t2.id, avg(rating) from t2 group by t2.id END INPUT select mid('hello',1,null),mid('hello',null,1),mid(null,1,1); @@ -12212,7 +12212,7 @@ INPUT select * from t1 where MATCH a,b AGAINST ('"text search" +"now support"' IN BOOLEAN MODE); END OUTPUT -select * from t1 where match(a, b) against ('\"text search\" +\"now support\"' in boolean mode) +select * from t1 where match(a, b) against ('"text search" +"now support"' in boolean mode) END INPUT select trigger_name from information_schema.triggers where event_object_table='t1'; @@ -14750,7 +14750,7 @@ INPUT select * from t1 where MATCH a,b AGAINST('"space model' IN BOOLEAN MODE); END OUTPUT -select * from t1 where match(a, b) against ('\"space model' in boolean mode) +select * from t1 where match(a, b) against ('"space model' in boolean mode) END INPUT select @ujis4 = CONVERT(@utf84 USING ujis); @@ -14906,7 +14906,7 @@ INPUT select * from t1 where MATCH a,b AGAINST ('"text search" -"now support"' IN BOOLEAN MODE); END OUTPUT -select * from t1 where match(a, b) against ('\"text search\" -\"now support\"' in boolean mode) +select * from t1 where match(a, b) against ('"text search" -"now support"' in boolean mode) END INPUT select _rowid,t1._rowid,skey,sval from t1; @@ -15391,8 +15391,8 @@ END INPUT select SQL_BIG_RESULT distinct t1.a from t1, t2 group by t1.b order by 1; END -ERROR -syntax error at position 31 near 'distinct' +OUTPUT +select distinct sql_big_result t1.a from t1, t2 group by t1.b order by 1 asc END INPUT select t1.time+0,t1.date+0,t1.timestamp+0,concat(date," ",time), t1.quarter+t1.week, t1.year+timestampadd, timestampdiff from t1; @@ -16831,8 +16831,8 @@ END INPUT select SQL_BUFFER_RESULT from t1 order by 1, 2; END -OUTPUT -select SQL_BUFFER_RESULT from t1 order by 1 asc, 2 asc +ERROR +syntax error at position 30 near 'from' END INPUT select collation(convert('a',char(2) ascii)), collation(convert('a',char(2) ascii binary)); @@ -17612,7 +17612,7 @@ INPUT select 'aaa','aa''a',"aa""a"; END OUTPUT -select 'aaa', 'aa\'a', 'aa\"a' from dual +select 'aaa', 'aa\'a', 'aa"a' from dual END INPUT select cast('18446744073709551615' as signed); @@ -18542,7 +18542,7 @@ INPUT select * from t1 where MATCH a,b AGAINST ('"now support"' IN BOOLEAN MODE); END OUTPUT -select * from t1 where match(a, b) against ('\"now support\"' in boolean mode) +select * from t1 where match(a, b) against ('"now support"' in boolean mode) END INPUT select date_add("1997-12-31 23:59:59",INTERVAL "10000:99:99" HOUR_SECOND); @@ -19129,8 +19129,8 @@ END INPUT select sql_big_result trim(v),count(c) from t1 group by v order by v limit 10; END -ERROR -syntax error at position 28 +OUTPUT +select sql_big_result trim(v), count(c) from t1 group by v order by v asc limit 10 END INPUT select 1, min(a) from t1m where a=99; @@ -19171,8 +19171,8 @@ END INPUT select SQL_BIG_RESULT bit_and(col), bit_or(col) from t1 group by col; END -ERROR -syntax error at position 31 +OUTPUT +select sql_big_result bit_and(col), bit_or(col) from t1 group by col END INPUT select 3; @@ -19681,8 +19681,8 @@ END INPUT select sql_big_result t2.id, avg(rating+0.0e0) from t2 group by t2.id; END -ERROR -syntax error at position 26 +OUTPUT +select sql_big_result t2.id, avg(rating + 0.0e0) from t2 group by t2.id END INPUT select cast(NULL as signed); @@ -19705,8 +19705,8 @@ END INPUT select sql_big_result distinct t1.a from t1,t2 order by t2.a; END -ERROR -syntax error at position 31 near 'distinct' +OUTPUT +select distinct sql_big_result t1.a from t1, t2 order by t2.a asc END INPUT select reverse('abc'),reverse('abcd'); @@ -20000,7 +20000,7 @@ INPUT select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b), bit_xor(b) from t1 group by a; END OUTPUT -select `SQL_BIG_RESULT` as a, count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b), bit_xor(b) from t1 group by a +select sql_big_result a, count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b), bit_xor(b) from t1 group by a END INPUT select * from (t2 join t4 on b + 1 = y) join t1 on t1.c = t4.c; @@ -20371,8 +20371,8 @@ END INPUT select sql_big_result t2.id, avg(rating) from t2 group by t2.id; END -ERROR -syntax error at position 26 +OUTPUT +select sql_big_result t2.id, avg(rating) from t2 group by t2.id END INPUT select ST_Astext(ST_Envelope(ST_MPointFromWKB(ST_AsWKB(MultiPoint(Point('0', '-0'),Point('-0', '0'), Point('0', '0')))))) as result; @@ -20852,7 +20852,7 @@ INPUT select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; END OUTPUT -select `SQL_BIG_RESULT` as a, count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a +select sql_big_result a, count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a END INPUT select lpad('hello', 18446744073709551617, '1'); @@ -20911,8 +20911,8 @@ END INPUT select sql_buffer_result max(f1)+1 from t1; END -ERROR -syntax error at position 30 +OUTPUT +select sql_buffer_result max(f1) + 1 from t1 END INPUT select t1Aa.col1 from t1aA,t2Aa where t1Aa.col1 = t2aA.col1; @@ -21721,8 +21721,8 @@ END INPUT select SQL_BUFFER_RESULT from t1 WHERE (SEQ = 1); END -OUTPUT -select SQL_BUFFER_RESULT from t1 where SEQ = 1 +ERROR +syntax error at position 30 near 'from' END INPUT select i, count(*), std(s1/s2) from bug22555 group by i order by i; @@ -22148,7 +22148,7 @@ INPUT select * from t1 where MATCH a,b AGAINST ('"Now sUPPort"' IN BOOLEAN MODE); END OUTPUT -select * from t1 where match(a, b) against ('\"Now sUPPort\"' in boolean mode) +select * from t1 where match(a, b) against ('"Now sUPPort"' in boolean mode) END INPUT select sum(all a),count(all a),avg(all a),std(all a),variance(all a),bit_or(all a),bit_and(all a),min(all a),max(all a),min(all c),max(all c) from t1; diff --git a/go/vt/tableacl/tableacl.go b/go/vt/tableacl/tableacl.go index 9a6e6eeba4e..1b236cb1812 100644 --- a/go/vt/tableacl/tableacl.go +++ b/go/vt/tableacl/tableacl.go @@ -113,7 +113,7 @@ func (tacl *tableACL) init(configFile string, aclCB func()) error { config := &tableaclpb.Config{} if err := config.UnmarshalVT(data); err != nil { // try to parse tableacl as json file - if jsonErr := json2.Unmarshal(data, config); jsonErr != nil { + if jsonErr := json2.UnmarshalPB(data, config); jsonErr != nil { log.Infof("unable to parse tableACL config file as a protobuf or json file. protobuf err: %v json err: %v", err, jsonErr) return fmt.Errorf("unable to unmarshal Table ACL data: %s", data) } diff --git a/go/vt/throttler/demo/throttler_demo.go b/go/vt/throttler/demo/throttler_demo.go index cd2a4e11307..032b1fae3ca 100644 --- a/go/vt/throttler/demo/throttler_demo.go +++ b/go/vt/throttler/demo/throttler_demo.go @@ -103,7 +103,7 @@ type replica struct { // throttler is used to enforce the maximum rate at which replica applies // transactions. It must not be confused with the client's throttler. - throttler *throttler.Throttler + throttler throttler.Throttler lastHealthUpdate time.Time lagUpdateInterval time.Duration @@ -226,7 +226,7 @@ type client struct { primary *primary healthCheck discovery.HealthCheck - throttler *throttler.Throttler + throttler throttler.Throttler stopChan chan struct{} wg sync.WaitGroup diff --git a/go/vt/throttler/manager.go b/go/vt/throttler/manager.go index c2ee9f0a652..ee142190f75 100644 --- a/go/vt/throttler/manager.go +++ b/go/vt/throttler/manager.go @@ -64,16 +64,16 @@ type managerImpl struct { // mu guards all fields in this group. mu sync.Mutex // throttlers tracks all running throttlers (by their name). - throttlers map[string]*Throttler + throttlers map[string]Throttler } func newManager() *managerImpl { return &managerImpl{ - throttlers: make(map[string]*Throttler), + throttlers: make(map[string]Throttler), } } -func (m *managerImpl) registerThrottler(name string, throttler *Throttler) error { +func (m *managerImpl) registerThrottler(name string, throttler Throttler) error { m.mu.Lock() defer m.mu.Unlock() @@ -207,7 +207,7 @@ func (m *managerImpl) throttlerNamesLocked() []string { // log returns the most recent changes of the MaxReplicationLag module. // There will be one result for each processed replication lag record. -func (m *managerImpl) log(throttlerName string) ([]result, error) { +func (m *managerImpl) log(throttlerName string) ([]Result, error) { m.mu.Lock() defer m.mu.Unlock() @@ -216,5 +216,5 @@ func (m *managerImpl) log(throttlerName string) ([]result, error) { return nil, fmt.Errorf("throttler: %v does not exist", throttlerName) } - return t.log(), nil + return t.Log(), nil } diff --git a/go/vt/throttler/manager_test.go b/go/vt/throttler/manager_test.go index 3d61d4d6b68..21b6ba2e67d 100644 --- a/go/vt/throttler/manager_test.go +++ b/go/vt/throttler/manager_test.go @@ -37,7 +37,7 @@ var ( type managerTestFixture struct { m *managerImpl - t1, t2 *Throttler + t1, t2 Throttler } func (f *managerTestFixture) setUp() error { diff --git a/go/vt/throttler/max_replication_lag_module.go b/go/vt/throttler/max_replication_lag_module.go index ac184fe7be8..6f86a50400f 100644 --- a/go/vt/throttler/max_replication_lag_module.go +++ b/go/vt/throttler/max_replication_lag_module.go @@ -313,7 +313,7 @@ func (m *MaxReplicationLagModule) recalculateRate(lagRecordNow replicationLagRec m.memory.ageBadRate(now) - r := result{ + r := Result{ Now: now, RateChange: unchangedRate, lastRateChange: m.lastRateChange, @@ -446,7 +446,7 @@ func stateGreater(a, b state) bool { // and we should not skip the current replica ("lagRecordNow"). // Even if it's the same replica we may skip it and return false because // we want to wait longer for the propagation of the current rate change. -func (m *MaxReplicationLagModule) isReplicaUnderTest(r *result, now time.Time, testedState state, lagRecordNow replicationLagRecord) bool { +func (m *MaxReplicationLagModule) isReplicaUnderTest(r *Result, now time.Time, testedState state, lagRecordNow replicationLagRecord) bool { if m.replicaUnderTest == nil { return true } @@ -472,7 +472,7 @@ func (m *MaxReplicationLagModule) isReplicaUnderTest(r *result, now time.Time, t return true } -func (m *MaxReplicationLagModule) increaseRate(r *result, now time.Time, lagRecordNow replicationLagRecord) { +func (m *MaxReplicationLagModule) increaseRate(r *Result, now time.Time, lagRecordNow replicationLagRecord) { m.markCurrentRateAsBadOrGood(r, now, stateIncreaseRate, unknown) oldRate := m.rate.Load() @@ -560,7 +560,7 @@ func (m *MaxReplicationLagModule) minTestDurationUntilNextIncrease(increase floa return minDuration } -func (m *MaxReplicationLagModule) decreaseAndGuessRate(r *result, now time.Time, lagRecordNow replicationLagRecord) { +func (m *MaxReplicationLagModule) decreaseAndGuessRate(r *Result, now time.Time, lagRecordNow replicationLagRecord) { // Guess replication rate based on the difference in the replication lag of this // particular replica. lagRecordBefore := m.lagCache(lagRecordNow).atOrAfter(discovery.TabletToMapKey(lagRecordNow.Tablet), m.lastRateChange) @@ -631,7 +631,7 @@ func (m *MaxReplicationLagModule) decreaseAndGuessRate(r *result, now time.Time, // guessReplicationRate guesses the actual replication rate based on the new bac // Note that "lagDifference" can be positive (lag increased) or negative (lag // decreased). -func (m *MaxReplicationLagModule) guessReplicationRate(r *result, avgPrimaryRate float64, lagBefore, lagNow int64, lagDifference, d time.Duration) (int64, string) { +func (m *MaxReplicationLagModule) guessReplicationRate(r *Result, avgPrimaryRate float64, lagBefore, lagNow int64, lagDifference, d time.Duration) (int64, string) { // avgReplicationRate is the average rate (per second) at which the replica // applied transactions from the replication stream. We infer the value // from the relative change in the replication lag. @@ -676,14 +676,14 @@ func (m *MaxReplicationLagModule) guessReplicationRate(r *result, avgPrimaryRate return int64(newRate), reason } -func (m *MaxReplicationLagModule) emergency(r *result, now time.Time, lagRecordNow replicationLagRecord) { +func (m *MaxReplicationLagModule) emergency(r *Result, now time.Time, lagRecordNow replicationLagRecord) { m.markCurrentRateAsBadOrGood(r, now, stateEmergency, unknown) decreaseReason := fmt.Sprintf("replication lag went beyond max: %d > %d", lagRecordNow.lag(), m.config.MaxReplicationLagSec) m.decreaseRateByPercentage(r, now, lagRecordNow, stateEmergency, m.config.EmergencyDecrease, decreaseReason) } -func (m *MaxReplicationLagModule) decreaseRateByPercentage(r *result, now time.Time, lagRecordNow replicationLagRecord, newState state, decrease float64, decreaseReason string) { +func (m *MaxReplicationLagModule) decreaseRateByPercentage(r *Result, now time.Time, lagRecordNow replicationLagRecord, newState state, decrease float64, decreaseReason string) { oldRate := m.rate.Load() rate := int64(float64(oldRate) - float64(oldRate)*decrease) if rate == 0 { @@ -695,7 +695,7 @@ func (m *MaxReplicationLagModule) decreaseRateByPercentage(r *result, now time.T m.updateRate(r, newState, rate, reason, now, lagRecordNow, m.config.MinDurationBetweenDecreases()) } -func (m *MaxReplicationLagModule) updateRate(r *result, newState state, rate int64, reason string, now time.Time, lagRecordNow replicationLagRecord, testDuration time.Duration) { +func (m *MaxReplicationLagModule) updateRate(r *Result, newState state, rate int64, reason string, now time.Time, lagRecordNow replicationLagRecord, testDuration time.Duration) { oldRate := m.rate.Load() m.currentState = newState @@ -723,7 +723,7 @@ func (m *MaxReplicationLagModule) updateRate(r *result, newState state, rate int // markCurrentRateAsBadOrGood determines the actual rate between the last rate // change and "now" and determines if that rate was bad or good. -func (m *MaxReplicationLagModule) markCurrentRateAsBadOrGood(r *result, now time.Time, newState state, replicationLagChange replicationLagChange) { +func (m *MaxReplicationLagModule) markCurrentRateAsBadOrGood(r *Result, now time.Time, newState state, replicationLagChange replicationLagChange) { if m.lastRateChange.IsZero() { // Module was just started. We don't have any data points yet. r.GoodOrBad = ignoredRate @@ -797,6 +797,6 @@ func (m *MaxReplicationLagModule) markCurrentRateAsBadOrGood(r *result, now time } } -func (m *MaxReplicationLagModule) log() []result { +func (m *MaxReplicationLagModule) log() []Result { return m.results.latestValues() } diff --git a/go/vt/throttler/result.go b/go/vt/throttler/result.go index 0976a180877..bd7a86b3b18 100644 --- a/go/vt/throttler/result.go +++ b/go/vt/throttler/result.go @@ -50,10 +50,10 @@ state (old/tested/new): {{.OldState}}/{{.TestedState}}/{{.NewState}} lag before: {{.LagBefore}} ({{.AgeOfBeforeLag}} ago) rates (primary/replica): {{.PrimaryRate}}/{{.GuessedReplicationRate}} backlog (old/new): {{.GuessedReplicationBacklogOld}}/{{.GuessedReplicationBacklogNew}} reason: {{.Reason}}`)) -// result is generated by the MaxReplicationLag module for each processed +// Result is generated by the MaxReplicationLag module for each processed // "replicationLagRecord". // It captures the details and the decision of the processing. -type result struct { +type Result struct { Now time.Time RateChange rateChange lastRateChange time.Time @@ -80,7 +80,7 @@ type result struct { GuessedReplicationBacklogNew int } -func (r result) String() string { +func (r Result) String() string { var b strings.Builder if err := resultStringTemplate.Execute(&b, r); err != nil { panic(fmt.Sprintf("failed to Execute() template: %v", err)) @@ -88,25 +88,25 @@ func (r result) String() string { return b.String() } -func (r result) Alias() string { +func (r Result) Alias() string { return topoproto.TabletAliasString(r.LagRecordNow.Tablet.Alias) } -func (r result) TimeSinceLastRateChange() string { +func (r Result) TimeSinceLastRateChange() string { if r.lastRateChange.IsZero() { return "n/a" } return fmt.Sprintf("%.1fs", r.Now.Sub(r.lastRateChange).Seconds()) } -func (r result) LagBefore() string { +func (r Result) LagBefore() string { if r.LagRecordBefore.isZero() { return "n/a" } return fmt.Sprintf("%ds", r.LagRecordBefore.Stats.ReplicationLagSeconds) } -func (r result) AgeOfBeforeLag() string { +func (r Result) AgeOfBeforeLag() string { if r.LagRecordBefore.isZero() { return "n/a" } @@ -123,18 +123,18 @@ type resultRing struct { // started reusing entries. wrapped bool // values is the underlying ring buffer. - values []result + values []Result } // newResultRing creates a new resultRing. func newResultRing(capacity int) *resultRing { return &resultRing{ - values: make([]result, capacity), + values: make([]Result, capacity), } } // add inserts a new result into the ring buffer. -func (rr *resultRing) add(r result) { +func (rr *resultRing) add(r Result) { rr.mu.Lock() defer rr.mu.Unlock() @@ -148,7 +148,7 @@ func (rr *resultRing) add(r result) { // latestValues returns all values of the buffer. Entries are sorted in reverse // chronological order i.e. newer items come first. -func (rr *resultRing) latestValues() []result { +func (rr *resultRing) latestValues() []Result { rr.mu.Lock() defer rr.mu.Unlock() @@ -162,7 +162,7 @@ func (rr *resultRing) latestValues() []result { count = rr.position } - results := make([]result, count) + results := make([]Result, count) for i := 0; i < count; i++ { pos := start - i if pos < 0 { diff --git a/go/vt/throttler/result_test.go b/go/vt/throttler/result_test.go index 8cc5357ef7b..8bab6d9296a 100644 --- a/go/vt/throttler/result_test.go +++ b/go/vt/throttler/result_test.go @@ -24,7 +24,7 @@ import ( ) var ( - resultIncreased = result{ + resultIncreased = Result{ Now: sinceZero(1234 * time.Millisecond), RateChange: increasedRate, lastRateChange: sinceZero(1 * time.Millisecond), @@ -46,7 +46,7 @@ var ( GuessedReplicationBacklogOld: 0, GuessedReplicationBacklogNew: 0, } - resultDecreased = result{ + resultDecreased = Result{ Now: sinceZero(5000 * time.Millisecond), RateChange: decreasedRate, lastRateChange: sinceZero(1234 * time.Millisecond), @@ -68,7 +68,7 @@ var ( GuessedReplicationBacklogOld: 10, GuessedReplicationBacklogNew: 20, } - resultEmergency = result{ + resultEmergency = Result{ Now: sinceZero(10123 * time.Millisecond), RateChange: decreasedRate, lastRateChange: sinceZero(5000 * time.Millisecond), @@ -94,7 +94,7 @@ var ( func TestResultString(t *testing.T) { testcases := []struct { - r result + r Result want string }{ { @@ -134,24 +134,24 @@ reason: emergency state decreased the rate`, func TestResultRing(t *testing.T) { // Test data. - r1 := result{Reason: "r1"} - r2 := result{Reason: "r2"} - r3 := result{Reason: "r3"} + r1 := Result{Reason: "r1"} + r2 := Result{Reason: "r2"} + r3 := Result{Reason: "r3"} rr := newResultRing(2) // Use the ring partially. rr.add(r1) - got, want := rr.latestValues(), []result{r1} + got, want := rr.latestValues(), []Result{r1} require.Equal(t, want, got, "items not correctly added to resultRing") // Use it fully. rr.add(r2) - got, want = rr.latestValues(), []result{r2, r1} + got, want = rr.latestValues(), []Result{r2, r1} require.Equal(t, want, got, "items not correctly added to resultRing") // Let it wrap. rr.add(r3) - got, want = rr.latestValues(), []result{r3, r2} + got, want = rr.latestValues(), []Result{r3, r2} require.Equal(t, want, got, "resultRing did not wrap correctly") } diff --git a/go/vt/throttler/throttler.go b/go/vt/throttler/throttler.go index 909888bd0d4..a12d8f241a2 100644 --- a/go/vt/throttler/throttler.go +++ b/go/vt/throttler/throttler.go @@ -38,6 +38,7 @@ import ( "vitess.io/vitess/go/vt/proto/topodata" throttlerdatapb "vitess.io/vitess/go/vt/proto/throttlerdata" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" ) const ( @@ -66,7 +67,22 @@ const ( InvalidMaxReplicationLag = -1 ) -// Throttler provides a client-side, thread-aware throttler. +// Throttler defines the throttler interface. +type Throttler interface { + Throttle(threadID int) time.Duration + ThreadFinished(threadID int) + Close() + MaxRate() int64 + SetMaxRate(rate int64) + RecordReplicationLag(time time.Time, th *discovery.TabletHealth) + GetConfiguration() *throttlerdatapb.Configuration + UpdateConfiguration(configuration *throttlerdatapb.Configuration, copyZeroValues bool) error + ResetConfiguration() + MaxLag(tabletType topodatapb.TabletType) uint32 + Log() []Result +} + +// ThrottlerImpl implements a client-side, thread-aware throttler. // See the package doc for more information. // // Calls of Throttle() and ThreadFinished() take threadID as parameter which is @@ -74,7 +90,7 @@ const ( // NOTE: Trottle() and ThreadFinished() assume that *per thread* calls to them // // are serialized and must not happen concurrently. -type Throttler struct { +type ThrottlerImpl struct { // name describes the Throttler instance and is used e.g. in the webinterface. name string // unit describes the entity the throttler is limiting e.g. "queries" or @@ -127,15 +143,15 @@ type Throttler struct { // unit refers to the type of entity you want to throttle e.g. "queries" or // "transactions". // name describes the Throttler instance and will be used by the webinterface. -func NewThrottler(name, unit string, threadCount int, maxRate, maxReplicationLag int64) (*Throttler, error) { +func NewThrottler(name, unit string, threadCount int, maxRate, maxReplicationLag int64) (Throttler, error) { return newThrottler(GlobalManager, name, unit, threadCount, maxRate, maxReplicationLag, time.Now) } -func NewThrottlerFromConfig(name, unit string, threadCount int, maxRateModuleMaxRate int64, maxReplicationLagModuleConfig MaxReplicationLagModuleConfig, nowFunc func() time.Time) (*Throttler, error) { +func NewThrottlerFromConfig(name, unit string, threadCount int, maxRateModuleMaxRate int64, maxReplicationLagModuleConfig MaxReplicationLagModuleConfig, nowFunc func() time.Time) (Throttler, error) { return newThrottlerFromConfig(GlobalManager, name, unit, threadCount, maxRateModuleMaxRate, maxReplicationLagModuleConfig, nowFunc) } -func newThrottler(manager *managerImpl, name, unit string, threadCount int, maxRate, maxReplicationLag int64, nowFunc func() time.Time) (*Throttler, error) { +func newThrottler(manager *managerImpl, name, unit string, threadCount int, maxRate, maxReplicationLag int64, nowFunc func() time.Time) (Throttler, error) { config := NewMaxReplicationLagModuleConfig(maxReplicationLag) config.MaxReplicationLagSec = maxReplicationLag @@ -143,7 +159,7 @@ func newThrottler(manager *managerImpl, name, unit string, threadCount int, maxR } -func newThrottlerFromConfig(manager *managerImpl, name, unit string, threadCount int, maxRateModuleMaxRate int64, maxReplicationLagModuleConfig MaxReplicationLagModuleConfig, nowFunc func() time.Time) (*Throttler, error) { +func newThrottlerFromConfig(manager *managerImpl, name, unit string, threadCount int, maxRateModuleMaxRate int64, maxReplicationLagModuleConfig MaxReplicationLagModuleConfig, nowFunc func() time.Time) (Throttler, error) { err := maxReplicationLagModuleConfig.Verify() if err != nil { return nil, fmt.Errorf("invalid max replication lag config: %w", err) @@ -176,7 +192,7 @@ func newThrottlerFromConfig(manager *managerImpl, name, unit string, threadCount threadThrottlers[i] = newThreadThrottler(i, actualRateHistory) runningThreads[i] = true } - t := &Throttler{ + t := &ThrottlerImpl{ name: name, unit: unit, manager: manager, @@ -215,7 +231,7 @@ func newThrottlerFromConfig(manager *managerImpl, name, unit string, threadCount // the backoff duration elapsed. // The maximum value for the returned backoff is 1 second since the throttler // internally operates on a per-second basis. -func (t *Throttler) Throttle(threadID int) time.Duration { +func (t *ThrottlerImpl) Throttle(threadID int) time.Duration { if t.closed { panic(fmt.Sprintf("BUG: thread with ID: %v must not access closed Throttler", threadID)) } @@ -227,7 +243,7 @@ func (t *Throttler) Throttle(threadID int) time.Duration { // MaxLag returns the max of all the last replication lag values seen across all tablets of // the provided type, excluding ignored tablets. -func (t *Throttler) MaxLag(tabletType topodata.TabletType) uint32 { +func (t *ThrottlerImpl) MaxLag(tabletType topodata.TabletType) uint32 { cache := t.maxReplicationLagModule.lagCacheByType(tabletType) var maxLag uint32 @@ -250,7 +266,7 @@ func (t *Throttler) MaxLag(tabletType topodata.TabletType) uint32 { // ThreadFinished marks threadID as finished and redistributes the thread's // rate allotment across the other threads. // After ThreadFinished() is called, Throttle() must not be called anymore. -func (t *Throttler) ThreadFinished(threadID int) { +func (t *ThrottlerImpl) ThreadFinished(threadID int) { if t.threadFinished[threadID] { panic(fmt.Sprintf("BUG: thread with ID: %v already finished", threadID)) } @@ -265,7 +281,7 @@ func (t *Throttler) ThreadFinished(threadID int) { // Close stops all modules and frees all resources. // When Close() returned, the Throttler object must not be used anymore. -func (t *Throttler) Close() { +func (t *ThrottlerImpl) Close() { for _, m := range t.modules { m.Stop() } @@ -278,7 +294,7 @@ func (t *Throttler) Close() { // threadThrottlers accordingly. // The rate changes when the number of thread changes or a module updated its // max rate. -func (t *Throttler) updateMaxRate() { +func (t *ThrottlerImpl) updateMaxRate() { // Set it to infinite initially. maxRate := int64(math.MaxInt64) @@ -319,39 +335,39 @@ func (t *Throttler) updateMaxRate() { } // MaxRate returns the current rate of the MaxRateModule. -func (t *Throttler) MaxRate() int64 { +func (t *ThrottlerImpl) MaxRate() int64 { return t.maxRateModule.MaxRate() } // SetMaxRate updates the rate of the MaxRateModule. -func (t *Throttler) SetMaxRate(rate int64) { +func (t *ThrottlerImpl) SetMaxRate(rate int64) { t.maxRateModule.SetMaxRate(rate) } // RecordReplicationLag must be called by users to report the "ts" tablet health // data observed at "time". // Note: After Close() is called, this method must not be called anymore. -func (t *Throttler) RecordReplicationLag(time time.Time, th *discovery.TabletHealth) { +func (t *ThrottlerImpl) RecordReplicationLag(time time.Time, th *discovery.TabletHealth) { t.maxReplicationLagModule.RecordReplicationLag(time, th) } // GetConfiguration returns the configuration of the MaxReplicationLag module. -func (t *Throttler) GetConfiguration() *throttlerdatapb.Configuration { +func (t *ThrottlerImpl) GetConfiguration() *throttlerdatapb.Configuration { return t.maxReplicationLagModule.getConfiguration() } // UpdateConfiguration updates the configuration of the MaxReplicationLag module. -func (t *Throttler) UpdateConfiguration(configuration *throttlerdatapb.Configuration, copyZeroValues bool) error { +func (t *ThrottlerImpl) UpdateConfiguration(configuration *throttlerdatapb.Configuration, copyZeroValues bool) error { return t.maxReplicationLagModule.updateConfiguration(configuration, copyZeroValues) } // ResetConfiguration resets the configuration of the MaxReplicationLag module // to its initial settings. -func (t *Throttler) ResetConfiguration() { +func (t *ThrottlerImpl) ResetConfiguration() { t.maxReplicationLagModule.resetConfiguration() } -// log returns the most recent changes of the MaxReplicationLag module. -func (t *Throttler) log() []result { +// Log returns the most recent changes of the MaxReplicationLag module. +func (t *ThrottlerImpl) Log() []Result { return t.maxReplicationLagModule.log() } diff --git a/go/vt/throttler/throttler_test.go b/go/vt/throttler/throttler_test.go index b33bb2ca255..74e8784f021 100644 --- a/go/vt/throttler/throttler_test.go +++ b/go/vt/throttler/throttler_test.go @@ -163,7 +163,7 @@ func sinceZero(sinceZero time.Duration) time.Time { // threadThrottler.newThreadThrottler() for more details. // newThrottlerWithClock should only be used for testing. -func newThrottlerWithClock(name, unit string, threadCount int, maxRate int64, maxReplicationLag int64, nowFunc func() time.Time) (*Throttler, error) { +func newThrottlerWithClock(name, unit string, threadCount int, maxRate int64, maxReplicationLag int64, nowFunc func() time.Time) (Throttler, error) { return newThrottler(GlobalManager, name, unit, threadCount, maxRate, maxReplicationLag, nowFunc) } @@ -264,14 +264,16 @@ func TestThreadFinished(t *testing.T) { // Max rate update to threadThrottlers happens asynchronously. Wait for it. timer := time.NewTimer(2 * time.Second) + throttlerImpl, ok := throttler.(*ThrottlerImpl) + require.True(t, ok) for { - if throttler.threadThrottlers[0].getMaxRate() == 2 { + if throttlerImpl.threadThrottlers[0].getMaxRate() == 2 { timer.Stop() break } select { case <-timer.C: - t.Fatalf("max rate was not propapgated to threadThrottler[0] in time: %v", throttler.threadThrottlers[0].getMaxRate()) + t.Fatalf("max rate was not propapgated to threadThrottler[0] in time: %v", throttlerImpl.threadThrottlers[0].getMaxRate()) default: // Timer not up yet. Try again. } @@ -369,7 +371,9 @@ func TestUpdateMaxRate_AllThreadsFinished(t *testing.T) { throttler.ThreadFinished(1) // Make sure that there's no division by zero error (threadsRunning == 0). - throttler.updateMaxRate() + throttlerImpl, ok := throttler.(*ThrottlerImpl) + require.True(t, ok) + throttlerImpl.updateMaxRate() // We don't care about the Throttler state at this point. } diff --git a/go/vt/throttler/throttlerlogz.go b/go/vt/throttler/throttlerlogz.go index 4023dcd7e68..8cace8ce5c4 100644 --- a/go/vt/throttler/throttlerlogz.go +++ b/go/vt/throttler/throttlerlogz.go @@ -159,7 +159,7 @@ func showThrottlerLog(w http.ResponseWriter, m *managerImpl, name string) { colorLevel = "high" } data := struct { - result + Result ColorLevel string }{r, colorLevel} diff --git a/go/vt/throttler/throttlerlogz_test.go b/go/vt/throttler/throttlerlogz_test.go index 22927f3f201..78151fc750b 100644 --- a/go/vt/throttler/throttlerlogz_test.go +++ b/go/vt/throttler/throttlerlogz_test.go @@ -54,7 +54,7 @@ func TestThrottlerlogzHandler(t *testing.T) { testcases := []struct { desc string - r result + r Result want string }{ { @@ -147,7 +147,9 @@ func TestThrottlerlogzHandler(t *testing.T) { request, _ := http.NewRequest("GET", "/throttlerlogz/t1", nil) response := httptest.NewRecorder() - f.t1.maxReplicationLagModule.results.add(tc.r) + throttler, ok := f.t1.(*ThrottlerImpl) + require.True(t, ok) + throttler.maxReplicationLagModule.results.add(tc.r) throttlerlogzHandler(response, request, f.m) got := response.Body.String() diff --git a/go/vt/topo/conn.go b/go/vt/topo/conn.go index 348fc569ecf..b00bdc67207 100644 --- a/go/vt/topo/conn.go +++ b/go/vt/topo/conn.go @@ -19,6 +19,7 @@ package topo import ( "context" "sort" + "time" ) // Conn defines the interface that must be implemented by topology @@ -120,6 +121,21 @@ type Conn interface { // Returns ErrInterrupted if ctx is canceled. Lock(ctx context.Context, dirPath, contents string) (LockDescriptor, error) + // LockWithTTL is similar to `Lock` but the difference is that it allows + // you to override the global default TTL that is configured for the + // implementation (--topo_etcd_lease_ttl and --topo_consul_lock_session_ttl). + // Note: this is no different than `Lock` for ZooKeeper as it does not + // support lock TTLs and they exist until released or the session ends. + LockWithTTL(ctx context.Context, dirPath, contents string, ttl time.Duration) (LockDescriptor, error) + + // LockName is similar to `Lock` but the difference is that it does not require + // the path to exist and have children in order to lock it. This is because with + // named locks you are NOT locking an actual topo entity such as a Keyspace record. + // Because this lock is not blocking any Vitess operations OTHER than another + // caller that is trying to get the same named lock, there is a static 24 hour + // TTL on them to ensure that they are eventually cleaned up. + LockName(ctx context.Context, dirPath, contents string) (LockDescriptor, error) + // TryLock takes lock on the given directory with a fail-fast approach. // It is similar to `Lock` but the difference is it attempts to acquire the lock // if it is likely to succeed. If there is already a lock on given path, then unlike `Lock` diff --git a/go/vt/topo/consultopo/lock.go b/go/vt/topo/consultopo/lock.go index ae47b91cc6c..49554474677 100644 --- a/go/vt/topo/consultopo/lock.go +++ b/go/vt/topo/consultopo/lock.go @@ -20,6 +20,7 @@ import ( "context" "fmt" "path" + "time" "github.com/hashicorp/consul/api" @@ -49,7 +50,27 @@ func (s *Server) Lock(ctx context.Context, dirPath, contents string) (topo.LockD return nil, convertError(err, dirPath) } - return s.lock(ctx, dirPath, contents) + return s.lock(ctx, dirPath, contents, s.lockTTL) +} + +// LockWithTTL is part of the topo.Conn interface. +func (s *Server) LockWithTTL(ctx context.Context, dirPath, contents string, ttl time.Duration) (topo.LockDescriptor, error) { + // We list the directory first to make sure it exists. + if _, err := s.ListDir(ctx, dirPath, false /*full*/); err != nil { + // We need to return the right error codes, like + // topo.ErrNoNode and topo.ErrInterrupted, and the + // easiest way to do this is to return convertError(err). + // It may lose some of the context, if this is an issue, + // maybe logging the error would work here. + return nil, convertError(err, dirPath) + } + + return s.lock(ctx, dirPath, contents, ttl.String()) +} + +// LockName is part of the topo.Conn interface. +func (s *Server) LockName(ctx context.Context, dirPath, contents string) (topo.LockDescriptor, error) { + return s.lock(ctx, dirPath, contents, topo.NamedLockTTL.String()) } // TryLock is part of the topo.Conn interface. @@ -74,11 +95,11 @@ func (s *Server) TryLock(ctx context.Context, dirPath, contents string) (topo.Lo } // everything is good let's acquire the lock. - return s.lock(ctx, dirPath, contents) + return s.lock(ctx, dirPath, contents, s.lockTTL) } // Lock is part of the topo.Conn interface. -func (s *Server) lock(ctx context.Context, dirPath, contents string) (topo.LockDescriptor, error) { +func (s *Server) lock(ctx context.Context, dirPath, contents, ttl string) (topo.LockDescriptor, error) { lockPath := path.Join(s.root, dirPath, locksFilename) lockOpts := &api.LockOptions{ @@ -90,12 +111,19 @@ func (s *Server) lock(ctx context.Context, dirPath, contents string) (topo.LockD }, } lockOpts.SessionOpts.Checks = s.lockChecks - if s.lockDelay > 0 { - lockOpts.SessionOpts.LockDelay = s.lockDelay - } if s.lockTTL != "" { + // Override the API default with the global default from + // --topo_consul_lock_session_ttl. lockOpts.SessionOpts.TTL = s.lockTTL } + if ttl != "" { + // Override the global default with the one provided by the + // caller. + lockOpts.SessionOpts.TTL = ttl + } + if s.lockDelay > 0 { + lockOpts.SessionOpts.LockDelay = s.lockDelay + } // Build the lock structure. l, err := s.client.LockOpts(lockOpts) if err != nil { diff --git a/go/vt/topo/consultopo/server.go b/go/vt/topo/consultopo/server.go index a7a5446c274..ab61a40b1e8 100644 --- a/go/vt/topo/consultopo/server.go +++ b/go/vt/topo/consultopo/server.go @@ -111,7 +111,7 @@ type Server struct { locks map[string]*lockInstance lockChecks []string - lockTTL string + lockTTL string // This is the default used for all non-named locks lockDelay time.Duration } diff --git a/go/vt/topo/etcd2topo/election.go b/go/vt/topo/etcd2topo/election.go index 276d9e60355..94768b50470 100644 --- a/go/vt/topo/etcd2topo/election.go +++ b/go/vt/topo/etcd2topo/election.go @@ -91,7 +91,7 @@ func (mp *etcdLeaderParticipation) WaitForLeadership() (context.Context, error) // Try to get the primaryship, by getting a lock. var err error - ld, err = mp.s.lock(lockCtx, electionPath, mp.id) + ld, err = mp.s.lock(lockCtx, electionPath, mp.id, leaseTTL) if err != nil { // It can be that we were interrupted. return nil, err diff --git a/go/vt/topo/etcd2topo/lock.go b/go/vt/topo/etcd2topo/lock.go index 89095156471..7fb761611cd 100644 --- a/go/vt/topo/etcd2topo/lock.go +++ b/go/vt/topo/etcd2topo/lock.go @@ -20,6 +20,7 @@ import ( "context" "fmt" "path" + "time" "github.com/spf13/pflag" @@ -34,7 +35,7 @@ import ( ) var ( - leaseTTL = 30 + leaseTTL = 30 // This is the default used for all non-named locks ) func init() { @@ -153,7 +154,7 @@ func (s *Server) TryLock(ctx context.Context, dirPath, contents string) (topo.Lo } // everything is good let's acquire the lock. - return s.lock(ctx, dirPath, contents) + return s.lock(ctx, dirPath, contents, leaseTTL) } // Lock is part of the topo.Conn interface. @@ -168,15 +169,35 @@ func (s *Server) Lock(ctx context.Context, dirPath, contents string) (topo.LockD return nil, convertError(err, dirPath) } - return s.lock(ctx, dirPath, contents) + return s.lock(ctx, dirPath, contents, leaseTTL) +} + +// LockWithTTL is part of the topo.Conn interface. +func (s *Server) LockWithTTL(ctx context.Context, dirPath, contents string, ttl time.Duration) (topo.LockDescriptor, error) { + // We list the directory first to make sure it exists. + if _, err := s.ListDir(ctx, dirPath, false /*full*/); err != nil { + // We need to return the right error codes, like + // topo.ErrNoNode and topo.ErrInterrupted, and the + // easiest way to do this is to return convertError(err). + // It may lose some of the context, if this is an issue, + // maybe logging the error would work here. + return nil, convertError(err, dirPath) + } + + return s.lock(ctx, dirPath, contents, int(ttl.Seconds())) +} + +// LockName is part of the topo.Conn interface. +func (s *Server) LockName(ctx context.Context, dirPath, contents string) (topo.LockDescriptor, error) { + return s.lock(ctx, dirPath, contents, int(topo.NamedLockTTL.Seconds())) } // lock is used by both Lock() and primary election. -func (s *Server) lock(ctx context.Context, nodePath, contents string) (topo.LockDescriptor, error) { +func (s *Server) lock(ctx context.Context, nodePath, contents string, ttl int) (topo.LockDescriptor, error) { nodePath = path.Join(s.root, nodePath, locksPath) // Get a lease, set its KeepAlive. - lease, err := s.cli.Grant(ctx, int64(leaseTTL)) + lease, err := s.cli.Grant(ctx, int64(ttl)) if err != nil { return nil, convertError(err, nodePath) } diff --git a/go/vt/topo/faketopo/faketopo.go b/go/vt/topo/faketopo/faketopo.go index 52a2a41c5df..0c88b95e3da 100644 --- a/go/vt/topo/faketopo/faketopo.go +++ b/go/vt/topo/faketopo/faketopo.go @@ -20,6 +20,7 @@ import ( "context" "strings" "sync" + "time" "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/topo" @@ -291,6 +292,20 @@ func (f *FakeConn) Lock(ctx context.Context, dirPath, contents string) (topo.Loc return &fakeLockDescriptor{}, nil } +// LockWithTTL implements the Conn interface. +func (f *FakeConn) LockWithTTL(ctx context.Context, dirPath, contents string, _ time.Duration) (topo.LockDescriptor, error) { + f.mu.Lock() + defer f.mu.Unlock() + return &fakeLockDescriptor{}, nil +} + +// LockName implements the Conn interface. +func (f *FakeConn) LockName(ctx context.Context, dirPath, contents string) (topo.LockDescriptor, error) { + f.mu.Lock() + defer f.mu.Unlock() + return &fakeLockDescriptor{}, nil +} + // TryLock is part of the topo.Conn interface. Its implementation is same as Lock func (f *FakeConn) TryLock(ctx context.Context, dirPath, contents string) (topo.LockDescriptor, error) { return f.Lock(ctx, dirPath, contents) diff --git a/go/vt/topo/keyspace_lock.go b/go/vt/topo/keyspace_lock.go index 7df1b2ee64f..fe9da9a5f8b 100644 --- a/go/vt/topo/keyspace_lock.go +++ b/go/vt/topo/keyspace_lock.go @@ -43,10 +43,10 @@ func (s *keyspaceLock) Path() string { // - a context with a locksInfo structure for future reference. // - an unlock method // - an error if anything failed. -func (ts *Server) LockKeyspace(ctx context.Context, keyspace, action string) (context.Context, func(*error), error) { +func (ts *Server) LockKeyspace(ctx context.Context, keyspace, action string, opts ...LockOption) (context.Context, func(*error), error) { return ts.internalLock(ctx, &keyspaceLock{ keyspace: keyspace, - }, action, true) + }, action, opts...) } // CheckKeyspaceLocked can be called on a context to make sure we have the lock diff --git a/go/vt/topo/keyspace_lock_test.go b/go/vt/topo/keyspace_lock_test.go index 6d0a34de554..35fd804db9a 100644 --- a/go/vt/topo/keyspace_lock_test.go +++ b/go/vt/topo/keyspace_lock_test.go @@ -19,12 +19,14 @@ package topo_test import ( "context" "testing" + "time" "github.com/stretchr/testify/require" - topodatapb "vitess.io/vitess/go/vt/proto/topodata" "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/topo/memorytopo" + + topodatapb "vitess.io/vitess/go/vt/proto/topodata" ) // TestTopoKeyspaceLock tests keyspace lock operations. @@ -82,3 +84,34 @@ func TestTopoKeyspaceLock(t *testing.T) { require.NoError(t, err) defer unlock(&err) } + +// TestTopoKeyspaceLockWithTTL tests keyspace lock with a custom TTL. +func TestTopoKeyspaceLockWithTTL(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + ts, tsf := memorytopo.NewServerAndFactory(ctx, "zone1") + defer ts.Close() + + currentTopoLockTimeout := topo.LockTimeout + topo.LockTimeout = testLockTimeout + defer func() { + topo.LockTimeout = currentTopoLockTimeout + }() + + ks1 := "ks1" + ttl := time.Second + err := ts.CreateKeyspace(ctx, ks1, &topodatapb.Keyspace{}) + require.NoError(t, err) + + ctx, unlock, err := ts.LockKeyspace(ctx, ks1, ks1, topo.WithTTL(ttl)) + require.NoError(t, err) + defer unlock(&err) + + err = topo.CheckKeyspaceLocked(ctx, ks1) + require.NoError(t, err) + + // Confirm the new stats. + stats := tsf.GetCallStats() + require.NotNil(t, stats) + require.Equal(t, int64(1), stats.Counts()["LockWithTTL"]) +} diff --git a/go/vt/topo/locks.go b/go/vt/topo/locks.go index 16caaf49dfb..f46e5f06e4b 100644 --- a/go/vt/topo/locks.go +++ b/go/vt/topo/locks.go @@ -46,6 +46,11 @@ var ( RemoteOperationTimeout = 15 * time.Second ) +// How long named locks are kept in the topo server. +// This ensures that orphaned named locks are not kept around forever. +// This should never happen, but it provides a final safety net. +const NamedLockTTL = 24 * time.Hour + // Lock describes a long-running lock on a keyspace or a shard. // It needs to be public as we JSON-serialize it. type Lock struct { @@ -54,6 +59,7 @@ type Lock struct { HostName string UserName string Time string + Options lockOptions // Status is the current status of the Lock. Status string @@ -120,6 +126,28 @@ type locksKeyType int var locksKey locksKeyType +// Support different lock types. +type LockType int + +const ( + // Blocking is the default lock type when no other valid type + // is specified. + Blocking LockType = iota + NonBlocking // Uses TryLock + Named // Uses LockName +) + +func (lt LockType) String() string { + switch lt { + case NonBlocking: + return "non blocking" + case Named: + return "named" + default: + return "blocking" + } +} + // iTopoLock is the interface for knowing the resource that is being locked. // It allows for better controlling nuances for different lock types and log messages. type iTopoLock interface { @@ -129,8 +157,11 @@ type iTopoLock interface { } // perform the topo lock operation -func (l *Lock) lock(ctx context.Context, ts *Server, lt iTopoLock, isBlocking bool) (LockDescriptor, error) { - log.Infof("Locking %v %v for action %v", lt.Type(), lt.ResourceName(), l.Action) +func (l *Lock) lock(ctx context.Context, ts *Server, lt iTopoLock, opts ...LockOption) (LockDescriptor, error) { + for _, o := range opts { + o.apply(&l.Options) + } + log.Infof("Locking %s %s for action %s with options: %+v", lt.Type(), lt.ResourceName(), l.Action, l.Options) ctx, cancel := context.WithTimeout(ctx, LockTimeout) defer cancel() @@ -143,10 +174,18 @@ func (l *Lock) lock(ctx context.Context, ts *Server, lt iTopoLock, isBlocking bo if err != nil { return nil, err } - if isBlocking { + + switch l.Options.lockType { + case NonBlocking: + return ts.globalCell.TryLock(ctx, lt.Path(), j) + case Named: + return ts.globalCell.LockName(ctx, lt.Path(), j) + default: + if l.Options.ttl != 0 { + return ts.globalCell.LockWithTTL(ctx, lt.Path(), j, l.Options.ttl) + } return ts.globalCell.Lock(ctx, lt.Path(), j) } - return ts.globalCell.TryLock(ctx, lt.Path(), j) } // unlock unlocks a previously locked key. @@ -174,7 +213,7 @@ func (l *Lock) unlock(ctx context.Context, lt iTopoLock, lockDescriptor LockDesc return lockDescriptor.Unlock(ctx) } -func (ts *Server) internalLock(ctx context.Context, lt iTopoLock, action string, isBlocking bool) (context.Context, func(*error), error) { +func (ts *Server) internalLock(ctx context.Context, lt iTopoLock, action string, opts ...LockOption) (context.Context, func(*error), error) { i, ok := ctx.Value(locksKey).(*locksInfo) if !ok { i = &locksInfo{ @@ -191,7 +230,7 @@ func (ts *Server) internalLock(ctx context.Context, lt iTopoLock, action string, // lock it l := newLock(action) - lockDescriptor, err := l.lock(ctx, ts, lt, isBlocking) + lockDescriptor, err := l.lock(ctx, ts, lt, opts...) if err != nil { return nil, nil, err } @@ -246,3 +285,52 @@ func checkLocked(ctx context.Context, lt iTopoLock) error { // Check the lock server implementation still holds the lock. return li.lockDescriptor.Check(ctx) } + +// lockOptions configure a Lock call. lockOptions are set by the LockOption +// values passed to the lock functions. +type lockOptions struct { + lockType LockType + ttl time.Duration +} + +// LockOption configures how we perform the locking operation. +type LockOption interface { + apply(*lockOptions) +} + +// funcLockOption wraps a function that modifies lockOptions into an +// implementation of the LockOption interface. +type funcLockOption struct { + f func(*lockOptions) +} + +func (flo *funcLockOption) apply(lo *lockOptions) { + flo.f(lo) +} + +func newFuncLockOption(f func(*lockOptions)) *funcLockOption { + return &funcLockOption{ + f: f, + } +} + +// WithTTL allows you to specify how long the underlying topo server +// implementation should hold the lock before releasing it — even if the caller +// has not explicitly released it. This provides a way to override the global +// ttl values that are set via --topo_consul_lock_session_ttl and +// --topo_etcd_lease_ttl. +// Note: This option is ignored by the ZooKeeper implementation as it does not +// support TTLs. +func WithTTL(ttl time.Duration) LockOption { + return newFuncLockOption(func(o *lockOptions) { + o.ttl = ttl + }) +} + +// WithType determines the type of lock we take. The options are defined +// by the LockType type. +func WithType(lt LockType) LockOption { + return newFuncLockOption(func(o *lockOptions) { + o.lockType = lt + }) +} diff --git a/go/vt/topo/memorytopo/lock.go b/go/vt/topo/memorytopo/lock.go index d0943c7058d..0dafcf250ed 100644 --- a/go/vt/topo/memorytopo/lock.go +++ b/go/vt/topo/memorytopo/lock.go @@ -19,6 +19,7 @@ package memorytopo import ( "context" "fmt" + "time" "vitess.io/vitess/go/vt/topo" ) @@ -65,11 +66,32 @@ func (c *Conn) Lock(ctx context.Context, dirPath, contents string) (topo.LockDes return nil, err } - return c.lock(ctx, dirPath, contents) + return c.lock(ctx, dirPath, contents, false) +} + +// LockWithTTL is part of the topo.Conn interface. It behaves the same as Lock +// as TTLs are not supported in memorytopo. +func (c *Conn) LockWithTTL(ctx context.Context, dirPath, contents string, _ time.Duration) (topo.LockDescriptor, error) { + c.factory.callstats.Add([]string{"LockWithTTL"}, 1) + + c.factory.mu.Lock() + err := c.factory.getOperationError(Lock, dirPath) + c.factory.mu.Unlock() + if err != nil { + return nil, err + } + + return c.lock(ctx, dirPath, contents, false) +} + +// LockName is part of the topo.Conn interface. +func (c *Conn) LockName(ctx context.Context, dirPath, contents string) (topo.LockDescriptor, error) { + c.factory.callstats.Add([]string{"LockName"}, 1) + return c.lock(ctx, dirPath, contents, true) } // Lock is part of the topo.Conn interface. -func (c *Conn) lock(ctx context.Context, dirPath, contents string) (topo.LockDescriptor, error) { +func (c *Conn) lock(ctx context.Context, dirPath, contents string, named bool) (topo.LockDescriptor, error) { for { if err := c.dial(ctx); err != nil { return nil, err @@ -82,7 +104,12 @@ func (c *Conn) lock(ctx context.Context, dirPath, contents string) (topo.LockDes return nil, c.factory.err } - n := c.factory.nodeByPath(c.cell, dirPath) + var n *node + if named { + n = c.factory.getOrCreatePath(c.cell, dirPath) + } else { + n = c.factory.nodeByPath(c.cell, dirPath) + } if n == nil { c.factory.mu.Unlock() return nil, topo.NewError(topo.NoNode, dirPath) diff --git a/go/vt/topo/named_lock.go b/go/vt/topo/named_lock.go new file mode 100644 index 00000000000..533317f8d9d --- /dev/null +++ b/go/vt/topo/named_lock.go @@ -0,0 +1,58 @@ +/* +Copyright 2024 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 topo + +import ( + "context" + "path" +) + +type namedLock struct { + name string +} + +var _ iTopoLock = (*namedLock)(nil) + +func (s *namedLock) Type() string { + return "named" +} + +func (s *namedLock) ResourceName() string { + return s.name +} + +func (s *namedLock) Path() string { + return path.Join(NamedLocksPath, s.name) +} + +// LockName will lock the opaque identifier, and return: +// - a context with a locksInfo structure for future reference. +// - an unlock method +// - an error if anything failed. +func (ts *Server) LockName(ctx context.Context, name, action string) (context.Context, func(*error), error) { + return ts.internalLock(ctx, &namedLock{ + name: name, + }, action, WithType(Named)) +} + +// CheckNameLocked can be called on a context to make sure we have the lock +// for a given opaque identifier. +func CheckNameLocked(ctx context.Context, name string) error { + return checkLocked(ctx, &namedLock{ + name: name, + }) +} diff --git a/go/vt/topo/named_lock_test.go b/go/vt/topo/named_lock_test.go new file mode 100644 index 00000000000..a2bb82c73e9 --- /dev/null +++ b/go/vt/topo/named_lock_test.go @@ -0,0 +1,88 @@ +/* +Copyright 2024 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 topo_test + +import ( + "context" + "fmt" + "testing" + + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/vt/topo" + "vitess.io/vitess/go/vt/topo/memorytopo" +) + +// TestTopoNamedLock tests named lock operations. +func TestTopoNamedLock(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + ts, tsf := memorytopo.NewServerAndFactory(ctx, "zone1") + defer ts.Close() + + currentTopoLockTimeout := topo.LockTimeout + topo.LockTimeout = testLockTimeout + defer func() { + topo.LockTimeout = currentTopoLockTimeout + }() + + lockName := "testy" + action := "testing" + lockNameCalls := int64(0) + + ctx, unlock, err := ts.LockName(ctx, lockName, action) + require.NoError(t, err) + lockNameCalls++ + + // Locking the same name again, without unlocking, should return an error. + // This does not attempt the lock within the topo server implementation + // as we first check the context and see that the lock is held, thus the + // lockNameCalls should not be increased. + _, _, err = ts.LockName(ctx, lockName, action) + require.ErrorContains(t, err, fmt.Sprintf("%s is already held", lockName)) + + // Check that we have the named lock. + err = topo.CheckNameLocked(ctx, lockName) + require.NoError(t, err) + + // Confirm that we can acquire a different named lock. + lockName2 := "testy2" + ctx, unlock2, err := ts.LockName(ctx, lockName2, action) + require.NoError(t, err) + defer unlock2(&err) + lockNameCalls++ + + // Unlock the first name. + unlock(&err) + + // Confirm that we no longer have the first named lock. + err = topo.CheckNameLocked(ctx, lockName) + require.ErrorContains(t, err, fmt.Sprintf("%s is not locked", lockName)) + err = topo.CheckNameLocked(ctx, lockName2) + require.NoError(t, err) + + // Confirm that the first named lock can be re-acquired after unlocking. + _, unlock, err = ts.LockName(ctx, lockName, action) + require.NoError(t, err) + defer unlock(&err) + lockNameCalls++ + + // Confirm the stats. + stats := tsf.GetCallStats() + require.NotNil(t, stats) + require.Equal(t, lockNameCalls, stats.Counts()["LockName"]) +} diff --git a/go/vt/topo/routing_rules_lock.go b/go/vt/topo/routing_rules_lock.go index c45ddb738c9..682eff30dc5 100644 --- a/go/vt/topo/routing_rules_lock.go +++ b/go/vt/topo/routing_rules_lock.go @@ -37,8 +37,8 @@ func (s *routingRules) Path() string { } // LockRoutingRules acquires a lock for routing rules. -func (ts *Server) LockRoutingRules(ctx context.Context, action string) (context.Context, func(*error), error) { - return ts.internalLock(ctx, &routingRules{}, action, true) +func (ts *Server) LockRoutingRules(ctx context.Context, action string, opts ...LockOption) (context.Context, func(*error), error) { + return ts.internalLock(ctx, &routingRules{}, action, opts...) } // CheckRoutingRulesLocked checks if a lock for routing rules is still possessed. diff --git a/go/vt/topo/server.go b/go/vt/topo/server.go index 6e5fadd8b97..23b7be6cfa1 100644 --- a/go/vt/topo/server.go +++ b/go/vt/topo/server.go @@ -81,6 +81,7 @@ const ( ExternalClustersFile = "ExternalClusters" ShardRoutingRulesFile = "ShardRoutingRules" CommonRoutingRulesFile = "Rules" + MirrorRulesFile = "MirrorRules" ) // Path for all object types. @@ -94,6 +95,7 @@ const ( ExternalClusterVitess = "vitess" RoutingRulesPath = "routing_rules" KeyspaceRoutingRulesPath = "keyspace" + NamedLocksPath = "internal/named_locks" ) // Factory is a factory interface to create Conn objects. diff --git a/go/vt/topo/shard_lock.go b/go/vt/topo/shard_lock.go index 72d0b1c8ca4..23326dcd23f 100644 --- a/go/vt/topo/shard_lock.go +++ b/go/vt/topo/shard_lock.go @@ -59,11 +59,11 @@ func (s *shardLock) Path() string { // // * operations that we don't want to conflict with re-parenting: // - DeleteTablet when it's the shard's current primary -func (ts *Server) LockShard(ctx context.Context, keyspace, shard, action string) (context.Context, func(*error), error) { +func (ts *Server) LockShard(ctx context.Context, keyspace, shard, action string, opts ...LockOption) (context.Context, func(*error), error) { return ts.internalLock(ctx, &shardLock{ keyspace: keyspace, shard: shard, - }, action, true) + }, action, opts...) } // TryLockShard will lock the shard, and return: @@ -85,7 +85,7 @@ func (ts *Server) TryLockShard(ctx context.Context, keyspace, shard, action stri return ts.internalLock(ctx, &shardLock{ keyspace: keyspace, shard: shard, - }, action, false) + }, action, WithType(NonBlocking)) } // CheckShardLocked can be called on a context to make sure we have the lock diff --git a/go/vt/topo/srv_vschema.go b/go/vt/topo/srv_vschema.go index c118253e8a8..f69fca83537 100644 --- a/go/vt/topo/srv_vschema.go +++ b/go/vt/topo/srv_vschema.go @@ -210,6 +210,12 @@ func (ts *Server) RebuildSrvVSchema(ctx context.Context, cells []string) error { } srvVSchema.KeyspaceRoutingRules = krr + mr, err := ts.GetMirrorRules(ctx) + if err != nil { + return fmt.Errorf("GetMirrorRules failed: %v", err) + } + srvVSchema.MirrorRules = mr + // now save the SrvVSchema in all cells in parallel for _, cell := range cells { wg.Add(1) diff --git a/go/vt/topo/stats_conn.go b/go/vt/topo/stats_conn.go index 34c45d793ac..39bc8c9bc43 100644 --- a/go/vt/topo/stats_conn.go +++ b/go/vt/topo/stats_conn.go @@ -159,17 +159,33 @@ func (st *StatsConn) Delete(ctx context.Context, filePath string, version Versio // Lock is part of the Conn interface func (st *StatsConn) Lock(ctx context.Context, dirPath, contents string) (LockDescriptor, error) { - return st.internalLock(ctx, dirPath, contents, true) + return st.internalLock(ctx, dirPath, contents, Blocking, 0) +} + +// LockWithTTL is part of the Conn interface +func (st *StatsConn) LockWithTTL(ctx context.Context, dirPath, contents string, ttl time.Duration) (LockDescriptor, error) { + return st.internalLock(ctx, dirPath, contents, Blocking, ttl) +} + +// LockName is part of the Conn interface +func (st *StatsConn) LockName(ctx context.Context, dirPath, contents string) (LockDescriptor, error) { + return st.internalLock(ctx, dirPath, contents, Named, 0) } // TryLock is part of the topo.Conn interface. Its implementation is same as Lock func (st *StatsConn) TryLock(ctx context.Context, dirPath, contents string) (LockDescriptor, error) { - return st.internalLock(ctx, dirPath, contents, false) + return st.internalLock(ctx, dirPath, contents, NonBlocking, 0) } // TryLock is part of the topo.Conn interface. Its implementation is same as Lock -func (st *StatsConn) internalLock(ctx context.Context, dirPath, contents string, isBlocking bool) (LockDescriptor, error) { - statsKey := []string{"Lock", st.cell} +func (st *StatsConn) internalLock(ctx context.Context, dirPath, contents string, lockType LockType, ttl time.Duration) (LockDescriptor, error) { + statsKey := []string{"Lock", st.cell} // Also used for NonBlocking / TryLock + switch { + case lockType == Named: + statsKey[0] = "LockName" + case ttl != 0: + statsKey[0] = "LockWithTTL" + } if st.readOnly { return nil, vterrors.Errorf(vtrpc.Code_READ_ONLY, readOnlyErrorStrFormat, statsKey[0], dirPath) } @@ -177,10 +193,17 @@ func (st *StatsConn) internalLock(ctx context.Context, dirPath, contents string, defer topoStatsConnTimings.Record(statsKey, startTime) var res LockDescriptor var err error - if isBlocking { - res, err = st.conn.Lock(ctx, dirPath, contents) - } else { + switch lockType { + case NonBlocking: res, err = st.conn.TryLock(ctx, dirPath, contents) + case Named: + res, err = st.conn.LockName(ctx, dirPath, contents) + default: + if ttl != 0 { + res, err = st.conn.LockWithTTL(ctx, dirPath, contents, ttl) + } else { + res, err = st.conn.Lock(ctx, dirPath, contents) + } } if err != nil { topoStatsConnErrors.Add(statsKey, int64(1)) diff --git a/go/vt/topo/stats_conn_test.go b/go/vt/topo/stats_conn_test.go index 78f9cc6eb72..605487697cc 100644 --- a/go/vt/topo/stats_conn_test.go +++ b/go/vt/topo/stats_conn_test.go @@ -20,6 +20,9 @@ import ( "context" "fmt" "testing" + "time" + + "github.com/stretchr/testify/require" "vitess.io/vitess/go/vt/proto/vtrpc" "vitess.io/vitess/go/vt/vterrors" @@ -108,7 +111,28 @@ func (st *fakeConn) Lock(ctx context.Context, dirPath, contents string) (lock Lo } if dirPath == "error" { return lock, fmt.Errorf("dummy error") + } + return lock, err +} +// LockWithTTL is part of the Conn interface. +func (st *fakeConn) LockWithTTL(ctx context.Context, dirPath, contents string, _ time.Duration) (lock LockDescriptor, err error) { + if st.readOnly { + return nil, vterrors.Errorf(vtrpc.Code_READ_ONLY, "topo server connection is read-only") + } + if dirPath == "error" { + return lock, fmt.Errorf("dummy error") + } + return lock, err +} + +// LockName is part of the Conn interface. +func (st *fakeConn) LockName(ctx context.Context, dirPath, contents string) (lock LockDescriptor, err error) { + if st.readOnly { + return nil, vterrors.Errorf(vtrpc.Code_READ_ONLY, "topo server connection is read-only") + } + if dirPath == "error" { + return lock, fmt.Errorf("dummy error") } return lock, err } @@ -121,7 +145,6 @@ func (st *fakeConn) TryLock(ctx context.Context, dirPath, contents string) (lock } if dirPath == "error" { return lock, fmt.Errorf("dummy error") - } return lock, err } @@ -140,7 +163,6 @@ func (st *fakeConn) WatchRecursive(ctx context.Context, path string) (current [] func (st *fakeConn) NewLeaderParticipation(name, id string) (mp LeaderParticipation, err error) { if name == "error" { return mp, fmt.Errorf("dummy error") - } return mp, err } @@ -302,23 +324,25 @@ func TestStatsConnTopoLock(t *testing.T) { statsConn.Lock(ctx, "", "") timingCounts := topoStatsConnTimings.Counts()["Lock.global"] - if got, want := timingCounts, int64(1); got != want { - t.Errorf("stats were not properly recorded: got = %d, want = %d", got, want) - } + require.Equal(t, timingCounts, int64(1)) - // error is zero before getting an error + statsConn.LockWithTTL(ctx, "", "", time.Second) + timingCounts = topoStatsConnTimings.Counts()["LockWithTTL.global"] + require.Equal(t, timingCounts, int64(1)) + + statsConn.LockName(ctx, "", "") + timingCounts = topoStatsConnTimings.Counts()["LockName.global"] + require.Equal(t, timingCounts, int64(1)) + + // Error is zero before getting an error. errorCount := topoStatsConnErrors.Counts()["Lock.global"] - if got, want := errorCount, int64(0); got != want { - t.Errorf("stats were not properly recorded: got = %d, want = %d", got, want) - } + require.Equal(t, errorCount, int64(0)) statsConn.Lock(ctx, "error", "") - // error stats gets emitted + // Error stats gets emitted. errorCount = topoStatsConnErrors.Counts()["Lock.global"] - if got, want := errorCount, int64(1); got != want { - t.Errorf("stats were not properly recorded: got = %d, want = %d", got, want) - } + require.Equal(t, errorCount, int64(1)) } // TestStatsConnTopoWatch emits stats on Watch diff --git a/go/vt/topo/topotests/srv_vschema_test.go b/go/vt/topo/topotests/srv_vschema_test.go index 85a2d65c4ec..8fd818150b0 100644 --- a/go/vt/topo/topotests/srv_vschema_test.go +++ b/go/vt/topo/topotests/srv_vschema_test.go @@ -29,6 +29,7 @@ import ( func TestRebuildVSchema(t *testing.T) { emptySrvVSchema := &vschemapb.SrvVSchema{ + MirrorRules: &vschemapb.MirrorRules{}, RoutingRules: &vschemapb.RoutingRules{}, ShardRoutingRules: &vschemapb.ShardRoutingRules{}, } @@ -52,6 +53,7 @@ func TestRebuildVSchema(t *testing.T) { // create a keyspace, rebuild, should see an empty entry emptyKs1SrvVSchema := &vschemapb.SrvVSchema{ + MirrorRules: &vschemapb.MirrorRules{}, RoutingRules: &vschemapb.RoutingRules{}, ShardRoutingRules: &vschemapb.ShardRoutingRules{}, Keyspaces: map[string]*vschemapb.Keyspace{ @@ -81,6 +83,7 @@ func TestRebuildVSchema(t *testing.T) { t.Errorf("RebuildVSchema failed: %v", err) } wanted1 := &vschemapb.SrvVSchema{ + MirrorRules: &vschemapb.MirrorRules{}, RoutingRules: &vschemapb.RoutingRules{}, ShardRoutingRules: &vschemapb.ShardRoutingRules{}, Keyspaces: map[string]*vschemapb.Keyspace{ @@ -122,6 +125,7 @@ func TestRebuildVSchema(t *testing.T) { t.Errorf("RebuildVSchema failed: %v", err) } wanted2 := &vschemapb.SrvVSchema{ + MirrorRules: &vschemapb.MirrorRules{}, RoutingRules: &vschemapb.RoutingRules{}, ShardRoutingRules: &vschemapb.ShardRoutingRules{}, Keyspaces: map[string]*vschemapb.Keyspace{ @@ -160,6 +164,7 @@ func TestRebuildVSchema(t *testing.T) { t.Errorf("RebuildVSchema failed: %v", err) } wanted3 := &vschemapb.SrvVSchema{ + MirrorRules: &vschemapb.MirrorRules{}, RoutingRules: rr, ShardRoutingRules: &vschemapb.ShardRoutingRules{}, Keyspaces: map[string]*vschemapb.Keyspace{ diff --git a/go/vt/topo/vschema.go b/go/vt/topo/vschema.go index c6845691b25..d9802da2c35 100644 --- a/go/vt/topo/vschema.go +++ b/go/vt/topo/vschema.go @@ -212,3 +212,39 @@ func (ts *Server) GetKeyspaceRoutingRules(ctx context.Context) (*vschemapb.Keysp } return rules, nil } + +// GetMirrorRules fetches the mirror rules from the topo. +func (ts *Server) GetMirrorRules(ctx context.Context) (*vschemapb.MirrorRules, error) { + rr := &vschemapb.MirrorRules{} + data, _, err := ts.globalCell.Get(ctx, MirrorRulesFile) + if err != nil { + if IsErrType(err, NoNode) { + return rr, nil + } + return nil, err + } + err = rr.UnmarshalVT(data) + if err != nil { + return nil, vterrors.Wrapf(err, "bad mirror rules data: %q", data) + } + return rr, nil +} + +// SaveMirrorRules saves the mirror rules into the topo. +func (ts *Server) SaveMirrorRules(ctx context.Context, mirrorRules *vschemapb.MirrorRules) error { + data, err := mirrorRules.MarshalVT() + if err != nil { + return err + } + + if len(data) == 0 { + // No vschema, remove it. So we can remove the keyspace. + if err := ts.globalCell.Delete(ctx, MirrorRulesFile, nil); err != nil && !IsErrType(err, NoNode) { + return err + } + return nil + } + + _, err = ts.globalCell.Update(ctx, MirrorRulesFile, data, nil) + return err +} diff --git a/go/vt/topo/zk2topo/lock.go b/go/vt/topo/zk2topo/lock.go index 5baf1f7f33f..fdd9fbd0137 100644 --- a/go/vt/topo/zk2topo/lock.go +++ b/go/vt/topo/zk2topo/lock.go @@ -20,6 +20,7 @@ import ( "context" "fmt" "path" + "time" "github.com/z-division/go-zookeeper/zk" @@ -42,6 +43,17 @@ func (zs *Server) Lock(ctx context.Context, dirPath, contents string) (topo.Lock return zs.lock(ctx, dirPath, contents) } +// LockWithTTL is part of the topo.Conn interface. It behaves the same as Lock +// as TTLs are not supported in Zookeeper. +func (zs *Server) LockWithTTL(ctx context.Context, dirPath, contents string, _ time.Duration) (topo.LockDescriptor, error) { + return zs.lock(ctx, dirPath, contents) +} + +// LockName is part of the topo.Conn interface. +func (zs *Server) LockName(ctx context.Context, dirPath, contents string) (topo.LockDescriptor, error) { + return zs.lock(ctx, dirPath, contents) +} + // TryLock is part of the topo.Conn interface. func (zs *Server) TryLock(ctx context.Context, dirPath, contents string) (topo.LockDescriptor, error) { // We list all the entries under dirPath diff --git a/go/vt/topotools/mirror_rules.go b/go/vt/topotools/mirror_rules.go new file mode 100644 index 00000000000..3076a12b394 --- /dev/null +++ b/go/vt/topotools/mirror_rules.go @@ -0,0 +1,72 @@ +/* +Copyright 2024 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 topotools + +import ( + "context" + + "vitess.io/vitess/go/vt/log" + "vitess.io/vitess/go/vt/topo" + + vschemapb "vitess.io/vitess/go/vt/proto/vschema" +) + +func GetMirrorRulesMap(rules *vschemapb.MirrorRules) map[string]map[string]float32 { + if rules == nil { + return nil + } + rulesMap := make(map[string]map[string]float32) + for _, mr := range rules.Rules { + if _, ok := rulesMap[mr.FromTable]; !ok { + rulesMap[mr.FromTable] = make(map[string]float32) + } + rulesMap[mr.FromTable][mr.ToTable] = mr.Percent + } + return rulesMap +} + +// GetMirrorRules fetches mirror rules from the topology server and returns a +// mapping of fromTable=>toTable=>percent. +func GetMirrorRules(ctx context.Context, ts *topo.Server) (map[string]map[string]float32, error) { + mrs, err := ts.GetMirrorRules(ctx) + if err != nil { + return nil, err + } + + rules := GetMirrorRulesMap(mrs) + + return rules, nil +} + +// SaveMirrorRules converts a mapping of fromTable=>[]toTables into a +// vschemapb.MirrorRules protobuf message and saves it in the topology. +func SaveMirrorRules(ctx context.Context, ts *topo.Server, rules map[string]map[string]float32) error { + log.Infof("Saving mirror rules %v\n", rules) + + rrs := &vschemapb.MirrorRules{Rules: make([]*vschemapb.MirrorRule, 0)} + for fromTable, mrs := range rules { + for toTable, percent := range mrs { + rrs.Rules = append(rrs.Rules, &vschemapb.MirrorRule{ + FromTable: fromTable, + Percent: percent, + ToTable: toTable, + }) + } + } + + return ts.SaveMirrorRules(ctx, rrs) +} diff --git a/go/vt/topotools/mirror_rules_test.go b/go/vt/topotools/mirror_rules_test.go new file mode 100644 index 00000000000..3ce25cb4de6 --- /dev/null +++ b/go/vt/topotools/mirror_rules_test.go @@ -0,0 +1,79 @@ +/* +Copyright 2024 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 topotools + +import ( + "context" + "errors" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/vt/topo/memorytopo" +) + +func TestMirrorRulesRoundTrip(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + ts := memorytopo.NewServer(ctx, "zone1") + defer ts.Close() + + rules := map[string]map[string]float32{ + "k1.t1@replica": { + "k2": 50.0, + }, + "k1.t4": { + "k3": 75.0, + }, + } + + err := SaveMirrorRules(ctx, ts, rules) + require.NoError(t, err, "could not save mirror rules to topo %v", rules) + + roundtripRules, err := GetMirrorRules(ctx, ts) + require.NoError(t, err, "could not fetch mirror rules from topo") + + assert.Equal(t, rules, roundtripRules) +} + +func TestMirrorRulesErrors(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + ts, factory := memorytopo.NewServerAndFactory(ctx, "zone1") + defer ts.Close() + factory.SetError(errors.New("topo failure for testing")) + + t.Run("GetMirrorRules error", func(t *testing.T) { + rules, err := GetMirrorRules(ctx, ts) + assert.Error(t, err, "expected error from GetMirrorRules, got rules=%v", rules) + }) + + t.Run("SaveMirrorRules error", func(t *testing.T) { + rules := map[string]map[string]float32{ + "k1.t1@replica": { + "k2": 50.0, + }, + "k1.t4": { + "k3": 75.0, + }, + } + + err := SaveMirrorRules(ctx, ts, rules) + assert.Error(t, err, "expected error from SaveMirrorRules, got rules=%v", rules) + }) +} diff --git a/go/vt/vitessdriver/fakeserver_test.go b/go/vt/vitessdriver/fakeserver_test.go index a74e44e682c..a4b17fc65d6 100644 --- a/go/vt/vitessdriver/fakeserver_test.go +++ b/go/vt/vitessdriver/fakeserver_test.go @@ -18,7 +18,6 @@ package vitessdriver import ( "context" - "errors" "fmt" "reflect" @@ -156,14 +155,6 @@ func (f *fakeVTGateService) CloseSession(ctx context.Context, session *vtgatepb. return nil } -// ResolveTransaction is part of the VTGateService interface -func (f *fakeVTGateService) ResolveTransaction(ctx context.Context, dtid string) error { - if dtid != dtid2 { - return errors.New("ResolveTransaction: dtid mismatch") - } - return nil -} - func (f *fakeVTGateService) VStream(ctx context.Context, tabletType topodatapb.TabletType, vgtid *binlogdatapb.VGtid, filter *binlogdatapb.Filter, flags *vtgatepb.VStreamFlags, send func([]*binlogdatapb.VEvent) error) error { return nil } diff --git a/go/vt/vitessdriver/rows.go b/go/vt/vitessdriver/rows.go index 1af88e64ec3..d3c5ca7e4d4 100644 --- a/go/vt/vitessdriver/rows.go +++ b/go/vt/vitessdriver/rows.go @@ -110,7 +110,7 @@ func (ri *rows) ColumnTypeScanType(index int) reflect.Type { case query.Type_TIMESTAMP, query.Type_DECIMAL, query.Type_VARCHAR, query.Type_TEXT, query.Type_BLOB, query.Type_VARBINARY, query.Type_CHAR, query.Type_BINARY, query.Type_BIT, query.Type_ENUM, query.Type_SET, query.Type_TUPLE, query.Type_GEOMETRY, query.Type_JSON, - query.Type_HEXNUM, query.Type_HEXVAL, query.Type_BITNUM: + query.Type_HEXNUM, query.Type_HEXVAL, query.Type_BITNUM, query.Type_VECTOR: return typeRawBytes case query.Type_DATE, query.Type_TIME, query.Type_DATETIME: @@ -179,6 +179,8 @@ func (ri *rows) ColumnTypeDatabaseTypeName(index int) string { return "GEOMETRY" case query.Type_JSON: return "JSON" + case query.Type_VECTOR: + return "VECTOR" case query.Type_TIMESTAMP: return "TIMESTAMP" case query.Type_DATE: diff --git a/go/vt/vtcombo/tablet_map.go b/go/vt/vtcombo/tablet_map.go index 27fbf2dd6e3..77b7446fc1d 100644 --- a/go/vt/vtcombo/tablet_map.go +++ b/go/vt/vtcombo/tablet_map.go @@ -165,6 +165,23 @@ func InitRoutingRules( return ts.RebuildSrvVSchema(ctx, nil) } +// InitMirrorRules saves the mirror rules into ts and reloads the vschema. +func InitMirrorRules( + ctx context.Context, + ts *topo.Server, + mr *vschemapb.MirrorRules, +) error { + if mr == nil { + return nil + } + + if err := ts.SaveMirrorRules(ctx, mr); err != nil { + return err + } + + return ts.RebuildSrvVSchema(ctx, nil) +} + // InitTabletMap creates the action tms and associated data structures // for all tablets, based on the vttest proto parameter. func InitTabletMap( @@ -305,6 +322,11 @@ func CreateKs( return 0, fmt.Errorf("CreateKeyspace(%v) failed: %v", keyspace, err) } + // make sure a valid vschema has been loaded + if err := ts.EnsureVSchema(ctx, keyspace); err != nil { + return 0, fmt.Errorf("EnsureVSchema(%v) failed: %v", keyspace, err) + } + // iterate through the shards for _, spb := range kpb.Shards { shard := spb.Name @@ -536,6 +558,12 @@ func (itc *internalTabletConn) ReadTransaction(ctx context.Context, target *quer return metadata, tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err)) } +// UnresolvedTransactions is part of queryservice.QueryService +func (itc *internalTabletConn) UnresolvedTransactions(ctx context.Context, target *querypb.Target) (transactions []*querypb.TransactionMetadata, err error) { + transactions, err = itc.tablet.qsc.QueryService().UnresolvedTransactions(ctx, target) + return transactions, tabletconn.ErrorFromGRPC(vterrors.ToGRPC(err)) +} + // BeginExecute is part of queryservice.QueryService func (itc *internalTabletConn) BeginExecute( ctx context.Context, @@ -958,6 +986,10 @@ func (itmc *internalTabletManagerClient) CheckThrottler(context.Context, *topoda return nil, fmt.Errorf("not implemented in vtcombo") } +func (itmc *internalTabletManagerClient) GetThrottlerStatus(context.Context, *topodatapb.Tablet, *tabletmanagerdatapb.GetThrottlerStatusRequest) (*tabletmanagerdatapb.GetThrottlerStatusResponse, error) { + return nil, fmt.Errorf("not implemented in vtcombo") +} + func (itmc *internalTabletManagerClient) Close() { } diff --git a/go/vt/vtctl/endtoend/get_schema_test.go b/go/vt/vtctl/endtoend/get_schema_test.go index a9829a193f3..58e6b220aad 100644 --- a/go/vt/vtctl/endtoend/get_schema_test.go +++ b/go/vt/vtctl/endtoend/get_schema_test.go @@ -173,7 +173,7 @@ func TestGetSchema(t *testing.T) { val := events[0].Value actual := &tabletmanagerdatapb.SchemaDefinition{} - err = json2.Unmarshal([]byte(val), actual) + err = json2.UnmarshalPB([]byte(val), actual) require.NoError(t, err) utils.MustMatch(t, sd, actual) @@ -214,7 +214,7 @@ func TestGetSchema(t *testing.T) { val = events[0].Value actual = &tabletmanagerdatapb.SchemaDefinition{} - err = json2.Unmarshal([]byte(val), actual) + err = json2.UnmarshalPB([]byte(val), actual) require.NoError(t, err) utils.MustMatch(t, sd, actual) diff --git a/go/vt/vtctl/grpcvtctldclient/client_gen.go b/go/vt/vtctl/grpcvtctldclient/client_gen.go index e0b14337bba..2153d2c94f4 100644 --- a/go/vt/vtctl/grpcvtctldclient/client_gen.go +++ b/go/vt/vtctl/grpcvtctldclient/client_gen.go @@ -362,6 +362,15 @@ func (client *gRPCVtctldClient) GetKeyspaces(ctx context.Context, in *vtctldatap return client.c.GetKeyspaces(ctx, in, opts...) } +// GetMirrorRules is part of the vtctlservicepb.VtctldClient interface. +func (client *gRPCVtctldClient) GetMirrorRules(ctx context.Context, in *vtctldatapb.GetMirrorRulesRequest, opts ...grpc.CallOption) (*vtctldatapb.GetMirrorRulesResponse, error) { + if client.c == nil { + return nil, status.Error(codes.Unavailable, connClosedMsg) + } + + return client.c.GetMirrorRules(ctx, in, opts...) +} + // GetPermissions is part of the vtctlservicepb.VtctldClient interface. func (client *gRPCVtctldClient) GetPermissions(ctx context.Context, in *vtctldatapb.GetPermissionsRequest, opts ...grpc.CallOption) (*vtctldatapb.GetPermissionsResponse, error) { if client.c == nil { @@ -1055,6 +1064,15 @@ func (client *gRPCVtctldClient) WorkflowDelete(ctx context.Context, in *vtctldat return client.c.WorkflowDelete(ctx, in, opts...) } +// WorkflowMirrorTraffic is part of the vtctlservicepb.VtctldClient interface. +func (client *gRPCVtctldClient) WorkflowMirrorTraffic(ctx context.Context, in *vtctldatapb.WorkflowMirrorTrafficRequest, opts ...grpc.CallOption) (*vtctldatapb.WorkflowMirrorTrafficResponse, error) { + if client.c == nil { + return nil, status.Error(codes.Unavailable, connClosedMsg) + } + + return client.c.WorkflowMirrorTraffic(ctx, in, opts...) +} + // WorkflowStatus is part of the vtctlservicepb.VtctldClient interface. func (client *gRPCVtctldClient) WorkflowStatus(ctx context.Context, in *vtctldatapb.WorkflowStatusRequest, opts ...grpc.CallOption) (*vtctldatapb.WorkflowStatusResponse, error) { if client.c == nil { diff --git a/go/vt/vtctl/grpcvtctldserver/server.go b/go/vt/vtctl/grpcvtctldserver/server.go index 92ae7c66146..0ab76e6b523 100644 --- a/go/vt/vtctl/grpcvtctldserver/server.go +++ b/go/vt/vtctl/grpcvtctldserver/server.go @@ -64,6 +64,7 @@ import ( "vitess.io/vitess/go/vt/vtenv" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/vindexes" + "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base" "vitess.io/vitess/go/vt/vttablet/tmclient" logutilpb "vitess.io/vitess/go/vt/proto/logutil" @@ -291,7 +292,6 @@ func (s *VtctldServer) ApplySchema(ctx context.Context, req *vtctldatapb.ApplySc schemamanager.NewPlainController(req.Sql, req.Keyspace), executor, ) - if err != nil { return nil, err } @@ -464,7 +464,6 @@ func (s *VtctldServer) BackupShard(req *vtctldatapb.BackupShardRequest, stream v span.Annotate("incremental_from_pos", req.IncrementalFromPos) tablets, stats, err := reparentutil.ShardReplicationStatuses(ctx, s.ts, s.tmc, req.Keyspace, req.Shard) - // Instead of return on err directly, only return err when no tablets for backup at all if err != nil { tablets = reparentutil.GetBackupCandidates(tablets, stats) @@ -517,7 +516,8 @@ func (s *VtctldServer) BackupShard(req *vtctldatapb.BackupShardRequest, stream v func (s *VtctldServer) backupTablet(ctx context.Context, tablet *topodatapb.Tablet, req *vtctldatapb.BackupRequest, stream interface { Send(resp *vtctldatapb.BackupResponse) error -}) error { +}, +) error { r := &tabletmanagerdatapb.BackupRequest{ Concurrency: req.Concurrency, AllowPrimary: req.AllowPrimary, @@ -681,6 +681,64 @@ func (s *VtctldServer) ChangeTabletType(ctx context.Context, req *vtctldatapb.Ch }, nil } +// CheckThrottler is part of the vtctlservicepb.VtctldServer interface. +func (s *VtctldServer) CheckThrottler(ctx context.Context, req *vtctldatapb.CheckThrottlerRequest) (resp *vtctldatapb.CheckThrottlerResponse, err error) { + span, ctx := trace.NewSpan(ctx, "VtctldServer.CheckThrottler") + defer span.Finish() + + defer panicHandler(&err) + + span.Annotate("tablet_alias", topoproto.TabletAliasString(req.TabletAlias)) + span.Annotate("app_name", req.AppName) + + ti, err := s.ts.GetTablet(ctx, req.TabletAlias) + if err != nil { + return nil, err + } + + tmReq := &tabletmanagerdatapb.CheckThrottlerRequest{ + AppName: req.AppName, + Scope: req.Scope, + SkipRequestHeartbeats: req.SkipRequestHeartbeats, + OkIfNotExists: req.OkIfNotExists, + MultiMetricsEnabled: true, + } + r, err := s.tmc.CheckThrottler(ctx, ti.Tablet, tmReq) + if err != nil { + return nil, err + } + + resp = &vtctldatapb.CheckThrottlerResponse{ + TabletAlias: req.TabletAlias, + Check: r, + } + return resp, nil +} + +// GetThrottlerStatus is part of the vtctlservicepb.VtctldServer interface. +func (s *VtctldServer) GetThrottlerStatus(ctx context.Context, req *vtctldatapb.GetThrottlerStatusRequest) (resp *vtctldatapb.GetThrottlerStatusResponse, err error) { + span, ctx := trace.NewSpan(ctx, "VtctldServer.GetThrottlerStatus") + defer span.Finish() + + defer panicHandler(&err) + + span.Annotate("tablet_alias", topoproto.TabletAliasString(req.TabletAlias)) + + ti, err := s.ts.GetTablet(ctx, req.TabletAlias) + if err != nil { + return nil, err + } + + r, err := s.tmc.GetThrottlerStatus(ctx, ti.Tablet, &tabletmanagerdatapb.GetThrottlerStatusRequest{}) + if err != nil { + return nil, err + } + resp = &vtctldatapb.GetThrottlerStatusResponse{ + Status: r, + } + return resp, nil +} + // CleanupSchemaMigration is part of the vtctlservicepb.VtctldServer interface. func (s *VtctldServer) CleanupSchemaMigration(ctx context.Context, req *vtctldatapb.CleanupSchemaMigrationRequest) (resp *vtctldatapb.CleanupSchemaMigrationResponse, err error) { span, ctx := trace.NewSpan(ctx, "VtctldServer.CleanupSchemaMigration") @@ -1898,7 +1956,6 @@ func (s *VtctldServer) GetSrvKeyspaces(ctx context.Context, req *vtctldatapb.Get for _, cell := range cells { var srvKeyspace *topodatapb.SrvKeyspace srvKeyspace, err = s.ts.GetSrvKeyspace(ctx, cell, req.Keyspace) - if err != nil { if !topo.IsErrType(err, topo.NoNode) { return nil, err @@ -1931,6 +1988,24 @@ func (s *VtctldServer) UpdateThrottlerConfig(ctx context.Context, req *vtctldata return nil, fmt.Errorf("--check-as-check-self and --check-as-check-shard are mutually exclusive") } + if req.MetricName != "" && !base.KnownMetricNames.Contains(base.MetricName(req.MetricName)) { + return nil, fmt.Errorf("unknown metric name: %s", req.MetricName) + } + + if len(req.AppCheckedMetrics) > 0 { + specifiedMetrics := map[base.MetricName]bool{} + for _, metricName := range req.AppCheckedMetrics { + _, knownMetric, err := base.DisaggregateMetricName(metricName) + if err != nil { + return nil, fmt.Errorf("invalid metric name: %s", metricName) + } + if _, ok := specifiedMetrics[knownMetric]; ok { + return nil, fmt.Errorf("duplicate metric name: %s", knownMetric) + } + specifiedMetrics[knownMetric] = true + } + } + update := func(throttlerConfig *topodatapb.ThrottlerConfig) *topodatapb.ThrottlerConfig { if throttlerConfig == nil { throttlerConfig = &topodatapb.ThrottlerConfig{} @@ -1938,14 +2013,37 @@ func (s *VtctldServer) UpdateThrottlerConfig(ctx context.Context, req *vtctldata if throttlerConfig.ThrottledApps == nil { throttlerConfig.ThrottledApps = make(map[string]*topodatapb.ThrottledAppRule) } - if req.CustomQuerySet { - // custom query provided - throttlerConfig.CustomQuery = req.CustomQuery - throttlerConfig.Threshold = req.Threshold // allowed to be zero/negative because who knows what kind of custom query this is + if throttlerConfig.AppCheckedMetrics == nil { + throttlerConfig.AppCheckedMetrics = make(map[string]*topodatapb.ThrottlerConfig_MetricNames) + } + if throttlerConfig.MetricThresholds == nil { + throttlerConfig.MetricThresholds = make(map[string]float64) + } + if req.MetricName == "" { + // v20 behavior + if req.CustomQuerySet { + // custom query provided + throttlerConfig.CustomQuery = req.CustomQuery + throttlerConfig.Threshold = req.Threshold // allowed to be zero/negative because who knows what kind of custom query this is + } else if req.Threshold > 0 { + // no custom query, throttler works by querying replication lag. We only allow positive values + throttlerConfig.Threshold = req.Threshold + } } else { - // no custom query, throttler works by querying replication lag. We only allow positive values + // --metric-name specified. We apply the threshold to the metric if req.Threshold > 0 { - throttlerConfig.Threshold = req.Threshold + throttlerConfig.MetricThresholds[req.MetricName] = req.Threshold + } else { + delete(throttlerConfig.MetricThresholds, req.MetricName) + } + } + if req.AppName != "" { + if len(req.AppCheckedMetrics) > 0 { + throttlerConfig.AppCheckedMetrics[req.AppName] = &topodatapb.ThrottlerConfig_MetricNames{ + Names: req.AppCheckedMetrics, + } + } else { + delete(throttlerConfig.AppCheckedMetrics, req.AppName) } } if req.Enable { @@ -1961,7 +2059,14 @@ func (s *VtctldServer) UpdateThrottlerConfig(ctx context.Context, req *vtctldata throttlerConfig.CheckAsCheckSelf = false } if req.ThrottledApp != nil && req.ThrottledApp.Name != "" { + // TODO(shlomi) in v22: replace the following line with the commented out block throttlerConfig.ThrottledApps[req.ThrottledApp.Name] = req.ThrottledApp + // timeNow := time.Now() + // if protoutil.TimeFromProto(req.ThrottledApp.ExpiresAt).After(timeNow) { + // throttlerConfig.ThrottledApps[req.ThrottledApp.Name] = req.ThrottledApp + // } else { + // delete(throttlerConfig.ThrottledApps, req.ThrottledApp.Name) + // } } return throttlerConfig } @@ -2036,7 +2141,6 @@ func (s *VtctldServer) GetSrvVSchemas(ctx context.Context, req *vtctldatapb.GetS for _, cell := range cells { var sv *vschemapb.SrvVSchema sv, err = s.ts.GetSrvVSchema(ctx, cell) - if err != nil { if !topo.IsErrType(err, topo.NoNode) { return nil, err @@ -3289,6 +3393,7 @@ func (s *VtctldServer) ReshardCreate(ctx context.Context, req *vtctldatapb.Resha resp, err = s.ws.ReshardCreate(ctx, req) return resp, err } + func (s *VtctldServer) RestoreFromBackup(req *vtctldatapb.RestoreFromBackupRequest, stream vtctlservicepb.Vtctld_RestoreFromBackupServer) (err error) { span, ctx := trace.NewSpan(stream.Context(), "VtctldServer.RestoreFromBackup") defer span.Finish() @@ -4119,7 +4224,6 @@ func (s *VtctldServer) UpdateCellInfo(ctx context.Context, req *vtctldatapb.Upda return nil }) - if err != nil { return nil, err } @@ -4150,7 +4254,6 @@ func (s *VtctldServer) UpdateCellsAlias(ctx context.Context, req *vtctldatapb.Up ca.Cells = req.CellsAlias.Cells return nil }) - if err != nil { return nil, err } @@ -5060,6 +5163,38 @@ func (s *VtctldServer) WorkflowUpdate(ctx context.Context, req *vtctldatapb.Work return resp, err } +// GetMirrorRules is part of the vtctlservicepb.VtctldServer interface. +func (s *VtctldServer) GetMirrorRules(ctx context.Context, req *vtctldatapb.GetMirrorRulesRequest) (resp *vtctldatapb.GetMirrorRulesResponse, err error) { + span, ctx := trace.NewSpan(ctx, "VtctldServer.GetMirrorRules") + defer span.Finish() + + defer panicHandler(&err) + + mr, err := s.ts.GetMirrorRules(ctx) + if err != nil { + return nil, err + } + + return &vtctldatapb.GetMirrorRulesResponse{ + MirrorRules: mr, + }, nil +} + +// WorkflowMirrorTraffic is part of the vtctlservicepb.VtctldServer interface. +func (s *VtctldServer) WorkflowMirrorTraffic(ctx context.Context, req *vtctldatapb.WorkflowMirrorTrafficRequest) (resp *vtctldatapb.WorkflowMirrorTrafficResponse, err error) { + span, ctx := trace.NewSpan(ctx, "VtctldServer.WorkflowMirrorTraffic") + defer span.Finish() + + defer panicHandler(&err) + + span.Annotate("keyspace", req.Keyspace) + span.Annotate("workflow", req.Workflow) + span.Annotate("percent", req.Percent) + + resp, err = s.ws.WorkflowMirrorTraffic(ctx, req) + return resp, err +} + // StartServer registers a VtctldServer for RPCs on the given gRPC server. func StartServer(s *grpc.Server, env *vtenv.Environment, ts *topo.Server) { vtctlservicepb.RegisterVtctldServer(s, NewVtctldServer(env, ts)) @@ -5150,8 +5285,10 @@ var getVersionFromTabletDebugVars = func(tabletAddr string) (string, error) { return version, nil } -var versionFuncMu sync.Mutex -var getVersionFromTablet = getVersionFromTabletDebugVars +var ( + versionFuncMu sync.Mutex + getVersionFromTablet = getVersionFromTabletDebugVars +) func SetVersionFunc(versionFunc func(string) (string, error)) { versionFuncMu.Lock() diff --git a/go/vt/vtctl/grpcvtctldserver/server_slow_test.go b/go/vt/vtctl/grpcvtctldserver/server_slow_test.go index 4d7c5aa1943..6c73bb1d264 100644 --- a/go/vt/vtctl/grpcvtctldserver/server_slow_test.go +++ b/go/vt/vtctl/grpcvtctldserver/server_slow_test.go @@ -25,6 +25,7 @@ import ( "github.com/stretchr/testify/require" "vitess.io/vitess/go/mysql/replication" + "vitess.io/vitess/go/vt/vtctl/reparentutil" "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/protoutil" @@ -402,19 +403,24 @@ func TestPlannedReparentShardSlow(t *testing.T) { Error: nil, }, }, - // This is only needed to verify reachability, so empty results are fine. - PrimaryStatusResults: map[string]struct { - Status *replicationdatapb.PrimaryStatus - Error error + GetGlobalStatusVarsResults: map[string]struct { + Statuses map[string]string + Error error }{ "zone1-0000000200": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + reparentutil.InnodbBufferPoolsDataVar: "123", + }, }, "zone1-0000000101": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + reparentutil.InnodbBufferPoolsDataVar: "123", + }, }, "zone1-0000000100": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + reparentutil.InnodbBufferPoolsDataVar: "123", + }, }, }, PrimaryPositionResults: map[string]struct { @@ -519,19 +525,24 @@ func TestPlannedReparentShardSlow(t *testing.T) { Error: nil, }, }, - // This is only needed to verify reachability, so empty results are fine. - PrimaryStatusResults: map[string]struct { - Status *replicationdatapb.PrimaryStatus - Error error + GetGlobalStatusVarsResults: map[string]struct { + Statuses map[string]string + Error error }{ "zone1-0000000200": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + reparentutil.InnodbBufferPoolsDataVar: "123", + }, }, "zone1-0000000101": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + reparentutil.InnodbBufferPoolsDataVar: "123", + }, }, "zone1-0000000100": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + reparentutil.InnodbBufferPoolsDataVar: "123", + }, }, }, PrimaryPositionResults: map[string]struct { diff --git a/go/vt/vtctl/grpcvtctldserver/server_test.go b/go/vt/vtctl/grpcvtctldserver/server_test.go index f72b92479a1..b98087d0560 100644 --- a/go/vt/vtctl/grpcvtctldserver/server_test.go +++ b/go/vt/vtctl/grpcvtctldserver/server_test.go @@ -29,6 +29,7 @@ import ( "time" _flag "vitess.io/vitess/go/internal/flag" + "vitess.io/vitess/go/vt/vtctl/reparentutil" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -665,6 +666,9 @@ func TestApplyVSchema(t *testing.T) { Sharded: false, }, }, + MirrorRules: &vschemapb.MirrorRules{ + Rules: []*vschemapb.MirrorRule{}, + }, RoutingRules: &vschemapb.RoutingRules{ Rules: []*vschemapb.RoutingRule{}, }, @@ -8293,19 +8297,24 @@ func TestPlannedReparentShard(t *testing.T) { Error: nil, }, }, - // This is only needed to verify reachability, so empty results are fine. - PrimaryStatusResults: map[string]struct { - Status *replicationdatapb.PrimaryStatus - Error error + GetGlobalStatusVarsResults: map[string]struct { + Statuses map[string]string + Error error }{ "zone1-0000000200": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + reparentutil.InnodbBufferPoolsDataVar: "123", + }, }, "zone1-0000000101": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + reparentutil.InnodbBufferPoolsDataVar: "123", + }, }, "zone1-0000000100": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + reparentutil.InnodbBufferPoolsDataVar: "123", + }, }, }, PrimaryPositionResults: map[string]struct { @@ -8422,19 +8431,22 @@ func TestPlannedReparentShard(t *testing.T) { }, }, tmc: &testutil.TabletManagerClient{ - // This is only needed to verify reachability, so empty results are fine. - PrimaryStatusResults: map[string]struct { - Status *replicationdatapb.PrimaryStatus - Error error + GetGlobalStatusVarsResults: map[string]struct { + Statuses map[string]string + Error error }{ "zone1-0000000200": { - Error: fmt.Errorf("primary status failed"), + Error: fmt.Errorf("global status vars failed"), }, "zone1-0000000101": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + reparentutil.InnodbBufferPoolsDataVar: "123", + }, }, "zone1-0000000100": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + reparentutil.InnodbBufferPoolsDataVar: "123", + }, }, }, }, @@ -8448,7 +8460,7 @@ func TestPlannedReparentShard(t *testing.T) { WaitReplicasTimeout: protoutil.DurationToProto(time.Millisecond * 10), }, expectEventsToOccur: true, - expectedErr: "primary status failed", + expectedErr: "global status vars failed", }, } diff --git a/go/vt/vtctl/grpcvtctldserver/testutil/test_tmclient.go b/go/vt/vtctl/grpcvtctldserver/testutil/test_tmclient.go index ba560129459..a17ad376e0b 100644 --- a/go/vt/vtctl/grpcvtctldserver/testutil/test_tmclient.go +++ b/go/vt/vtctl/grpcvtctldserver/testutil/test_tmclient.go @@ -250,6 +250,7 @@ type TabletManagerClient struct { Schema *tabletmanagerdatapb.SchemaDefinition Error error } + GetGlobalStatusVarsDelays map[string]time.Duration GetGlobalStatusVarsResults map[string]struct { Statuses map[string]string Error error @@ -742,6 +743,17 @@ func (fake *TabletManagerClient) GetGlobalStatusVars(ctx context.Context, tablet } key := topoproto.TabletAliasString(tablet.Alias) + if fake.GetGlobalStatusVarsDelays != nil { + if delay, ok := fake.GetGlobalStatusVarsDelays[key]; ok { + select { + case <-ctx.Done(): + return nil, ctx.Err() + case <-time.After(delay): + // proceed to results + } + } + } + if result, ok := fake.GetGlobalStatusVarsResults[key]; ok { return result.Statuses, result.Error } diff --git a/go/vt/vtctl/localvtctldclient/client_gen.go b/go/vt/vtctl/localvtctldclient/client_gen.go index 3457c355cb6..2738c771be3 100644 --- a/go/vt/vtctl/localvtctldclient/client_gen.go +++ b/go/vt/vtctl/localvtctldclient/client_gen.go @@ -306,6 +306,11 @@ func (client *localVtctldClient) GetKeyspaces(ctx context.Context, in *vtctldata return client.s.GetKeyspaces(ctx, in) } +// GetMirrorRules is part of the vtctlservicepb.VtctldClient interface. +func (client *localVtctldClient) GetMirrorRules(ctx context.Context, in *vtctldatapb.GetMirrorRulesRequest, opts ...grpc.CallOption) (*vtctldatapb.GetMirrorRulesResponse, error) { + return client.s.GetMirrorRules(ctx, in) +} + // GetPermissions is part of the vtctlservicepb.VtctldClient interface. func (client *localVtctldClient) GetPermissions(ctx context.Context, in *vtctldatapb.GetPermissionsRequest, opts ...grpc.CallOption) (*vtctldatapb.GetPermissionsResponse, error) { return client.s.GetPermissions(ctx, in) @@ -737,6 +742,11 @@ func (client *localVtctldClient) WorkflowDelete(ctx context.Context, in *vtctlda return client.s.WorkflowDelete(ctx, in) } +// WorkflowMirrorTraffic is part of the vtctlservicepb.VtctldClient interface. +func (client *localVtctldClient) WorkflowMirrorTraffic(ctx context.Context, in *vtctldatapb.WorkflowMirrorTrafficRequest, opts ...grpc.CallOption) (*vtctldatapb.WorkflowMirrorTrafficResponse, error) { + return client.s.WorkflowMirrorTraffic(ctx, in) +} + // WorkflowStatus is part of the vtctlservicepb.VtctldClient interface. func (client *localVtctldClient) WorkflowStatus(ctx context.Context, in *vtctldatapb.WorkflowStatusRequest, opts ...grpc.CallOption) (*vtctldatapb.WorkflowStatusResponse, error) { return client.s.WorkflowStatus(ctx, in) diff --git a/go/vt/vtctl/reparentutil/emergency_reparenter.go b/go/vt/vtctl/reparentutil/emergency_reparenter.go index 60e423c502c..b776a39e1d7 100644 --- a/go/vt/vtctl/reparentutil/emergency_reparenter.go +++ b/go/vt/vtctl/reparentutil/emergency_reparenter.go @@ -202,7 +202,7 @@ func (erp *EmergencyReparenter) reparentShardLocked(ctx context.Context, ev *eve // check that we still have the shard lock. If we don't then we can terminate at this point if err := topo.CheckShardLocked(ctx, keyspace, shard); err != nil { - return vterrors.Wrapf(err, "lost topology lock, aborting: %v", err) + return vterrors.Wrap(err, lostTopologyLockMsg) } // find the valid candidates for becoming the primary @@ -255,8 +255,8 @@ func (erp *EmergencyReparenter) reparentShardLocked(ctx context.Context, ev *eve erp.logger.Infof("intermediate source is ideal candidate- %v", isIdeal) // Check (again) we still have the topology lock. - if err = topo.CheckShardLocked(ctx, keyspace, shard); err != nil { - return vterrors.Wrapf(err, "lost topology lock, aborting: %v", err) + if err := topo.CheckShardLocked(ctx, keyspace, shard); err != nil { + return vterrors.Wrap(err, lostTopologyLockMsg) } // initialize the newPrimary with the intermediate source, override this value if it is not the ideal candidate @@ -287,6 +287,10 @@ func (erp *EmergencyReparenter) reparentShardLocked(ctx context.Context, ev *eve } newPrimary = betterCandidate } + + if err := topo.CheckShardLocked(ctx, keyspace, shard); err != nil { + return vterrors.Wrap(err, lostTopologyLockMsg) + } } // The new primary which will be promoted will always belong to the validCandidateTablets list because - @@ -386,7 +390,7 @@ func (erp *EmergencyReparenter) findMostAdvanced( } // sort the tablets for finding the best intermediate source in ERS - err = sortTabletsForReparent(validTablets, tabletPositions, opts.durability) + err = sortTabletsForReparent(validTablets, tabletPositions, nil, opts.durability) if err != nil { return nil, nil, err } diff --git a/go/vt/vtctl/reparentutil/planned_reparenter.go b/go/vt/vtctl/reparentutil/planned_reparenter.go index c311a5c836c..e09761ea982 100644 --- a/go/vt/vtctl/reparentutil/planned_reparenter.go +++ b/go/vt/vtctl/reparentutil/planned_reparenter.go @@ -19,6 +19,7 @@ package reparentutil import ( "context" "fmt" + "strconv" "sync" "time" @@ -44,6 +45,7 @@ var ( prsCounter = stats.NewCountersWithMultiLabels("PlannedReparentCounts", "Number of times Planned Reparent Shard has been run", []string{"Keyspace", "Shard", "Result"}, ) + InnodbBufferPoolsDataVar = "Innodb_buffer_pool_pages_data" ) // PlannedReparenter performs PlannedReparentShard operations. @@ -157,9 +159,8 @@ func (pr *PlannedReparenter) getLockAction(opts PlannedReparentOptions) string { func (pr *PlannedReparenter) preflightChecks( ctx context.Context, ev *events.Reparent, - keyspace string, - shard string, tabletMap map[string]*topo.TabletInfo, + innodbBufferPoolData map[string]int, opts *PlannedReparentOptions, // we take a pointer here to set NewPrimaryAlias ) (isNoop bool, err error) { // We don't want to fail when both NewPrimaryAlias and AvoidPrimaryAlias are nil. @@ -180,7 +181,7 @@ func (pr *PlannedReparenter) preflightChecks( } event.DispatchUpdate(ev, "electing a primary candidate") - opts.NewPrimaryAlias, err = ElectNewPrimary(ctx, pr.tmc, &ev.ShardInfo, tabletMap, opts.NewPrimaryAlias, opts.AvoidPrimaryAlias, opts.WaitReplicasTimeout, opts.TolerableReplLag, opts.durability, pr.logger) + opts.NewPrimaryAlias, err = ElectNewPrimary(ctx, pr.tmc, &ev.ShardInfo, tabletMap, innodbBufferPoolData, opts.NewPrimaryAlias, opts.AvoidPrimaryAlias, opts.WaitReplicasTimeout, opts.TolerableReplLag, opts.durability, pr.logger) if err != nil { return true, err } @@ -220,7 +221,6 @@ func (pr *PlannedReparenter) performGracefulPromotion( shard string, currentPrimary *topo.TabletInfo, primaryElect *topodatapb.Tablet, - tabletMap map[string]*topo.TabletInfo, opts PlannedReparentOptions, ) error { primaryElectAliasStr := topoproto.TabletAliasString(primaryElect.Alias) @@ -260,7 +260,7 @@ func (pr *PlannedReparenter) performGracefulPromotion( // Verify we still have the topology lock before doing the demotion. if err := topo.CheckShardLocked(ctx, keyspace, shard); err != nil { - return vterrors.Wrap(err, "lost topology lock; aborting") + return vterrors.Wrap(err, lostTopologyLockMsg) } // Next up, demote the current primary and get its replication position. @@ -375,7 +375,6 @@ func (pr *PlannedReparenter) performPotentialPromotion( shard string, primaryElect *topodatapb.Tablet, tabletMap map[string]*topo.TabletInfo, - opts PlannedReparentOptions, ) error { primaryElectAliasStr := topoproto.TabletAliasString(primaryElect.Alias) @@ -490,7 +489,7 @@ func (pr *PlannedReparenter) performPotentialPromotion( // Check that we still have the topology lock. if err := topo.CheckShardLocked(ctx, keyspace, shard); err != nil { - return vterrors.Wrap(err, "lost topology lock; aborting") + return vterrors.Wrap(err, lostTopologyLockMsg) } return nil } @@ -527,18 +526,23 @@ func (pr *PlannedReparenter) reparentShardLocked( return err } - err = pr.verifyAllTabletsReachable(ctx, tabletMap) + innodbBufferPoolData, err := pr.verifyAllTabletsReachable(ctx, tabletMap) if err != nil { return err } // Check invariants that PlannedReparentShard depends on. - if isNoop, err := pr.preflightChecks(ctx, ev, keyspace, shard, tabletMap, &opts); err != nil { + if isNoop, err := pr.preflightChecks(ctx, ev, tabletMap, innodbBufferPoolData, &opts); err != nil { return err } else if isNoop { return nil } + // Before we run any RPCs that change the cluster configuration, we should ensure we still hold the topology lock. + if err := topo.CheckShardLocked(ctx, keyspace, shard); err != nil { + return vterrors.Wrap(err, lostTopologyLockMsg) + } + currentPrimary := FindCurrentPrimary(tabletMap, pr.logger) reparentJournalPos := "" // promoteReplicaRequired is a boolean that is used to store whether we need to call @@ -594,7 +598,7 @@ func (pr *PlannedReparenter) reparentShardLocked( case currentPrimary == nil && ev.ShardInfo.PrimaryTermStartTime != nil: // Case (2): no clear current primary. Try to find a safe promotion // candidate, and promote to it. - err = pr.performPotentialPromotion(ctx, keyspace, shard, ev.NewPrimary, tabletMap, opts) + err = pr.performPotentialPromotion(ctx, keyspace, shard, ev.NewPrimary, tabletMap) // We need to call `PromoteReplica` when we reparent the tablets. promoteReplicaRequired = true case topoproto.TabletAliasEqual(currentPrimary.Alias, opts.NewPrimaryAlias): @@ -604,7 +608,7 @@ func (pr *PlannedReparenter) reparentShardLocked( default: // Case (4): desired primary and current primary differ. Do a graceful // demotion-then-promotion. - err = pr.performGracefulPromotion(ctx, ev, keyspace, shard, currentPrimary, ev.NewPrimary, tabletMap, opts) + err = pr.performGracefulPromotion(ctx, ev, keyspace, shard, currentPrimary, ev.NewPrimary, opts) // We need to call `PromoteReplica` when we reparent the tablets. promoteReplicaRequired = true } @@ -614,7 +618,7 @@ func (pr *PlannedReparenter) reparentShardLocked( } if err := topo.CheckShardLocked(ctx, keyspace, shard); err != nil { - return vterrors.Wrap(err, "lost topology lock, aborting") + return vterrors.Wrap(err, lostTopologyLockMsg) } if err := pr.reparentTablets(ctx, ev, reparentJournalPos, promoteReplicaRequired, tabletMap, opts); err != nil { @@ -729,18 +733,30 @@ func (pr *PlannedReparenter) reparentTablets( } // verifyAllTabletsReachable verifies that all the tablets are reachable when running PRS. -func (pr *PlannedReparenter) verifyAllTabletsReachable(ctx context.Context, tabletMap map[string]*topo.TabletInfo) error { +func (pr *PlannedReparenter) verifyAllTabletsReachable(ctx context.Context, tabletMap map[string]*topo.TabletInfo) (map[string]int, error) { // Create a cancellable context for the entire set of RPCs to verify reachability. verifyCtx, verifyCancel := context.WithTimeout(ctx, topo.RemoteOperationTimeout) defer verifyCancel() + innodbBufferPoolsData := make(map[string]int) + var mu sync.Mutex errorGroup, groupCtx := errgroup.WithContext(verifyCtx) - for _, info := range tabletMap { + for tblStr, info := range tabletMap { tablet := info.Tablet errorGroup.Go(func() error { - _, err := pr.tmc.PrimaryStatus(groupCtx, tablet) - return err + statusValues, err := pr.tmc.GetGlobalStatusVars(groupCtx, tablet, []string{InnodbBufferPoolsDataVar}) + if err != nil { + return err + } + // We are ignoring the error in conversion because some MySQL variants might not have this + // status variable like MariaDB. + val, _ := strconv.Atoi(statusValues[InnodbBufferPoolsDataVar]) + mu.Lock() + defer mu.Unlock() + innodbBufferPoolsData[tblStr] = val + return nil }) } - return errorGroup.Wait() + err := errorGroup.Wait() + return innodbBufferPoolsData, err } diff --git a/go/vt/vtctl/reparentutil/planned_reparenter_flaky_test.go b/go/vt/vtctl/reparentutil/planned_reparenter_flaky_test.go index 25e4c86f7c5..3a37e178ff8 100644 --- a/go/vt/vtctl/reparentutil/planned_reparenter_flaky_test.go +++ b/go/vt/vtctl/reparentutil/planned_reparenter_flaky_test.go @@ -108,16 +108,19 @@ func TestPlannedReparenter_ReparentShard(t *testing.T) { SetReadWriteResults: map[string]error{ "zone1-0000000100": nil, }, - // This is only needed to verify reachability, so empty results are fine. - PrimaryStatusResults: map[string]struct { - Status *replicationdatapb.PrimaryStatus - Error error + GetGlobalStatusVarsResults: map[string]struct { + Statuses map[string]string + Error error }{ "zone1-0000000200": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, "zone1-0000000100": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, }, }, @@ -229,16 +232,19 @@ func TestPlannedReparenter_ReparentShard(t *testing.T) { PopulateReparentJournalResults: map[string]error{ "zone1-0000000200": nil, }, - // This is only needed to verify reachability, so empty results are fine. - PrimaryStatusResults: map[string]struct { - Status *replicationdatapb.PrimaryStatus - Error error + GetGlobalStatusVarsResults: map[string]struct { + Statuses map[string]string + Error error }{ "zone1-0000000200": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, "zone1-0000000100": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, }, }, @@ -318,16 +324,19 @@ func TestPlannedReparenter_ReparentShard(t *testing.T) { SetReadWriteResults: map[string]error{ "zone1-0000000100": nil, }, - // This is only needed to verify reachability, so empty results are fine. - PrimaryStatusResults: map[string]struct { - Status *replicationdatapb.PrimaryStatus - Error error + GetGlobalStatusVarsResults: map[string]struct { + Statuses map[string]string + Error error }{ "zone1-0000000200": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, "zone1-0000000100": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, }, }, @@ -390,13 +399,14 @@ func TestPlannedReparenter_ReparentShard(t *testing.T) { // thoroughly to cover all the cases. name: "reparent fails", tmc: &testutil.TabletManagerClient{ - // This is only needed to verify reachability, so empty results are fine. - PrimaryStatusResults: map[string]struct { - Status *replicationdatapb.PrimaryStatus - Error error + GetGlobalStatusVarsResults: map[string]struct { + Statuses map[string]string + Error error }{ "zone1-0000000100": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, }, }, @@ -556,11 +566,12 @@ func TestPlannedReparenter_preflightChecks(t *testing.T) { tmc tmclient.TabletManagerClient tablets []*topodatapb.Tablet - ev *events.Reparent - keyspace string - shard string - tabletMap map[string]*topo.TabletInfo - opts *PlannedReparentOptions + ev *events.Reparent + keyspace string + shard string + tabletMap map[string]*topo.TabletInfo + innodbBufferPoolData map[string]int + opts *PlannedReparentOptions expectedIsNoop bool expectedEvent *events.Reparent @@ -812,6 +823,104 @@ func TestPlannedReparenter_preflightChecks(t *testing.T) { }, shouldErr: false, }, + { + name: "primary selection based on buffer pool", + tmc: &testutil.TabletManagerClient{ + ReplicationStatusResults: map[string]struct { + Position *replicationdatapb.Status + Error error + }{ + "zone1-0000000100": { // most advanced position + Position: &replicationdatapb.Status{ + Position: "MySQL56/3E11FA47-71CA-11E1-9E33-C80AA9429562:1-10", + }, + }, + "zone1-0000000101": { + Position: &replicationdatapb.Status{ + Position: "MySQL56/3E11FA47-71CA-11E1-9E33-C80AA9429562:1-10", + }, + }, + }, + }, + innodbBufferPoolData: map[string]int{ + "zone1-0000000100": 100, + "zone1-0000000101": 200, + }, + ev: &events.Reparent{ + ShardInfo: *topo.NewShardInfo("testkeyspace", "-", &topodatapb.Shard{ + PrimaryAlias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 500, + }, + }, nil), + }, + tabletMap: map[string]*topo.TabletInfo{ + "zone1-0000000100": { + Tablet: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 100, + }, + Type: topodatapb.TabletType_REPLICA, + }, + }, + "zone1-0000000101": { + Tablet: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 101, + }, + Type: topodatapb.TabletType_REPLICA, + }, + }, + "zone1-0000000500": { + Tablet: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 500, + }, + Type: topodatapb.TabletType_PRIMARY, + }, + }, + }, + opts: &PlannedReparentOptions{ + // Avoid the current primary. + AvoidPrimaryAlias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 500, + }, + durability: &durabilityNone{}, + }, + expectedIsNoop: false, + expectedEvent: &events.Reparent{ + ShardInfo: *topo.NewShardInfo("testkeyspace", "-", &topodatapb.Shard{ + PrimaryAlias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 500, + }, + }, nil), + NewPrimary: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 101, + }, + Type: topodatapb.TabletType_REPLICA, + }, + }, + expectedOpts: &PlannedReparentOptions{ + AvoidPrimaryAlias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 500, + }, + // NewPrimaryAlias gets populated by the preflightCheck code + NewPrimaryAlias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 101, + }, + durability: &durabilityNone{}, + }, + shouldErr: false, + }, { name: "new-primary and avoid-primary match", opts: &PlannedReparentOptions{ @@ -1081,7 +1190,7 @@ func TestPlannedReparenter_preflightChecks(t *testing.T) { require.NoError(t, err) tt.opts.durability = durability } - isNoop, err := pr.preflightChecks(ctx, tt.ev, tt.keyspace, tt.shard, tt.tabletMap, tt.opts) + isNoop, err := pr.preflightChecks(ctx, tt.ev, tt.tabletMap, tt.innodbBufferPoolData, tt.opts) if tt.shouldErr { assert.Error(t, err) assert.Equal(t, tt.expectedIsNoop, isNoop, "preflightChecks returned wrong isNoop signal") @@ -1109,7 +1218,6 @@ func TestPlannedReparenter_performGracefulPromotion(t *testing.T) { shard string currentPrimary *topo.TabletInfo primaryElect *topodatapb.Tablet - tabletMap map[string]*topo.TabletInfo opts PlannedReparentOptions expectedEvent *events.Reparent @@ -1171,7 +1279,6 @@ func TestPlannedReparenter_performGracefulPromotion(t *testing.T) { Uid: 200, }, }, - tabletMap: map[string]*topo.TabletInfo{}, opts: PlannedReparentOptions{}, shouldErr: false, }, @@ -1204,7 +1311,6 @@ func TestPlannedReparenter_performGracefulPromotion(t *testing.T) { Uid: 200, }, }, - tabletMap: map[string]*topo.TabletInfo{}, opts: PlannedReparentOptions{}, shouldErr: true, }, @@ -1240,7 +1346,6 @@ func TestPlannedReparenter_performGracefulPromotion(t *testing.T) { Uid: 200, }, }, - tabletMap: map[string]*topo.TabletInfo{}, opts: PlannedReparentOptions{}, shouldErr: true, }, @@ -1279,7 +1384,6 @@ func TestPlannedReparenter_performGracefulPromotion(t *testing.T) { Uid: 200, }, }, - tabletMap: map[string]*topo.TabletInfo{}, opts: PlannedReparentOptions{ WaitReplicasTimeout: time.Millisecond * 10, }, @@ -1318,7 +1422,6 @@ func TestPlannedReparenter_performGracefulPromotion(t *testing.T) { Uid: 200, }, }, - tabletMap: map[string]*topo.TabletInfo{}, opts: PlannedReparentOptions{}, shouldErr: true, }, @@ -1362,7 +1465,6 @@ func TestPlannedReparenter_performGracefulPromotion(t *testing.T) { Uid: 200, }, }, - tabletMap: map[string]*topo.TabletInfo{}, opts: PlannedReparentOptions{}, shouldErr: true, }, @@ -1418,7 +1520,6 @@ func TestPlannedReparenter_performGracefulPromotion(t *testing.T) { Uid: 200, }, }, - tabletMap: map[string]*topo.TabletInfo{}, opts: PlannedReparentOptions{}, shouldErr: true, }, @@ -1477,7 +1578,6 @@ func TestPlannedReparenter_performGracefulPromotion(t *testing.T) { Uid: 200, }, }, - tabletMap: map[string]*topo.TabletInfo{}, opts: PlannedReparentOptions{ WaitReplicasTimeout: time.Millisecond * 10, }, @@ -1535,7 +1635,6 @@ func TestPlannedReparenter_performGracefulPromotion(t *testing.T) { Uid: 200, }, }, - tabletMap: map[string]*topo.TabletInfo{}, opts: PlannedReparentOptions{}, shouldErr: true, }, @@ -1594,7 +1693,6 @@ func TestPlannedReparenter_performGracefulPromotion(t *testing.T) { Uid: 200, }, }, - tabletMap: map[string]*topo.TabletInfo{}, opts: PlannedReparentOptions{}, shouldErr: true, extraAssertions: func(t *testing.T, err error) { @@ -1656,7 +1754,6 @@ func TestPlannedReparenter_performGracefulPromotion(t *testing.T) { Uid: 200, }, }, - tabletMap: map[string]*topo.TabletInfo{}, opts: PlannedReparentOptions{}, shouldErr: true, extraAssertions: func(t *testing.T, err error) { @@ -1713,7 +1810,6 @@ func TestPlannedReparenter_performGracefulPromotion(t *testing.T) { tt.shard, tt.currentPrimary, tt.primaryElect, - tt.tabletMap, tt.opts, ) @@ -2395,9 +2491,7 @@ func TestPlannedReparenter_performPotentialPromotion(t *testing.T) { ctx = _ctx } - durability, err := GetDurabilityPolicy("none") - require.NoError(t, err) - err = pr.performPotentialPromotion(ctx, tt.keyspace, tt.shard, tt.primaryElect, tt.tabletMap, PlannedReparentOptions{durability: durability}) + err := pr.performPotentialPromotion(ctx, tt.keyspace, tt.shard, tt.primaryElect, tt.tabletMap) if tt.shouldErr { assert.Error(t, err) @@ -2446,16 +2540,19 @@ func TestPlannedReparenter_reparentShardLocked(t *testing.T) { Error: nil, }, }, - // This is only needed to verify reachability, so empty results are fine. - PrimaryStatusResults: map[string]struct { - Status *replicationdatapb.PrimaryStatus - Error error + GetGlobalStatusVarsResults: map[string]struct { + Statuses map[string]string + Error error }{ "zone1-0000000200": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, "zone1-0000000100": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, }, PopulateReparentJournalResults: map[string]error{ @@ -2538,16 +2635,19 @@ func TestPlannedReparenter_reparentShardLocked(t *testing.T) { SetReadWriteResults: map[string]error{ "zone1-0000000100": nil, }, - // This is only needed to verify reachability, so empty results are fine. - PrimaryStatusResults: map[string]struct { - Status *replicationdatapb.PrimaryStatus - Error error + GetGlobalStatusVarsResults: map[string]struct { + Statuses map[string]string + Error error }{ "zone1-0000000200": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, "zone1-0000000100": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, }, }, @@ -2618,16 +2718,19 @@ func TestPlannedReparenter_reparentShardLocked(t *testing.T) { Error: nil, }, }, - // This is only needed to verify reachability, so empty results are fine. - PrimaryStatusResults: map[string]struct { - Status *replicationdatapb.PrimaryStatus - Error error + GetGlobalStatusVarsResults: map[string]struct { + Statuses map[string]string + Error error }{ "zone1-0000000200": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, "zone1-0000000100": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, }, PrimaryPositionResults: map[string]struct { @@ -2730,16 +2833,19 @@ func TestPlannedReparenter_reparentShardLocked(t *testing.T) { SetReplicationSourceResults: map[string]error{ "zone1-0000000100": nil, // called during reparentTablets to make this tablet a replica of newPrimary }, - // This is only needed to verify reachability, so empty results are fine. - PrimaryStatusResults: map[string]struct { - Status *replicationdatapb.PrimaryStatus - Error error + GetGlobalStatusVarsResults: map[string]struct { + Statuses map[string]string + Error error }{ "zone1-0000000200": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, "zone1-0000000100": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, }, }, @@ -2823,16 +2929,19 @@ func TestPlannedReparenter_reparentShardLocked(t *testing.T) { SetReplicationSourceResults: map[string]error{ "zone1-0000000100": nil, // called during reparentTablets to make this tablet a replica of newPrimary }, - // This is only needed to verify reachability, so empty results are fine. - PrimaryStatusResults: map[string]struct { - Status *replicationdatapb.PrimaryStatus - Error error + GetGlobalStatusVarsResults: map[string]struct { + Statuses map[string]string + Error error }{ "zone1-0000000200": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, "zone1-0000000100": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, }, }, @@ -2882,16 +2991,19 @@ func TestPlannedReparenter_reparentShardLocked(t *testing.T) { { name: "preflight checks determine PRS is no-op", tmc: &testutil.TabletManagerClient{ - // This is only needed to verify reachability, so empty results are fine. - PrimaryStatusResults: map[string]struct { - Status *replicationdatapb.PrimaryStatus - Error error + GetGlobalStatusVarsResults: map[string]struct { + Statuses map[string]string + Error error }{ "zone1-0000000200": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, "zone1-0000000100": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, }, }, @@ -2945,16 +3057,19 @@ func TestPlannedReparenter_reparentShardLocked(t *testing.T) { SetReadWriteResults: map[string]error{ "zone1-0000000100": assert.AnError, }, - // This is only needed to verify reachability, so empty results are fine. - PrimaryStatusResults: map[string]struct { - Status *replicationdatapb.PrimaryStatus - Error error + GetGlobalStatusVarsResults: map[string]struct { + Statuses map[string]string + Error error }{ "zone1-0000000200": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, "zone1-0000000100": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, }, }, @@ -3013,16 +3128,19 @@ func TestPlannedReparenter_reparentShardLocked(t *testing.T) { { name: "lost topology lock", tmc: &testutil.TabletManagerClient{ - // This is only needed to verify reachability, so empty results are fine. - PrimaryStatusResults: map[string]struct { - Status *replicationdatapb.PrimaryStatus - Error error + GetGlobalStatusVarsResults: map[string]struct { + Statuses map[string]string + Error error }{ "zone1-0000000200": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, "zone1-0000000100": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, }, PrimaryPositionResults: map[string]struct { @@ -3104,16 +3222,19 @@ func TestPlannedReparenter_reparentShardLocked(t *testing.T) { Error: nil, }, }, - // This is only needed to verify reachability, so empty results are fine. - PrimaryStatusResults: map[string]struct { - Status *replicationdatapb.PrimaryStatus - Error error + GetGlobalStatusVarsResults: map[string]struct { + Statuses map[string]string + Error error }{ "zone1-0000000200": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, "zone1-0000000100": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, }, PopulateReparentJournalResults: map[string]error{ @@ -3864,27 +3985,34 @@ func AssertReparentEventsEqual(t *testing.T, expected *events.Reparent, actual * // TestPlannedReparenter_verifyAllTabletsReachable tests the functionality of verifyAllTabletsReachable. func TestPlannedReparenter_verifyAllTabletsReachable(t *testing.T) { tests := []struct { - name string - tmc tmclient.TabletManagerClient - tabletMap map[string]*topo.TabletInfo - remoteOpTime time.Duration - wantErr string + name string + tmc tmclient.TabletManagerClient + tabletMap map[string]*topo.TabletInfo + remoteOpTime time.Duration + wantErr string + wantBufferPoolsData map[string]int }{ { name: "Success", tmc: &testutil.TabletManagerClient{ - PrimaryStatusResults: map[string]struct { - Status *replicationdatapb.PrimaryStatus - Error error + GetGlobalStatusVarsResults: map[string]struct { + Statuses map[string]string + Error error }{ "zone1-0000000200": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, "zone1-0000000201": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "1234", + }, }, "zone1-0000000100": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "1231", + }, }, }, }, @@ -3917,21 +4045,30 @@ func TestPlannedReparenter_verifyAllTabletsReachable(t *testing.T) { }, }, }, + wantBufferPoolsData: map[string]int{ + "zone1-0000000200": 123, + "zone1-0000000201": 1234, + "zone1-0000000100": 1231, + }, }, { name: "Failure", tmc: &testutil.TabletManagerClient{ - PrimaryStatusResults: map[string]struct { - Status *replicationdatapb.PrimaryStatus - Error error + GetGlobalStatusVarsResults: map[string]struct { + Statuses map[string]string + Error error }{ "zone1-0000000200": { Error: fmt.Errorf("primary status failed"), }, "zone1-0000000201": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "1234", + }, }, "zone1-0000000100": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "1231", + }, }, }, }, @@ -3968,21 +4105,27 @@ func TestPlannedReparenter_verifyAllTabletsReachable(t *testing.T) { }, { name: "Timeout", tmc: &testutil.TabletManagerClient{ - PrimaryStatusDelays: map[string]time.Duration{ + GetGlobalStatusVarsDelays: map[string]time.Duration{ "zone1-0000000100": 20 * time.Second, }, - PrimaryStatusResults: map[string]struct { - Status *replicationdatapb.PrimaryStatus - Error error + GetGlobalStatusVarsResults: map[string]struct { + Statuses map[string]string + Error error }{ "zone1-0000000200": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, "zone1-0000000201": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "1234", + }, }, "zone1-0000000100": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "1231", + }, }, }, }, @@ -4037,9 +4180,13 @@ func TestPlannedReparenter_verifyAllTabletsReachable(t *testing.T) { topo.RemoteOperationTimeout = oldTime }() } - err := pr.verifyAllTabletsReachable(context.Background(), tt.tabletMap) + innodbBufferPoolsData, err := pr.verifyAllTabletsReachable(context.Background(), tt.tabletMap) if tt.wantErr == "" { require.NoError(t, err) + require.EqualValues(t, len(tt.wantBufferPoolsData), len(innodbBufferPoolsData)) + for str, val := range tt.wantBufferPoolsData { + require.EqualValues(t, val, innodbBufferPoolsData[str]) + } return } require.ErrorContains(t, err, tt.wantErr) @@ -4070,16 +4217,19 @@ func TestPlannedReparenterStats(t *testing.T) { SetReadWriteResults: map[string]error{ "zone1-0000000100": nil, }, - // This is only needed to verify reachability, so empty results are fine. - PrimaryStatusResults: map[string]struct { - Status *replicationdatapb.PrimaryStatus - Error error + GetGlobalStatusVarsResults: map[string]struct { + Statuses map[string]string + Error error }{ "zone1-0000000101": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, "zone1-0000000100": { - Status: &replicationdatapb.PrimaryStatus{}, + Statuses: map[string]string{ + InnodbBufferPoolsDataVar: "123", + }, }, }, } diff --git a/go/vt/vtctl/reparentutil/reparent_sorter.go b/go/vt/vtctl/reparentutil/reparent_sorter.go index e4461b78064..ea7367bd36b 100644 --- a/go/vt/vtctl/reparentutil/reparent_sorter.go +++ b/go/vt/vtctl/reparentutil/reparent_sorter.go @@ -29,17 +29,19 @@ import ( // reparentSorter sorts tablets by GTID positions and Promotion rules aimed at finding the best // candidate for intermediate promotion in emergency reparent shard, and the new primary in planned reparent shard type reparentSorter struct { - tablets []*topodatapb.Tablet - positions []replication.Position - durability Durabler + tablets []*topodatapb.Tablet + positions []replication.Position + innodbBufferPool []int + durability Durabler } // newReparentSorter creates a new reparentSorter -func newReparentSorter(tablets []*topodatapb.Tablet, positions []replication.Position, durability Durabler) *reparentSorter { +func newReparentSorter(tablets []*topodatapb.Tablet, positions []replication.Position, innodbBufferPool []int, durability Durabler) *reparentSorter { return &reparentSorter{ - tablets: tablets, - positions: positions, - durability: durability, + tablets: tablets, + positions: positions, + durability: durability, + innodbBufferPool: innodbBufferPool, } } @@ -50,6 +52,9 @@ func (rs *reparentSorter) Len() int { return len(rs.tablets) } func (rs *reparentSorter) Swap(i, j int) { rs.tablets[i], rs.tablets[j] = rs.tablets[j], rs.tablets[i] rs.positions[i], rs.positions[j] = rs.positions[j], rs.positions[i] + if len(rs.innodbBufferPool) != 0 { + rs.innodbBufferPool[i], rs.innodbBufferPool[j] = rs.innodbBufferPool[j], rs.innodbBufferPool[i] + } } // Less implements the Interface for sorting @@ -79,18 +84,29 @@ func (rs *reparentSorter) Less(i, j int) bool { // so we check their promotion rules jPromotionRule := PromotionRule(rs.durability, rs.tablets[j]) iPromotionRule := PromotionRule(rs.durability, rs.tablets[i]) + + // If the promotion rules are different then we want to sort by the promotion rules. + if len(rs.innodbBufferPool) != 0 && jPromotionRule == iPromotionRule { + if rs.innodbBufferPool[i] > rs.innodbBufferPool[j] { + return true + } + if rs.innodbBufferPool[j] > rs.innodbBufferPool[i] { + return false + } + } + return !jPromotionRule.BetterThan(iPromotionRule) } // sortTabletsForReparent sorts the tablets, given their positions for emergency reparent shard and planned reparent shard. // Tablets are sorted first by their replication positions, with ties broken by the promotion rules. -func sortTabletsForReparent(tablets []*topodatapb.Tablet, positions []replication.Position, durability Durabler) error { +func sortTabletsForReparent(tablets []*topodatapb.Tablet, positions []replication.Position, innodbBufferPool []int, durability Durabler) error { // throw an error internal error in case of unequal number of tablets and positions // fail-safe code prevents panic in sorting in case the lengths are unequal if len(tablets) != len(positions) { return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "unequal number of tablets and positions") } - sort.Sort(newReparentSorter(tablets, positions, durability)) + sort.Sort(newReparentSorter(tablets, positions, innodbBufferPool, durability)) return nil } diff --git a/go/vt/vtctl/reparentutil/reparent_sorter_test.go b/go/vt/vtctl/reparentutil/reparent_sorter_test.go index c21c95ad22b..ae5d56e884e 100644 --- a/go/vt/vtctl/reparentutil/reparent_sorter_test.go +++ b/go/vt/vtctl/reparentutil/reparent_sorter_test.go @@ -89,17 +89,24 @@ func TestReparentSorter(t *testing.T) { positionIntermediate2.GTIDSet = positionIntermediate2.GTIDSet.AddGTID(mysqlGTID2) testcases := []struct { - name string - tablets []*topodatapb.Tablet - positions []replication.Position - containsErr string - sortedTablets []*topodatapb.Tablet + name string + tablets []*topodatapb.Tablet + innodbBufferPool []int + positions []replication.Position + containsErr string + sortedTablets []*topodatapb.Tablet }{ { name: "all advanced, sort via promotion rules", tablets: []*topodatapb.Tablet{nil, tabletReplica1_100, tabletRdonly1_102}, positions: []replication.Position{positionMostAdvanced, positionMostAdvanced, positionMostAdvanced}, sortedTablets: []*topodatapb.Tablet{tabletReplica1_100, tabletRdonly1_102, nil}, + }, { + name: "all advanced, sort via innodb buffer pool", + tablets: []*topodatapb.Tablet{tabletReplica1_101, tabletReplica2_100, tabletReplica1_100}, + positions: []replication.Position{positionMostAdvanced, positionMostAdvanced, positionMostAdvanced}, + innodbBufferPool: []int{10, 40, 25}, + sortedTablets: []*topodatapb.Tablet{tabletReplica2_100, tabletReplica1_100, tabletReplica1_101}, }, { name: "ordering by position", tablets: []*topodatapb.Tablet{tabletReplica1_101, tabletReplica2_100, tabletReplica1_100, tabletRdonly1_102}, @@ -120,6 +127,12 @@ func TestReparentSorter(t *testing.T) { tablets: []*topodatapb.Tablet{tabletReplica1_101, tabletReplica2_100, tabletReplica1_100, tabletRdonly1_102}, positions: []replication.Position{positionEmpty, positionIntermediate1, positionMostAdvanced, positionIntermediate1}, sortedTablets: []*topodatapb.Tablet{tabletReplica1_100, tabletReplica2_100, tabletRdonly1_102, tabletReplica1_101}, + }, { + name: "mixed - another", + tablets: []*topodatapb.Tablet{tabletReplica1_101, tabletReplica2_100, tabletReplica1_100, tabletRdonly1_102}, + positions: []replication.Position{positionIntermediate1, positionIntermediate1, positionMostAdvanced, positionIntermediate1}, + innodbBufferPool: []int{100, 200, 0, 200}, + sortedTablets: []*topodatapb.Tablet{tabletReplica1_100, tabletReplica2_100, tabletReplica1_101, tabletRdonly1_102}, }, } @@ -127,7 +140,7 @@ func TestReparentSorter(t *testing.T) { require.NoError(t, err) for _, testcase := range testcases { t.Run(testcase.name, func(t *testing.T) { - err := sortTabletsForReparent(testcase.tablets, testcase.positions, durability) + err := sortTabletsForReparent(testcase.tablets, testcase.positions, testcase.innodbBufferPool, durability) if testcase.containsErr != "" { require.EqualError(t, err, testcase.containsErr) } else { diff --git a/go/vt/vtctl/reparentutil/util.go b/go/vt/vtctl/reparentutil/util.go index 5962ff9fa24..ea7a9f7262c 100644 --- a/go/vt/vtctl/reparentutil/util.go +++ b/go/vt/vtctl/reparentutil/util.go @@ -49,6 +49,10 @@ var ( successResult = "success" ) +const ( + lostTopologyLockMsg = "lost topology lock, aborting" +) + // ElectNewPrimary finds a tablet that should become a primary after reparent. // The criteria for the new primary-elect are (preferably) to be in the same // cell as the current primary, and to be different from avoidPrimaryAlias. The @@ -64,6 +68,7 @@ func ElectNewPrimary( tmc tmclient.TabletManagerClient, shardInfo *topo.ShardInfo, tabletMap map[string]*topo.TabletInfo, + innodbBufferPoolData map[string]int, newPrimaryAlias *topodatapb.TabletAlias, avoidPrimaryAlias *topodatapb.TabletAlias, waitReplicasTimeout time.Duration, @@ -84,6 +89,7 @@ func ElectNewPrimary( // tablets that are possible candidates to be the new primary and their positions validTablets []*topodatapb.Tablet tabletPositions []replication.Position + innodbBufferPool []int errorGroup, groupCtx = errgroup.WithContext(ctx) ) @@ -130,6 +136,7 @@ func ElectNewPrimary( if err == nil && (tolerableReplLag == 0 || tolerableReplLag >= replLag) { validTablets = append(validTablets, tb) tabletPositions = append(tabletPositions, pos) + innodbBufferPool = append(innodbBufferPool, innodbBufferPoolData[topoproto.TabletAliasString(tb.Alias)]) } else { reasonsToInvalidate.WriteString(fmt.Sprintf("\n%v has %v replication lag which is more than the tolerable amount", topoproto.TabletAliasString(tablet.Alias), replLag)) } @@ -148,7 +155,7 @@ func ElectNewPrimary( } // sort the tablets for finding the best primary - err = sortTabletsForReparent(validTablets, tabletPositions, durability) + err = sortTabletsForReparent(validTablets, tabletPositions, innodbBufferPool, durability) if err != nil { return nil, err } diff --git a/go/vt/vtctl/reparentutil/util_test.go b/go/vt/vtctl/reparentutil/util_test.go index dd13e48f7b7..d42ae76f337 100644 --- a/go/vt/vtctl/reparentutil/util_test.go +++ b/go/vt/vtctl/reparentutil/util_test.go @@ -67,15 +67,16 @@ func TestElectNewPrimary(t *testing.T) { ctx := context.Background() logger := logutil.NewMemoryLogger() tests := []struct { - name string - tmc *chooseNewPrimaryTestTMClient - shardInfo *topo.ShardInfo - tabletMap map[string]*topo.TabletInfo - newPrimaryAlias *topodatapb.TabletAlias - avoidPrimaryAlias *topodatapb.TabletAlias - tolerableReplLag time.Duration - expected *topodatapb.TabletAlias - errContains []string + name string + tmc *chooseNewPrimaryTestTMClient + shardInfo *topo.ShardInfo + tabletMap map[string]*topo.TabletInfo + innodbBufferPoolData map[string]int + newPrimaryAlias *topodatapb.TabletAlias + avoidPrimaryAlias *topodatapb.TabletAlias + tolerableReplLag time.Duration + expected *topodatapb.TabletAlias + errContains []string }{ { name: "found a replica", @@ -472,6 +473,68 @@ func TestElectNewPrimary(t *testing.T) { }, errContains: nil, }, + { + name: "found a replica - more advanced innodb buffer pool", + tmc: &chooseNewPrimaryTestTMClient{ + replicationStatuses: map[string]*replicationdatapb.Status{ + "zone1-0000000101": { + Position: "MySQL56/3E11FA47-71CA-11E1-9E33-C80AA9429562:1-2", + }, + "zone1-0000000102": { + Position: "MySQL56/3E11FA47-71CA-11E1-9E33-C80AA9429562:1", + RelayLogPosition: "MySQL56/3E11FA47-71CA-11E1-9E33-C80AA9429562:1-2", + }, + }, + }, + innodbBufferPoolData: map[string]int{ + "zone1-0000000101": 200, + "zone1-0000000102": 100, + }, + shardInfo: topo.NewShardInfo("testkeyspace", "-", &topodatapb.Shard{ + PrimaryAlias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 100, + }, + }, nil), + tabletMap: map[string]*topo.TabletInfo{ + "primary": { + Tablet: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 100, + }, + Type: topodatapb.TabletType_PRIMARY, + }, + }, + "replica1": { + Tablet: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 101, + }, + Type: topodatapb.TabletType_REPLICA, + }, + }, + "replica2": { + Tablet: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 102, + }, + Type: topodatapb.TabletType_REPLICA, + }, + }, + }, + avoidPrimaryAlias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 0, + }, + expected: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 101, + }, + errContains: nil, + }, { name: "no active primary in shard", tmc: &chooseNewPrimaryTestTMClient{ @@ -731,7 +794,7 @@ zone1-0000000100 is not a replica`, t.Run(tt.name, func(t *testing.T) { t.Parallel() - actual, err := ElectNewPrimary(ctx, tt.tmc, tt.shardInfo, tt.tabletMap, tt.newPrimaryAlias, tt.avoidPrimaryAlias, time.Millisecond*50, tt.tolerableReplLag, durability, logger) + actual, err := ElectNewPrimary(ctx, tt.tmc, tt.shardInfo, tt.tabletMap, tt.innodbBufferPoolData, tt.newPrimaryAlias, tt.avoidPrimaryAlias, time.Millisecond*50, tt.tolerableReplLag, durability, logger) if len(tt.errContains) > 0 { for _, errC := range tt.errContains { assert.ErrorContains(t, err, errC) diff --git a/go/vt/vtctl/vtctl.go b/go/vt/vtctl/vtctl.go index 324cdda0a76..03b9e3d7077 100644 --- a/go/vt/vtctl/vtctl.go +++ b/go/vt/vtctl/vtctl.go @@ -2507,7 +2507,7 @@ func commandCreateLookupVindex(ctx context.Context, wr *wrangler.Wrangler, subFl } keyspace := subFlags.Arg(0) specs := &vschemapb.Keyspace{} - if err := json2.Unmarshal([]byte(subFlags.Arg(1)), specs); err != nil { + if err := json2.UnmarshalPB([]byte(subFlags.Arg(1)), specs); err != nil { return err } return wr.CreateLookupVindex(ctx, keyspace, specs, *cells, *tabletTypes, *continueAfterCopyWithOwner) @@ -2533,7 +2533,7 @@ func commandMaterialize(ctx context.Context, wr *wrangler.Wrangler, subFlags *pf return fmt.Errorf("a single argument is required: ") } ms := &vtctldatapb.MaterializeSettings{} - if err := json2.Unmarshal([]byte(subFlags.Arg(0)), ms); err != nil { + if err := json2.UnmarshalPB([]byte(subFlags.Arg(0)), ms); err != nil { return err } ms.Cell = *cells @@ -3402,7 +3402,7 @@ func commandApplyVSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *p } vs = &vschemapb.Keyspace{} - err := json2.Unmarshal(schema, vs) + err := json2.UnmarshalPB(schema, vs) if err != nil { return err } @@ -3490,7 +3490,7 @@ func commandApplyRoutingRules(ctx context.Context, wr *wrangler.Wrangler, subFla } rr := &vschemapb.RoutingRules{} - if err := json2.Unmarshal(rulesBytes, rr); err != nil { + if err := json2.UnmarshalPB(rulesBytes, rr); err != nil { return err } @@ -3656,7 +3656,7 @@ func commandUpdateThrottlerConfig(ctx context.Context, wr *wrangler.Wrangler, su req.ThrottledApp = &topodatapb.ThrottledAppRule{ Name: *unthrottledApp, Ratio: 0, - ExpiresAt: protoutil.TimeToProto(time.Now()), + ExpiresAt: &vttime.Time{}, // zero } } _, err = wr.VtctldServer().UpdateThrottlerConfig(ctx, req) diff --git a/go/vt/vtctl/workflow/framework_test.go b/go/vt/vtctl/workflow/framework_test.go index 73b34015338..e2ccde0a0e7 100644 --- a/go/vt/vtctl/workflow/framework_test.go +++ b/go/vt/vtctl/workflow/framework_test.go @@ -21,6 +21,7 @@ import ( "fmt" "os" "regexp" + "slices" "strings" "sync" "sync/atomic" @@ -33,6 +34,7 @@ import ( "vitess.io/vitess/go/protoutil" "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/vt/key" "vitess.io/vitess/go/vt/mysqlctl/tmutils" "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/topo/memorytopo" @@ -94,24 +96,68 @@ func newTestEnv(t *testing.T, ctx context.Context, cell string, sourceKeyspace, env.tmc = newTestTMClient(env) env.ws = NewServer(venv, env.ts, env.tmc) + serving := true tabletID := startingSourceTabletUID for _, shardName := range sourceKeyspace.ShardNames { - _ = env.addTablet(t, ctx, tabletID, sourceKeyspace.KeyspaceName, shardName, topodatapb.TabletType_PRIMARY) + _ = env.addTablet(t, ctx, tabletID, sourceKeyspace.KeyspaceName, shardName, topodatapb.TabletType_PRIMARY, serving) tabletID += tabletUIDStep } - if sourceKeyspace.KeyspaceName != targetKeyspace.KeyspaceName { - tabletID = startingTargetTabletUID - for _, shardName := range targetKeyspace.ShardNames { - _ = env.addTablet(t, ctx, tabletID, targetKeyspace.KeyspaceName, shardName, topodatapb.TabletType_PRIMARY) - tabletID += tabletUIDStep - } + + isReshard := func() bool { + return sourceKeyspace.KeyspaceName == targetKeyspace.KeyspaceName && + !slices.Equal(sourceKeyspace.ShardNames, targetKeyspace.ShardNames) } + + if isReshard() { + serving = false + } + tabletID = startingTargetTabletUID + for _, shardName := range targetKeyspace.ShardNames { + _ = env.addTablet(t, ctx, tabletID, targetKeyspace.KeyspaceName, shardName, topodatapb.TabletType_PRIMARY, serving) + tabletID += tabletUIDStep + } + + if isReshard() { + initSrvKeyspace(t, env.ts, targetKeyspace.KeyspaceName, sourceKeyspace.ShardNames, targetKeyspace.ShardNames, []string{cell}) + } + err := env.ts.RebuildSrvVSchema(ctx, nil) require.NoError(t, err) return env } +func initSrvKeyspace(t *testing.T, topo *topo.Server, keyspace string, sources, targets, cells []string) { + ctx := context.Background() + srvKeyspace := &topodatapb.SrvKeyspace{ + Partitions: []*topodatapb.SrvKeyspace_KeyspacePartition{}, + } + getPartition := func(t *testing.T, shards []string) *topodatapb.SrvKeyspace_KeyspacePartition { + partition := &topodatapb.SrvKeyspace_KeyspacePartition{ + ServedType: topodatapb.TabletType_PRIMARY, + ShardReferences: []*topodatapb.ShardReference{}, + } + for _, shard := range shards { + keyRange, err := key.ParseShardingSpec(shard) + require.NoError(t, err) + require.Equal(t, 1, len(keyRange)) + partition.ShardReferences = append(partition.ShardReferences, &topodatapb.ShardReference{ + Name: shard, + KeyRange: keyRange[0], + }) + } + return partition + } + srvKeyspace.Partitions = append(srvKeyspace.Partitions, getPartition(t, sources)) + srvKeyspace.Partitions = append(srvKeyspace.Partitions, getPartition(t, targets)) + for _, cell := range cells { + err := topo.UpdateSrvKeyspace(ctx, cell, keyspace, srvKeyspace) + require.NoError(t, err) + } + err := topo.ValidateSrvKeyspace(ctx, keyspace, strings.Join(cells, ",")) + require.NoError(t, err) +} + func (env *testEnv) close() { for _, k := range maps.Values(env.tablets) { for _, t := range maps.Values(k) { @@ -120,7 +166,7 @@ func (env *testEnv) close() { } } -func (env *testEnv) addTablet(t *testing.T, ctx context.Context, id int, keyspace, shard string, tabletType topodatapb.TabletType) *topodatapb.Tablet { +func (env *testEnv) addTablet(t *testing.T, ctx context.Context, id int, keyspace, shard string, tabletType topodatapb.TabletType, serving bool) *topodatapb.Tablet { tablet := &topodatapb.Tablet{ Alias: &topodatapb.TabletAlias{ Cell: env.cell, @@ -143,7 +189,7 @@ func (env *testEnv) addTablet(t *testing.T, ctx context.Context, id int, keyspac if tabletType == topodatapb.TabletType_PRIMARY { _, err = env.ws.ts.UpdateShardFields(ctx, keyspace, shard, func(si *topo.ShardInfo) error { si.PrimaryAlias = tablet.Alias - si.IsPrimaryServing = true + si.IsPrimaryServing = serving return nil }) require.NoError(t, err) diff --git a/go/vt/vtctl/workflow/materializer_env_test.go b/go/vt/vtctl/workflow/materializer_env_test.go index fe49b24a10d..569651f85ca 100644 --- a/go/vt/vtctl/workflow/materializer_env_test.go +++ b/go/vt/vtctl/workflow/materializer_env_test.go @@ -25,13 +25,17 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" "vitess.io/vitess/go/protoutil" "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/vt/key" + "vitess.io/vitess/go/vt/logutil" "vitess.io/vitess/go/vt/mysqlctl/tmutils" "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/topo/memorytopo" + "vitess.io/vitess/go/vt/topotools" "vitess.io/vitess/go/vt/vtenv" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vttablet/tmclient" @@ -40,6 +44,7 @@ import ( querypb "vitess.io/vitess/go/vt/proto/query" tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" topodatapb "vitess.io/vitess/go/vt/proto/topodata" + vschemapb "vitess.io/vitess/go/vt/proto/vschema" vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" ) @@ -53,35 +58,60 @@ type testMaterializerEnv struct { topoServ *topo.Server cell string tmc *testMaterializerTMClient + venv *vtenv.Environment } //---------------------------------------------- // testMaterializerEnv -func newTestMaterializerEnv(t *testing.T, ctx context.Context, ms *vtctldatapb.MaterializeSettings, sources, targets []string) *testMaterializerEnv { +func newTestMaterializerEnv(t *testing.T, ctx context.Context, ms *vtctldatapb.MaterializeSettings, sourceShards, targetShards []string) *testMaterializerEnv { t.Helper() + + tmc := newTestMaterializerTMClient(ms.SourceKeyspace, sourceShards, ms.TableSettings) + topoServ := memorytopo.NewServer(ctx, "cell") + venv := vtenv.NewTestEnv() env := &testMaterializerEnv{ ms: ms, - sources: sources, - targets: targets, + sources: sourceShards, + targets: targetShards, tablets: make(map[int]*topodatapb.Tablet), - topoServ: memorytopo.NewServer(ctx, defaultCellName), - cell: defaultCellName, - tmc: newTestMaterializerTMClient(), + topoServ: topoServ, + cell: "cell", + tmc: tmc, + ws: NewServer(venv, topoServ, tmc), + venv: venv, } - venv := vtenv.NewTestEnv() - env.ws = NewServer(venv, env.topoServ, env.tmc) + + require.NoError(t, topoServ.CreateKeyspace(ctx, ms.SourceKeyspace, &topodatapb.Keyspace{})) + require.NoError(t, topoServ.SaveVSchema(ctx, ms.SourceKeyspace, &vschemapb.Keyspace{})) + if ms.SourceKeyspace != ms.TargetKeyspace { + require.NoError(t, topoServ.CreateKeyspace(ctx, ms.TargetKeyspace, &topodatapb.Keyspace{})) + require.NoError(t, topoServ.SaveVSchema(ctx, ms.TargetKeyspace, &vschemapb.Keyspace{})) + } + logger := logutil.NewConsoleLogger() + require.NoError(t, topoServ.RebuildSrvVSchema(ctx, []string{"cell"})) + tabletID := 100 - for _, shard := range sources { - _ = env.addTablet(tabletID, env.ms.SourceKeyspace, shard, topodatapb.TabletType_PRIMARY) + sourceShardsMap := make(map[string]any) + for _, shard := range sourceShards { + sourceShardsMap[shard] = nil + require.NoError(t, topoServ.CreateShard(ctx, ms.SourceKeyspace, shard)) + _ = env.addTablet(t, tabletID, env.ms.SourceKeyspace, shard, topodatapb.TabletType_PRIMARY) tabletID += 10 } - if ms.SourceKeyspace != ms.TargetKeyspace { - tabletID = 200 - for _, shard := range targets { - _ = env.addTablet(tabletID, env.ms.TargetKeyspace, shard, topodatapb.TabletType_PRIMARY) - tabletID += 10 + + require.NoError(t, topotools.RebuildKeyspace(ctx, logger, topoServ, ms.SourceKeyspace, []string{"cell"}, false)) + + tabletID = 200 + for _, shard := range targetShards { + if ms.SourceKeyspace == ms.TargetKeyspace { + if _, ok := sourceShardsMap[shard]; ok { + continue + } } + require.NoError(t, topoServ.CreateShard(ctx, ms.TargetKeyspace, shard)) + _ = env.addTablet(t, tabletID, env.ms.TargetKeyspace, shard, topodatapb.TabletType_PRIMARY) + tabletID += 10 } for _, ts := range ms.TableSettings { @@ -103,6 +133,11 @@ func newTestMaterializerEnv(t *testing.T, ctx context.Context, ms *vtctldatapb.M }}, } } + + if ms.SourceKeyspace != ms.TargetKeyspace { + require.NoError(t, topotools.RebuildKeyspace(ctx, logger, topoServ, ms.TargetKeyspace, []string{"cell"}, false)) + } + return env } @@ -112,7 +147,10 @@ func (env *testMaterializerEnv) close() { } } -func (env *testMaterializerEnv) addTablet(id int, keyspace, shard string, tabletType topodatapb.TabletType) *topodatapb.Tablet { +func (env *testMaterializerEnv) addTablet(t *testing.T, id int, keyspace, shard string, tabletType topodatapb.TabletType) *topodatapb.Tablet { + keyRanges, err := key.ParseShardingSpec(shard) + require.NoError(t, err) + require.Len(t, keyRanges, 1) tablet := &topodatapb.Tablet{ Alias: &topodatapb.TabletAlias{ Cell: env.cell, @@ -120,7 +158,7 @@ func (env *testMaterializerEnv) addTablet(id int, keyspace, shard string, tablet }, Keyspace: keyspace, Shard: shard, - KeyRange: &topodatapb.KeyRange{}, + KeyRange: keyRanges[0], Type: tabletType, PortMap: map[string]int32{ "test": int32(id), @@ -148,12 +186,16 @@ func (env *testMaterializerEnv) deleteTablet(tablet *topodatapb.Tablet) { delete(env.tablets, int(tablet.Alias.Uid)) } -//---------------------------------------------- +// ---------------------------------------------- // testMaterializerTMClient +type readVReplicationWorkflowFunc = func(ctx context.Context, tablet *topodatapb.Tablet, request *tabletmanagerdatapb.ReadVReplicationWorkflowRequest) (*tabletmanagerdatapb.ReadVReplicationWorkflowResponse, error) type testMaterializerTMClient struct { tmclient.TabletManagerClient - schema map[string]*tabletmanagerdatapb.SchemaDefinition + keyspace string + schema map[string]*tabletmanagerdatapb.SchemaDefinition + sourceShards []string + tableSettings []*vtctldatapb.TableMaterializeSettings mu sync.Mutex vrQueries map[int][]*queryResult @@ -161,11 +203,17 @@ type testMaterializerTMClient struct { // Used to confirm the number of times WorkflowDelete was called. workflowDeleteCalls int + + // Used to override the response to ReadVReplicationWorkflow. + readVReplicationWorkflow readVReplicationWorkflowFunc } -func newTestMaterializerTMClient() *testMaterializerTMClient { +func newTestMaterializerTMClient(keyspace string, sourceShards []string, tableSettings []*vtctldatapb.TableMaterializeSettings) *testMaterializerTMClient { return &testMaterializerTMClient{ + keyspace: keyspace, schema: make(map[string]*tabletmanagerdatapb.SchemaDefinition), + sourceShards: sourceShards, + tableSettings: tableSettings, vrQueries: make(map[int][]*queryResult), createVReplicationWorkflowRequests: make(map[uint32]*tabletmanagerdatapb.CreateVReplicationWorkflowRequest), } @@ -182,29 +230,44 @@ func (tmc *testMaterializerTMClient) CreateVReplicationWorkflow(ctx context.Cont } func (tmc *testMaterializerTMClient) ReadVReplicationWorkflow(ctx context.Context, tablet *topodatapb.Tablet, request *tabletmanagerdatapb.ReadVReplicationWorkflowRequest) (*tabletmanagerdatapb.ReadVReplicationWorkflowResponse, error) { + if tmc.readVReplicationWorkflow != nil { + return tmc.readVReplicationWorkflow(ctx, tablet, request) + } + workflowType := binlogdatapb.VReplicationWorkflowType_MoveTables if strings.Contains(request.Workflow, "lookup") { workflowType = binlogdatapb.VReplicationWorkflowType_CreateLookupIndex } + + rules := make([]*binlogdatapb.Rule, len(tmc.tableSettings)) + if len(rules) == 0 { + rules = append(rules, &binlogdatapb.Rule{Match: "table1"}) + } else { + for i, tableSetting := range tmc.tableSettings { + rules[i] = &binlogdatapb.Rule{ + Match: tableSetting.TargetTable, + Filter: tableSetting.SourceExpression, + } + } + } + + streams := make([]*tabletmanagerdatapb.ReadVReplicationWorkflowResponse_Stream, len(tmc.sourceShards)) + for i, shard := range tmc.sourceShards { + streams[i] = &tabletmanagerdatapb.ReadVReplicationWorkflowResponse_Stream{ + Id: int32(i + 1), + Bls: &binlogdatapb.BinlogSource{ + Keyspace: tmc.keyspace, + Shard: shard, + Filter: &binlogdatapb.Filter{ + Rules: rules, + }, + }, + } + } return &tabletmanagerdatapb.ReadVReplicationWorkflowResponse{ Workflow: request.Workflow, WorkflowType: workflowType, - Streams: []*tabletmanagerdatapb.ReadVReplicationWorkflowResponse_Stream{ - { - Id: 1, - Bls: &binlogdatapb.BinlogSource{ - Keyspace: "sourceks", - Shard: "0", - Filter: &binlogdatapb.Filter{ - Rules: []*binlogdatapb.Rule{ - { - Match: ".*", - }, - }, - }, - }, - }, - }, + Streams: streams, }, nil } @@ -347,31 +410,33 @@ func (tmc *testMaterializerTMClient) ReadVReplicationWorkflows(ctx context.Conte workflowType = binlogdatapb.VReplicationWorkflowType_CreateLookupIndex } } + streams := make([]*tabletmanagerdatapb.ReadVReplicationWorkflowResponse_Stream, len(tmc.sourceShards)) + for i, shard := range tmc.sourceShards { + streams[i] = &tabletmanagerdatapb.ReadVReplicationWorkflowResponse_Stream{ + Id: 1, + State: binlogdatapb.VReplicationWorkflowState_Running, + Bls: &binlogdatapb.BinlogSource{ + Keyspace: tmc.keyspace, + Shard: shard, + Filter: &binlogdatapb.Filter{ + Rules: []*binlogdatapb.Rule{ + { + Match: ".*", + }, + }, + }, + }, + Pos: "MySQL56/" + position, + TimeUpdated: protoutil.TimeToProto(time.Now()), + TimeHeartbeat: protoutil.TimeToProto(time.Now()), + } + } return &tabletmanagerdatapb.ReadVReplicationWorkflowsResponse{ Workflows: []*tabletmanagerdatapb.ReadVReplicationWorkflowResponse{ { Workflow: req.IncludeWorkflows[0], WorkflowType: workflowType, - Streams: []*tabletmanagerdatapb.ReadVReplicationWorkflowResponse_Stream{ - { - Id: 1, - State: binlogdatapb.VReplicationWorkflowState_Running, - Bls: &binlogdatapb.BinlogSource{ - Keyspace: "sourceks", - Shard: "0", - Filter: &binlogdatapb.Filter{ - Rules: []*binlogdatapb.Rule{ - { - Match: ".*", - }, - }, - }, - }, - Pos: "MySQL56/" + position, - TimeUpdated: protoutil.TimeToProto(time.Now()), - TimeHeartbeat: protoutil.TimeToProto(time.Now()), - }, - }, + Streams: streams, }, }, }, nil diff --git a/go/vt/vtctl/workflow/materializer_test.go b/go/vt/vtctl/workflow/materializer_test.go index 9a43ea5ed7e..51a7d22d5eb 100644 --- a/go/vt/vtctl/workflow/materializer_test.go +++ b/go/vt/vtctl/workflow/materializer_test.go @@ -822,18 +822,21 @@ func TestCreateLookupVindexCreateDDL(t *testing.T) { }, }, } - if err := env.topoServ.SaveVSchema(ctx, ms.SourceKeyspace, vs); err != nil { - t.Fatal(err) + setStartingVschema := func() { + err := env.topoServ.SaveVSchema(ctx, ms.SourceKeyspace, vs) + require.NoError(t, err) } + setStartingVschema() testcases := []struct { description string specs *vschemapb.Keyspace sourceSchema string + preFunc func() out string err string }{{ - description: "unique lookup", + description: "unique lookup re-use vschema", specs: &vschemapb.Keyspace{ Vindexes: map[string]*vschemapb.Vindex{ "v": { @@ -855,6 +858,32 @@ func TestCreateLookupVindexCreateDDL(t *testing.T) { }, }, }, + preFunc: func() { + // The vschema entries will already exist and we will re-use them. + err := env.ws.ts.SaveVSchema(ctx, ms.SourceKeyspace, &vschemapb.Keyspace{ + Vindexes: map[string]*vschemapb.Vindex{ + "v": { + Type: "lookup_unique", + Params: map[string]string{ + "table": fmt.Sprintf("%s.lkp", ms.TargetKeyspace), + "from": "c1", + "to": "c2", + "write_only": "true", // It has not been externalized yet + }, + Owner: "t1", + }, + }, + Tables: map[string]*vschemapb.Table{ + "t1": { + ColumnVindexes: []*vschemapb.ColumnVindex{{ + Name: "v", + Column: "col2", + }}, + }, + }, + }) + require.NoError(t, err) + }, sourceSchema: "CREATE TABLE `t1` (\n" + " `col1` int(11) NOT NULL AUTO_INCREMENT,\n" + " `col2` int(11) DEFAULT NULL,\n" + @@ -866,6 +895,132 @@ func TestCreateLookupVindexCreateDDL(t *testing.T) { " `c2` varbinary(128),\n" + " PRIMARY KEY (`c1`)\n" + ")", + }, { + description: "unique lookup with conflicting vindex", + specs: &vschemapb.Keyspace{ + Vindexes: map[string]*vschemapb.Vindex{ + "v": { + Type: "lookup_unique", + Params: map[string]string{ + "table": fmt.Sprintf("%s.lkp", ms.TargetKeyspace), + "from": "c1", + "to": "c2", + }, + Owner: "t1", + }, + }, + Tables: map[string]*vschemapb.Table{ + "t1": { + ColumnVindexes: []*vschemapb.ColumnVindex{{ + Name: "v", + Column: "col2", + }}, + }, + }, + }, + preFunc: func() { + // The existing vindex vschema entry differs from what we want to + // create so we cannot re-use it. + err := env.ws.ts.SaveVSchema(ctx, ms.SourceKeyspace, &vschemapb.Keyspace{ + Vindexes: map[string]*vschemapb.Vindex{ + "v": { + Type: "lookup_unique", + Params: map[string]string{ + "table": fmt.Sprintf("%s.lkp", ms.TargetKeyspace), + "from": "c1", + "to": "c2", + "write_only": "false", // This vindex has been externalized + }, + Owner: "t1", + }, + }, + }) + require.NoError(t, err) + }, + err: "a conflicting vindex named v already exists in the sourceks keyspace", + sourceSchema: "CREATE TABLE `t1` (\n" + + " `col1` int(11) NOT NULL AUTO_INCREMENT,\n" + + " `col2` int(11) DEFAULT NULL,\n" + + " `col3` int(11) DEFAULT NULL,\n" + + " PRIMARY KEY (`id`)\n" + + ") ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1", + }, { + description: "unique lookup with conflicting column vindexes", + specs: &vschemapb.Keyspace{ + Vindexes: map[string]*vschemapb.Vindex{ + "v": { + Type: "lookup_unique", + Params: map[string]string{ + "table": fmt.Sprintf("%s.lkp", ms.TargetKeyspace), + "from": "c1", + "to": "c2", + }, + Owner: "t1", + }, + }, + Tables: map[string]*vschemapb.Table{ + "t1": { + ColumnVindexes: []*vschemapb.ColumnVindex{{ + Name: "v", + Column: "col2", + }}, + }, + }, + }, + preFunc: func() { + // The existing ColumnVindexes vschema entry differs from what we + // want to create so we cannot re-use it. + err := env.ws.ts.SaveVSchema(ctx, ms.SourceKeyspace, &vschemapb.Keyspace{ + Tables: map[string]*vschemapb.Table{ + "t1": { + ColumnVindexes: []*vschemapb.ColumnVindex{{ + Name: "v", + Columns: []string{"col1", "col2"}, + }}, + }, + }, + }) + require.NoError(t, err) + }, + err: "a conflicting ColumnVindex on column(s) col1,col2 in table t1 already exists in the sourceks keyspace", + sourceSchema: "CREATE TABLE `t1` (\n" + + " `col1` int(11) NOT NULL AUTO_INCREMENT,\n" + + " `col2` int(11) DEFAULT NULL,\n" + + " `col3` int(11) DEFAULT NULL,\n" + + " PRIMARY KEY (`id`)\n" + + ") ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1", + }, { + description: "unique lookup using last column w/o primary key", + specs: &vschemapb.Keyspace{ + Vindexes: map[string]*vschemapb.Vindex{ + "v": { + Type: "lookup_unique", + Params: map[string]string{ + "table": fmt.Sprintf("%s.lkp", ms.TargetKeyspace), + "from": "c1", + "to": "c2", + }, + Owner: "t1", + }, + }, + Tables: map[string]*vschemapb.Table{ + "t1": { + ColumnVindexes: []*vschemapb.ColumnVindex{{ + Name: "v", + Column: "col2", + }}, + }, + }, + }, + sourceSchema: "CREATE TABLE `t1` (\n" + + " `col1` int(11) NOT NULL AUTO_INCREMENT,\n" + + " `col2` int(11) DEFAULT NULL\n" + // Because it's the last entity in the definition it has no trailing comma + ") ENGINE=InnoDB", + out: "CREATE TABLE `lkp` (\n" + + " `c1` int(11),\n" + + " `c2` varbinary(128),\n" + + " PRIMARY KEY (`c1`)\n" + + ")", }, { description: "unique lookup, also pk", specs: &vschemapb.Keyspace{ @@ -992,27 +1147,36 @@ func TestCreateLookupVindexCreateDDL(t *testing.T) { err: "unexpected number of tables (0) returned from sourceks schema", }} for _, tcase := range testcases { - if tcase.sourceSchema != "" { - env.tmc.schema[ms.SourceKeyspace+".t1"] = &tabletmanagerdatapb.SchemaDefinition{ - TableDefinitions: []*tabletmanagerdatapb.TableDefinition{{ - Schema: tcase.sourceSchema, - }}, + t.Run(tcase.description, func(t *testing.T) { + if tcase.sourceSchema != "" { + env.tmc.schema[ms.SourceKeyspace+".t1"] = &tabletmanagerdatapb.SchemaDefinition{ + TableDefinitions: []*tabletmanagerdatapb.TableDefinition{{ + Schema: tcase.sourceSchema, + }}, + } + } else { + delete(env.tmc.schema, ms.SourceKeyspace+".t1") } - } else { - delete(env.tmc.schema, ms.SourceKeyspace+".t1") - } - outms, _, _, err := env.ws.prepareCreateLookup(ctx, "workflow", ms.SourceKeyspace, tcase.specs, false) - if tcase.err != "" { - if err == nil || !strings.Contains(err.Error(), tcase.err) { - t.Errorf("prepareCreateLookup(%s) err: %v, must contain %v", tcase.description, err, tcase.err) + if tcase.preFunc != nil { + tcase.preFunc() + defer func() { + // Reset the vschema as it may have been changed in the pre + // function. + setStartingVschema() + }() } - continue - } - require.NoError(t, err) - want := strings.Split(tcase.out, "\n") - got := strings.Split(outms.TableSettings[0].CreateDdl, "\n") - require.Equal(t, want, got, tcase.description) + outms, _, _, err := env.ws.prepareCreateLookup(ctx, "workflow", ms.SourceKeyspace, tcase.specs, false) + if tcase.err != "" { + require.Error(t, err) + require.Contains(t, err.Error(), tcase.err, "prepareCreateLookup(%s) err: %v, does not contain %v", tcase.description, err, tcase.err) + return + } + require.NoError(t, err) + want := strings.Split(tcase.out, "\n") + got := strings.Split(outms.TableSettings[0].CreateDdl, "\n") + require.Equal(t, want, got, tcase.description) + }) } } @@ -1367,15 +1531,15 @@ func TestCreateLookupVindexTargetVSchema(t *testing.T) { out: &vschemapb.Keyspace{ Sharded: true, Vindexes: map[string]*vschemapb.Vindex{ - "unicode_loose_md5": { - Type: "unicode_loose_md5", + "unicode_loose_xxhash": { + Type: "unicode_loose_xxhash", }, }, Tables: map[string]*vschemapb.Table{ "lkp": { ColumnVindexes: []*vschemapb.ColumnVindex{{ Column: "c1", - Name: "unicode_loose_md5", + Name: "unicode_loose_xxhash", }}, }, }, @@ -1417,7 +1581,7 @@ func TestCreateLookupVindexTargetVSchema(t *testing.T) { Vindexes: map[string]*vschemapb.Vindex{ // Create a misleading vindex name. "xxhash": { - Type: "unicode_loose_md5", + Type: "unicode_loose_xxhash", }, }, }, @@ -1639,7 +1803,7 @@ func TestCreateCustomizedVindex(t *testing.T) { }, "lookup": { ColumnVindexes: []*vschemapb.ColumnVindex{{ - Name: "unicode_loose_md5", + Name: "unicode_loose_xxhash", Column: "c1", }}, }, @@ -1659,8 +1823,8 @@ func TestCreateCustomizedVindex(t *testing.T) { "xxhash": { Type: "xxhash", }, - "unicode_loose_md5": { // Non default vindex type for the column. - Type: "unicode_loose_md5", + "unicode_loose_xxhash": { // Non default vindex type for the column. + Type: "unicode_loose_xxhash", }, }, Tables: map[string]*vschemapb.Table{ @@ -1678,8 +1842,8 @@ func TestCreateCustomizedVindex(t *testing.T) { "xxhash": { Type: "xxhash", }, - "unicode_loose_md5": { - Type: "unicode_loose_md5", + "unicode_loose_xxhash": { + Type: "unicode_loose_xxhash", }, "v": { Type: "lookup_unique", @@ -1705,7 +1869,7 @@ func TestCreateCustomizedVindex(t *testing.T) { "lookup": { ColumnVindexes: []*vschemapb.ColumnVindex{{ Column: "c1", - Name: "unicode_loose_md5", + Name: "unicode_loose_xxhash", }}, }, }, diff --git a/go/vt/vtctl/workflow/resharder.go b/go/vt/vtctl/workflow/resharder.go index 95fcea3a2a9..4f4ed34963a 100644 --- a/go/vt/vtctl/workflow/resharder.go +++ b/go/vt/vtctl/workflow/resharder.go @@ -99,6 +99,9 @@ func (s *Server) buildResharder(ctx context.Context, keyspace, workflow string, if err != nil { return nil, vterrors.Wrapf(err, "GetShard(%s) failed", shard) } + if si.PrimaryAlias == nil { + return nil, fmt.Errorf("target shard %v has no primary tablet", shard) + } if si.IsPrimaryServing { return nil, fmt.Errorf("target shard %v is in serving state", shard) } diff --git a/go/vt/vtctl/workflow/resharder_test.go b/go/vt/vtctl/workflow/resharder_test.go new file mode 100644 index 00000000000..1bb2f065e0f --- /dev/null +++ b/go/vt/vtctl/workflow/resharder_test.go @@ -0,0 +1,192 @@ +/* +Copyright 2024 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 workflow + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/vt/topo" + "vitess.io/vitess/go/vt/topo/topoproto" + + tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" + vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" +) + +const eol = "$" + +func TestReshardCreate(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + + workflowName := "wf1" + tableName := "t1" + sourceKeyspaceName := "targetks" + targetKeyspaceName := "targetks" + tabletTypes := []topodatapb.TabletType{ + topodatapb.TabletType_PRIMARY, + topodatapb.TabletType_REPLICA, + topodatapb.TabletType_RDONLY, + } + tabletTypesStr := topoproto.MakeStringTypeCSV(tabletTypes) + 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), + }, + }, + }, + } + + testcases := []struct { + name string + sourceKeyspace, targetKeyspace *testKeyspace + preFunc func(env *testEnv) + want *vtctldatapb.WorkflowStatusResponse + wantErr string + }{ + { + name: "basic", + sourceKeyspace: &testKeyspace{ + KeyspaceName: sourceKeyspaceName, + ShardNames: []string{"0"}, + }, + targetKeyspace: &testKeyspace{ + KeyspaceName: targetKeyspaceName, + ShardNames: []string{"-80", "80-"}, + }, + want: &vtctldatapb.WorkflowStatusResponse{ + ShardStreams: map[string]*vtctldatapb.WorkflowStatusResponse_ShardStreams{ + "targetks/-80": { + Streams: []*vtctldatapb.WorkflowStatusResponse_ShardStreamState{ + { + Id: 1, + Tablet: &topodatapb.TabletAlias{Cell: defaultCellName, Uid: startingTargetTabletUID}, + SourceShard: "targetks/0", Position: position, Status: "Running", Info: "VStream Lag: 0s", + }, + }, + }, + "targetks/80-": { + Streams: []*vtctldatapb.WorkflowStatusResponse_ShardStreamState{ + { + Id: 1, + Tablet: &topodatapb.TabletAlias{Cell: defaultCellName, Uid: startingTargetTabletUID + tabletUIDStep}, + SourceShard: "targetks/0", Position: position, Status: "Running", Info: "VStream Lag: 0s", + }, + }, + }, + }, + TrafficState: "Reads Not Switched. Writes Not Switched", + }, + }, + { + name: "no primary", + sourceKeyspace: &testKeyspace{ + KeyspaceName: sourceKeyspaceName, + ShardNames: []string{"0"}, + }, + targetKeyspace: &testKeyspace{ + KeyspaceName: targetKeyspaceName, + ShardNames: []string{"-80", "80-"}, + }, + preFunc: func(env *testEnv) { + _, err := env.ts.UpdateShardFields(ctx, targetKeyspaceName, "-80", func(si *topo.ShardInfo) error { + si.PrimaryAlias = nil + return nil + }) + require.NoError(t, err) + }, + wantErr: "buildResharder: target shard -80 has no primary tablet", + }, + } + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + require.NotNil(t, tc.sourceKeyspace) + require.NotNil(t, tc.targetKeyspace) + + env := newTestEnv(t, ctx, defaultCellName, tc.sourceKeyspace, tc.targetKeyspace) + defer env.close() + env.tmc.schema = schema + + req := &vtctldatapb.ReshardCreateRequest{ + Keyspace: targetKeyspaceName, + Workflow: workflowName, + TabletTypes: tabletTypes, + SourceShards: tc.sourceKeyspace.ShardNames, + TargetShards: tc.targetKeyspace.ShardNames, + Cells: []string{env.cell}, + } + + for i := range tc.sourceKeyspace.ShardNames { + tabletUID := startingSourceTabletUID + (tabletUIDStep * i) + env.tmc.expectVRQuery( + tabletUID, + "select distinct table_name from _vt.copy_state cs, _vt.vreplication vr where vr.id = cs.vrepl_id and vr.id = 1", + &sqltypes.Result{}, + ) + env.tmc.expectVRQuery( + tabletUID, + "select vrepl_id, table_name, lastpk from _vt.copy_state where vrepl_id in (1) and id in (select max(id) from _vt.copy_state where vrepl_id in (1) group by vrepl_id, table_name)", + &sqltypes.Result{}, + ) + } + + for i, target := range tc.targetKeyspace.ShardNames { + tabletUID := startingTargetTabletUID + (tabletUIDStep * i) + env.tmc.expectVRQuery( + tabletUID, + insertPrefix+ + `\('`+workflowName+`', 'keyspace:"`+targetKeyspaceName+`" shard:"0" filter:{rules:{match:"/.*" filter:"`+target+`"}}', '', [0-9]*, [0-9]*, '`+ + env.cell+`', '`+tabletTypesStr+`', [0-9]*, 0, 'Stopped', 'vt_`+targetKeyspaceName+`', 4, 0, false, '{}'\)`+eol, + &sqltypes.Result{}, + ) + env.tmc.expectVRQuery( + tabletUID, + "select distinct table_name from _vt.copy_state cs, _vt.vreplication vr where vr.id = cs.vrepl_id and vr.id = 1", + &sqltypes.Result{}, + ) + env.tmc.expectVRQuery( + tabletUID, + "select vrepl_id, table_name, lastpk from _vt.copy_state where vrepl_id in (1) and id in (select max(id) from _vt.copy_state where vrepl_id in (1) group by vrepl_id, table_name)", + &sqltypes.Result{}, + ) + } + + if tc.preFunc != nil { + tc.preFunc(env) + } + + res, err := env.ws.ReshardCreate(ctx, req) + if tc.wantErr != "" { + require.EqualError(t, err, tc.wantErr) + return + } + require.NoError(t, err) + if tc.want != nil { + require.Equal(t, tc.want, res) + } + }) + } +} diff --git a/go/vt/vtctl/workflow/server.go b/go/vt/vtctl/workflow/server.go index 587caff3c8c..5b6c3f05343 100644 --- a/go/vt/vtctl/workflow/server.go +++ b/go/vt/vtctl/workflow/server.go @@ -66,6 +66,7 @@ import ( binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" querypb "vitess.io/vitess/go/vt/proto/query" tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" + "vitess.io/vitess/go/vt/proto/topodata" topodatapb "vitess.io/vitess/go/vt/proto/topodata" vschemapb "vitess.io/vitess/go/vt/proto/vschema" vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" @@ -80,6 +81,8 @@ const ( rdonlyTabletSuffix = "@rdonly" // Globally routable tables don't have a keyspace prefix. globalTableQualifier = "" + // Default duration used for lag, timeout, etc. + DefaultTimeout = 30 * time.Second ) var tabletTypeSuffixes = []string{primaryTabletSuffix, replicaTabletSuffix, rdonlyTabletSuffix} @@ -129,9 +132,6 @@ const ( lockTablesCycles = 2 // Time to wait between LOCK TABLES cycles on the sources during SwitchWrites. lockTablesCycleDelay = time.Duration(100 * time.Millisecond) - - // Default duration used for lag, timeout, etc. - defaultDuration = 30 * time.Second ) var ( @@ -958,10 +958,7 @@ func (s *Server) getWorkflowState(ctx context.Context, targetKeyspace, workflowN return ts, state, nil } - var ( - reverse bool - sourceKeyspace string - ) + var sourceKeyspace string // We reverse writes by using the source_keyspace.workflowname_reverse workflow // spec, so we need to use the source of the reverse workflow, which is the @@ -970,7 +967,7 @@ func (s *Server) getWorkflowState(ctx context.Context, targetKeyspace, workflowN // source to check if writes have been switched. if strings.HasSuffix(workflowName, "_reverse") { - reverse = true + state.IsReverse = true // Flip the source and target keyspaces. sourceKeyspace = state.TargetKeyspace targetKeyspace = state.SourceKeyspace @@ -1039,7 +1036,7 @@ func (s *Server) getWorkflowState(ctx context.Context, targetKeyspace, workflowN // We assume a consistent state, so only choose one shard. var shard *topo.ShardInfo - if reverse { + if state.IsReverse { shard = ts.TargetShards()[0] } else { shard = ts.SourceShards()[0] @@ -1460,13 +1457,21 @@ func (s *Server) moveTablesCreate(ctx context.Context, req *vtctldatapb.MoveTabl return nil, err } sw := &switcher{s: s, ts: ts} - lockCtx, targetUnlock, lockErr := sw.lockKeyspace(ctx, ts.TargetKeyspaceName(), "MoveTablesCreate") + + // When creating the workflow, locking the workflow and its target keyspace is sufficient. + lockName := fmt.Sprintf("%s/%s", ts.TargetKeyspaceName(), ts.WorkflowName()) + ctx, workflowUnlock, lockErr := s.ts.LockName(ctx, lockName, "MoveTablesCreate") + if lockErr != nil { + ts.Logger().Errorf("Locking the workflow %s failed: %v", lockName, lockErr) + return nil, lockErr + } + defer workflowUnlock(&err) + ctx, targetUnlock, lockErr := sw.lockKeyspace(ctx, ts.TargetKeyspaceName(), "MoveTablesCreate") if lockErr != nil { ts.Logger().Errorf("Locking target keyspace %s failed: %v", ts.TargetKeyspaceName(), lockErr) return nil, lockErr } defer targetUnlock(&err) - ctx = lockCtx // If we get an error after this point, where the vreplication streams/records // have been created, then we clean up the workflow's artifacts. @@ -1725,7 +1730,7 @@ func (s *Server) ReshardCreate(ctx context.Context, req *vtctldatapb.ReshardCrea if err := s.ts.ValidateSrvKeyspace(ctx, keyspace, strings.Join(cells, ",")); err != nil { err2 := vterrors.Wrapf(err, "SrvKeyspace for keyspace %s is corrupt for cell(s) %s", keyspace, cells) - log.Errorf("%w", err2) + log.Errorf("%v", err2) return nil, err } tabletTypesStr := discovery.BuildTabletTypesString(req.TabletTypes, req.TabletSelectionPreference) @@ -1755,6 +1760,7 @@ func (s *Server) ReshardCreate(ctx context.Context, req *vtctldatapb.ReshardCrea return s.WorkflowStatus(ctx, &vtctldatapb.WorkflowStatusRequest{ Keyspace: req.Keyspace, Workflow: req.Workflow, + Shards: req.TargetShards, }) } @@ -2535,7 +2541,7 @@ func (s *Server) optimizeCopyStateTable(tablet *topodatapb.Tablet) { s.sem.Release(1) } }() - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) + ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout) defer cancel() sqlOptimizeTable := "optimize table _vt.copy_state" if _, err := s.tmc.ExecuteFetchAsAllPrivs(ctx, tablet, &tabletmanagerdatapb.ExecuteFetchAsAllPrivsRequest{ @@ -2571,24 +2577,30 @@ func (s *Server) DropTargets(ctx context.Context, ts *trafficSwitcher, keepData, } else { sw = &switcher{s: s, ts: ts} } - var tctx context.Context - tctx, sourceUnlock, lockErr := sw.lockKeyspace(ctx, ts.SourceKeyspaceName(), "DropTargets") + + // Lock the workflow along with its source and target keyspaces. + lockName := fmt.Sprintf("%s/%s", ts.TargetKeyspaceName(), ts.WorkflowName()) + ctx, workflowUnlock, lockErr := s.ts.LockName(ctx, lockName, "DropTargets") + if lockErr != nil { + ts.Logger().Errorf("Locking the workflow %s failed: %v", lockName, lockErr) + } + defer workflowUnlock(&err) + ctx, sourceUnlock, lockErr := sw.lockKeyspace(ctx, ts.SourceKeyspaceName(), "DropTargets") if lockErr != nil { ts.Logger().Errorf("Source LockKeyspace failed: %v", lockErr) return nil, lockErr } defer sourceUnlock(&err) - ctx = tctx - if ts.TargetKeyspaceName() != ts.SourceKeyspaceName() { - tctx, targetUnlock, lockErr := sw.lockKeyspace(ctx, ts.TargetKeyspaceName(), "DropTargets") + lockCtx, targetUnlock, lockErr := sw.lockKeyspace(ctx, ts.TargetKeyspaceName(), "DropTargets") if lockErr != nil { ts.Logger().Errorf("Target LockKeyspace failed: %v", lockErr) return nil, lockErr } defer targetUnlock(&err) - ctx = tctx + ctx = lockCtx } + if !keepData { switch ts.MigrationType() { case binlogdatapb.MigrationType_TABLES: @@ -2763,23 +2775,30 @@ func (s *Server) dropSources(ctx context.Context, ts *trafficSwitcher, removalTy } else { sw = &switcher{ts: ts, s: s} } - var tctx context.Context - tctx, sourceUnlock, lockErr := sw.lockKeyspace(ctx, ts.SourceKeyspaceName(), "DropSources") + + // Lock the workflow and its source and target keyspaces. + lockName := fmt.Sprintf("%s/%s", ts.TargetKeyspaceName(), ts.WorkflowName()) + ctx, workflowUnlock, lockErr := s.ts.LockName(ctx, lockName, "DropSources") + if lockErr != nil { + ts.Logger().Errorf("Locking the workflow %s failed: %v", lockName, lockErr) + } + defer workflowUnlock(&err) + ctx, sourceUnlock, lockErr := sw.lockKeyspace(ctx, ts.SourceKeyspaceName(), "DropSources") if lockErr != nil { ts.Logger().Errorf("Source LockKeyspace failed: %v", lockErr) return nil, lockErr } defer sourceUnlock(&err) - ctx = tctx if ts.TargetKeyspaceName() != ts.SourceKeyspaceName() { - tctx, targetUnlock, lockErr := sw.lockKeyspace(ctx, ts.TargetKeyspaceName(), "DropSources") + lockCtx, targetUnlock, lockErr := sw.lockKeyspace(ctx, ts.TargetKeyspaceName(), "DropSources") if lockErr != nil { ts.Logger().Errorf("Target LockKeyspace failed: %v", lockErr) return nil, lockErr } defer targetUnlock(&err) - ctx = tctx + ctx = lockCtx } + if !force { if err := sw.validateWorkflowHasCompleted(ctx); err != nil { ts.Logger().Errorf("Workflow has not completed, cannot DropSources: %v", err) @@ -2997,14 +3016,21 @@ func (s *Server) finalizeMigrateWorkflow(ctx context.Context, ts *trafficSwitche } else { sw = &switcher{s: s, ts: ts} } - var tctx context.Context - tctx, targetUnlock, lockErr := sw.lockKeyspace(ctx, ts.TargetKeyspaceName(), "completeMigrateWorkflow") + + // Lock the workflow and its target keyspace. + lockName := fmt.Sprintf("%s/%s", ts.TargetKeyspaceName(), ts.WorkflowName()) + ctx, workflowUnlock, lockErr := s.ts.LockName(ctx, lockName, "completeMigrateWorkflow") + if lockErr != nil { + ts.Logger().Errorf("Locking the workflow %s failed: %v", lockName, lockErr) + } + defer workflowUnlock(&err) + ctx, targetUnlock, lockErr := sw.lockKeyspace(ctx, ts.TargetKeyspaceName(), "completeMigrateWorkflow") if lockErr != nil { ts.Logger().Errorf("Target LockKeyspace failed: %v", lockErr) return nil, lockErr } defer targetUnlock(&err) - ctx = tctx + if err := sw.dropTargetVReplicationStreams(ctx); err != nil { return nil, err } @@ -3032,13 +3058,19 @@ func (s *Server) WorkflowSwitchTraffic(ctx context.Context, req *vtctldatapb.Wor rdDryRunResults, wrDryRunResults *[]string hasReplica, hasRdonly, hasPrimary bool ) - timeout, set, err := protoutil.DurationFromProto(req.Timeout) + timeout, set, err := protoutil.DurationFromProto(req.GetTimeout()) if err != nil { err = vterrors.Wrapf(err, "unable to parse Timeout into a valid duration") return nil, err } if !set { - timeout = defaultDuration + timeout = DefaultTimeout + } + // We enforce the 1 second minimum as some things that use it, such as Etcd, only takes + // a seconds value so you'd get unexpected behavior if you e.g. set the timeout to + // 500ms as Etcd would get a value of 0 or a never-ending TTL. + if timeout.Seconds() < 1 { + return nil, vterrors.Wrap(err, "Timeout must be at least 1 second") } ts, startState, err := s.getWorkflowState(ctx, req.Keyspace, req.Workflow) if err != nil { @@ -3055,7 +3087,7 @@ func (s *Server) WorkflowSwitchTraffic(ctx context.Context, req *vtctldatapb.Wor return nil, err } if !set { - maxReplicationLagAllowed = defaultDuration + maxReplicationLagAllowed = DefaultTimeout } direction := TrafficSwitchDirection(req.Direction) if direction == DirectionBackward { @@ -3238,12 +3270,37 @@ func (s *Server) switchReads(ctx context.Context, req *vtctldatapb.WorkflowSwitc return handleError("workflow validation failed", err) } + // For switching reads, locking the source keyspace is sufficient. + // We need to hold the keyspace locks longer than the command timeout. + ksLockTTL, set, err := protoutil.DurationFromProto(req.GetTimeout()) + if err != nil { + return nil, vterrors.Wrapf(err, "unable to parse Timeout into a valid duration") + } + if !set { + ksLockTTL = DefaultTimeout + } + // For reads, locking the source keyspace is sufficient. - ctx, unlock, lockErr := sw.lockKeyspace(ctx, ts.SourceKeyspaceName(), "SwitchReads") + ctx, unlock, lockErr := sw.lockKeyspace(ctx, ts.SourceKeyspaceName(), "SwitchReads", topo.WithTTL(ksLockTTL)) if lockErr != nil { return handleError(fmt.Sprintf("failed to lock the %s keyspace", ts.SourceKeyspaceName()), lockErr) } defer unlock(&err) + confirmKeyspaceLocksHeld := func() error { + if req.DryRun { // We don't actually take locks + return nil + } + if err := topo.CheckKeyspaceLocked(ctx, ts.SourceKeyspaceName()); err != nil { + return vterrors.Wrapf(err, "%s keyspace lock was lost", ts.SourceKeyspaceName()) + } + return nil + } + + // Remove mirror rules for the specified tablet types. + if err := sw.mirrorTableTraffic(ctx, roTabletTypes, 0); err != nil { + return handleError(fmt.Sprintf("failed to remove mirror rules from source keyspace %s to target keyspace %s, workflow %s, for read-only tablet types", + ts.SourceKeyspaceName(), ts.TargetKeyspaceName(), ts.WorkflowName()), err) + } if ts.MigrationType() == binlogdatapb.MigrationType_TABLES { switch { @@ -3263,11 +3320,18 @@ func (s *Server) switchReads(ctx context.Context, req *vtctldatapb.WorkflowSwitc } return sw.logs(), nil } + + if err := confirmKeyspaceLocksHeld(); err != nil { + return handleError("locks were lost", err) + } ts.Logger().Infof("About to switchShardReads: cells: %s, tablet types: %s, direction: %d", cellsStr, roTypesToSwitchStr, direction) if err := sw.switchShardReads(ctx, req.Cells, roTabletTypes, direction); err != nil { return handleError("failed to switch read traffic for the shards", err) } + if err := confirmKeyspaceLocksHeld(); err != nil { + return handleError("locks were lost", err) + } ts.Logger().Infof("switchShardReads Completed: cells: %s, tablet types: %s, direction: %d", cellsStr, roTypesToSwitchStr, direction) if err := s.ts.ValidateSrvKeyspace(ctx, ts.targetKeyspace, cellsStr); err != nil { err2 := vterrors.Wrapf(err, "after switching shard reads, found SrvKeyspace for %s is corrupt in cell %s", @@ -3278,7 +3342,7 @@ func (s *Server) switchReads(ctx context.Context, req *vtctldatapb.WorkflowSwitc } // switchWrites is a generic way of migrating write traffic for a workflow. -func (s *Server) switchWrites(ctx context.Context, req *vtctldatapb.WorkflowSwitchTrafficRequest, ts *trafficSwitcher, timeout time.Duration, +func (s *Server) switchWrites(ctx context.Context, req *vtctldatapb.WorkflowSwitchTrafficRequest, ts *trafficSwitcher, waitTimeout time.Duration, cancel bool, ) (journalID int64, dryRunResults *[]string, err error) { var sw iswitcher @@ -3310,21 +3374,53 @@ func (s *Server) switchWrites(ctx context.Context, req *vtctldatapb.WorkflowSwit } } + // Lock the workflow and its source and target keyspaces. + lockName := fmt.Sprintf("%s/%s", ts.TargetKeyspaceName(), ts.WorkflowName()) + ctx, workflowUnlock, lockErr := s.ts.LockName(ctx, lockName, "SwitchWrites") + if lockErr != nil { + return handleError(fmt.Sprintf("failed to lock the %s workflow", lockName), lockErr) + } + defer workflowUnlock(&err) + + // 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 + // Need to lock both source and target keyspaces. - tctx, sourceUnlock, lockErr := sw.lockKeyspace(ctx, ts.SourceKeyspaceName(), "SwitchWrites") + ctx, sourceUnlock, lockErr := sw.lockKeyspace(ctx, ts.SourceKeyspaceName(), "SwitchWrites", topo.WithTTL(ksLockTTL)) if lockErr != nil { return handleError(fmt.Sprintf("failed to lock the %s keyspace", ts.SourceKeyspaceName()), lockErr) } - ctx = tctx defer sourceUnlock(&err) + if ts.TargetKeyspaceName() != ts.SourceKeyspaceName() { - tctx, targetUnlock, lockErr := sw.lockKeyspace(ctx, ts.TargetKeyspaceName(), "SwitchWrites") + lockCtx, targetUnlock, lockErr := sw.lockKeyspace(ctx, ts.TargetKeyspaceName(), "SwitchWrites", topo.WithTTL(ksLockTTL)) if lockErr != nil { return handleError(fmt.Sprintf("failed to lock the %s keyspace", ts.TargetKeyspaceName()), lockErr) } - ctx = tctx + ctx = lockCtx defer targetUnlock(&err) } + confirmKeyspaceLocksHeld := func() error { + if req.DryRun { // We don't actually take locks + return nil + } + if err := topo.CheckKeyspaceLocked(ctx, ts.SourceKeyspaceName()); err != nil { + return vterrors.Wrapf(err, "%s keyspace lock was lost", ts.SourceKeyspaceName()) + } + if err := topo.CheckKeyspaceLocked(ctx, ts.TargetKeyspaceName()); err != nil { + return vterrors.Wrapf(err, "%s keyspace lock was lost", ts.TargetKeyspaceName()) + } + return nil + } + + // Remove mirror rules for the primary tablet type. + if err := sw.mirrorTableTraffic(ctx, []topodata.TabletType{topodatapb.TabletType_PRIMARY}, 0); err != nil { + return handleError(fmt.Sprintf("failed to remove mirror rules from source keyspace %s to target keyspace %s, workflow %s, for primary tablet type", + ts.SourceKeyspaceName(), ts.TargetKeyspaceName(), ts.WorkflowName()), err) + } // Find out if the target is using any sequence tables for auto_increment // value generation. If so, then we'll need to ensure that they are @@ -3375,7 +3471,7 @@ func (s *Server) switchWrites(ctx context.Context, req *vtctldatapb.WorkflowSwit // materializations then we have to wait for them to catchup before switching traffic for the // Reshard workflow. We use the the same timeout value here that is used for VReplication catchup // with the inter-keyspace workflows. - stopCtx, stopCancel := context.WithTimeout(ctx, timeout) + stopCtx, stopCancel := context.WithTimeout(ctx, waitTimeout) defer stopCancel() sourceWorkflows, err = sw.stopStreams(stopCtx, sm) if err != nil { @@ -3403,37 +3499,51 @@ func (s *Server) switchWrites(ctx context.Context, req *vtctldatapb.WorkflowSwit } } + if err := confirmKeyspaceLocksHeld(); err != nil { + return handleError("locks were lost", err) + } ts.Logger().Infof("Waiting for streams to catchup") - if err := sw.waitForCatchup(ctx, timeout); err != nil { + if err := sw.waitForCatchup(ctx, waitTimeout); err != nil { sw.cancelMigration(ctx, sm) return handleError("failed to sync up replication between the source and target", err) } + if err := confirmKeyspaceLocksHeld(); err != nil { + return handleError("locks were lost", err) + } ts.Logger().Infof("Migrating streams") if err := sw.migrateStreams(ctx, sm); err != nil { sw.cancelMigration(ctx, sm) return handleError("failed to migrate the workflow streams", err) } + if err := confirmKeyspaceLocksHeld(); err != nil { + return handleError("locks were lost", err) + } ts.Logger().Infof("Resetting sequences") if err := sw.resetSequences(ctx); err != nil { sw.cancelMigration(ctx, sm) return handleError("failed to reset the sequences", err) } + if err := confirmKeyspaceLocksHeld(); err != nil { + return handleError("locks were lost", err) + } ts.Logger().Infof("Creating reverse streams") if err := sw.createReverseVReplication(ctx); err != nil { sw.cancelMigration(ctx, sm) return handleError("failed to create the reverse vreplication streams", err) } + if err := confirmKeyspaceLocksHeld(); err != nil { + return handleError("locks were lost", err) + } // Initialize any target sequences, if there are any, before allowing new writes. if req.InitializeTargetSequences && len(sequenceMetadata) > 0 { ts.Logger().Infof("Initializing target sequences") // Writes are blocked so we can safely initialize the sequence tables but - // we also want to use a shorter timeout than the parent context. - // We use at most half of the overall timeout. - initSeqCtx, cancel := context.WithTimeout(ctx, timeout/2) + // we also want to use a shorter timeout than the the default. + initSeqCtx, cancel := context.WithTimeout(ctx, waitTimeout/2) defer cancel() if err := sw.initializeTargetSequences(initSeqCtx, sequenceMetadata); err != nil { sw.cancelMigration(ctx, sm) @@ -3453,6 +3563,9 @@ func (s *Server) switchWrites(ctx context.Context, req *vtctldatapb.WorkflowSwit // 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 := sw.createJournals(ctx, sourceWorkflows); err != nil { return handleError("failed to create the journal", err) } @@ -3634,7 +3747,7 @@ func (s *Server) applySQLShard(ctx context.Context, tabletInfo *topo.TabletInfo, if err != nil { return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "fillStringTemplate failed: %v", err) } - ctx, cancel := context.WithTimeout(ctx, 30*time.Second) + ctx, cancel := context.WithTimeout(ctx, DefaultTimeout) defer cancel() // Need to make sure that replication is enabled since we're only applying // the statement on primaries. @@ -3811,7 +3924,7 @@ func (s *Server) prepareCreateLookup(ctx context.Context, workflow, keyspace str targetVSchema.Tables = make(map[string]*vschemapb.Table) } if existing, ok := sourceVSchema.Vindexes[vindexName]; ok { - if !proto.Equal(existing, vindex) { + if !proto.Equal(existing, vindex) { // If the exact same vindex already exists then we can re-use it return nil, nil, nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "a conflicting vindex named %s already exists in the %s keyspace", vindexName, keyspace) } } @@ -3824,13 +3937,18 @@ func (s *Server) prepareCreateLookup(ctx context.Context, workflow, keyspace str if colVindex.Name != vindexName { continue } - colName := colVindex.Column - if len(colVindex.Columns) != 0 { - colName = colVindex.Columns[0] + var colNames []string + if len(colVindex.Columns) == 0 { + colNames = []string{colVindex.Column} + } else { + colNames = colVindex.Columns } - if colName == sourceVindexColumns[0] { - return nil, nil, nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "a conflicting ColumnVindex on column %s in table %s already exists in the %s keyspace", - colName, sourceTableName, keyspace) + // If this is the exact same definition then we can use the existing one. If they + // are not the same then they are two distinct conflicting vindexes and we should + // not proceed. + if !slices.Equal(colNames, sourceVindexColumns) { + return nil, nil, nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "a conflicting ColumnVindex on column(s) %s in table %s already exists in the %s keyspace", + strings.Join(colNames, ","), sourceTableName, keyspace) } } @@ -3884,6 +4002,10 @@ func (s *Server) prepareCreateLookup(ctx context.Context, workflow, keyspace str modified = append(modified, buf.String()) modified = append(modified, ")") createDDL = strings.Join(modified, "\n") + // Confirm that our DDL is valid before we create anything. + if _, err = s.env.Parser().ParseStrictDDL(createDDL); err != nil { + return nil, nil, nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "error: %v; invalid lookup table definition generated: %s", err, createDDL) + } // Generate vreplication query. buf = sqlparser.NewTrackedBuffer(nil) @@ -3999,6 +4121,13 @@ func generateColDef(lines []string, sourceVindexCol, vindexFromCol string) (stri line = strings.Replace(line, source, target, 1) line = strings.Replace(line, " AUTO_INCREMENT", "", 1) line = strings.Replace(line, " DEFAULT NULL", "", 1) + // Ensure that the column definition ends with a comma as we will + // be appending the TO column and PRIMARY KEY definitions. If the + // souce column here was the last entity defined in the source + // table's definition then it will not already have the comma. + if !strings.HasSuffix(strings.TrimSpace(line), ",") { + line += "," + } return line, nil } } @@ -4051,3 +4180,94 @@ func (s *Server) getWorkflowStatus(ctx context.Context, keyspace string, workflo } return workflowStatus, nil } + +// WorkflowMirrorTraffic mirrors traffic from the source keyspace to the target keyspace. +func (s *Server) WorkflowMirrorTraffic(ctx context.Context, req *vtctldatapb.WorkflowMirrorTrafficRequest) (*vtctldatapb.WorkflowMirrorTrafficResponse, error) { + ts, startState, err := s.getWorkflowState(ctx, req.Keyspace, req.Workflow) + if err != nil { + return nil, err + } + + // Traffic mirroring was built with basic MoveTables workflows in mind. In + // theory, other workflow types (e.g. Migrate) and variants (e.g. partial, + // multi-tenant) could be supported. Until demand for these use cases + // arises, reject everything but basic MoveTables. + if startState.WorkflowType != TypeMoveTables { + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "invalid action for %s workflow: MirrorTraffic", string(startState.WorkflowType)) + } + if startState.IsReverse { + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "invalid action for reverse workflow: MirrorTraffic") + } + if ts.MigrationType() != binlogdatapb.MigrationType_TABLES { + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "invalid action for %s migration type: MirrorTraffic", binlogdatapb.MigrationType_name[int32(ts.MigrationType())]) + } + if ts.IsPartialMigration() { + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "invalid action for partial migration: MirrorTraffic") + } + if ts.IsMultiTenantMigration() { + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "invalid action for multi-tenant migration: MirrorTraffic") + } + + // Don't allow traffic to be mirrored if any traffic has been switched over + // to the target keyspace. + var cannotSwitchTabletTypes []string + for _, tt := range req.TabletTypes { + if tt == topodatapb.TabletType_RDONLY && len(startState.RdonlyCellsSwitched) > 0 { + cannotSwitchTabletTypes = append(cannotSwitchTabletTypes, "rdonly") + } + if tt == topodatapb.TabletType_REPLICA && len(startState.ReplicaCellsSwitched) > 0 { + cannotSwitchTabletTypes = append(cannotSwitchTabletTypes, "replica") + } + if tt == topodatapb.TabletType_PRIMARY && startState.WritesSwitched { + cannotSwitchTabletTypes = append(cannotSwitchTabletTypes, "primary") + } + } + if len(cannotSwitchTabletTypes) > 0 { + return nil, vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "cannot mirror [%s] traffic for workflow %s at this time: traffic for those tablet types is switched", strings.Join(cannotSwitchTabletTypes, ","), startState.Workflow) + } + + if err := s.mirrorTraffic(ctx, req, ts, startState); err != nil { + return nil, err + } + + cmd := "MirrorTraffic" + resp := &vtctldatapb.WorkflowMirrorTrafficResponse{} + log.Infof("Mirror Traffic done for workflow %s.%s", req.Keyspace, req.Workflow) + resp.Summary = fmt.Sprintf("%s was successful for workflow %s.%s", cmd, req.Keyspace, req.Workflow) + // Reload the state after the MirrorTraffic operation + // and return that as a string. + keyspace := req.Keyspace + workflow := req.Workflow + resp.StartState = startState.String() + log.Infof("Before reloading workflow state after mirror traffic: %+v\n", resp.StartState) + _, currentState, err := s.getWorkflowState(ctx, keyspace, workflow) + if err != nil { + resp.CurrentState = fmt.Sprintf("Error reloading workflow state after mirror traffic: %v", err) + } else { + resp.CurrentState = currentState.String() + } + return resp, nil +} + +// mirrorTraffic manages mirror routing rules for tables in the workflow. +func (s *Server) mirrorTraffic(ctx context.Context, req *vtctldatapb.WorkflowMirrorTrafficRequest, ts *trafficSwitcher, state *State) (err error) { + // Consistently handle errors by logging and returning them. + handleError := func(message string, err error) error { + ts.Logger().Error(err) + return err + } + + log.Infof("Mirroring traffic: %s.%s, workflow state: %s", ts.targetKeyspace, ts.workflow, state.String()) + + sw := &switcher{ts: ts, s: s} + + if err := ts.validate(ctx); err != nil { + return handleError("workflow validation failed", err) + } + + if err := sw.mirrorTableTraffic(ctx, req.TabletTypes, req.Percent); err != nil { + return handleError("failed to mirror traffic for the tables", err) + } + + return nil +} diff --git a/go/vt/vtctl/workflow/server_test.go b/go/vt/vtctl/workflow/server_test.go index fb432403155..c67d45bb9e6 100644 --- a/go/vt/vtctl/workflow/server_test.go +++ b/go/vt/vtctl/workflow/server_test.go @@ -18,6 +18,7 @@ package workflow import ( "context" + "encoding/json" "fmt" "slices" "sort" @@ -34,6 +35,7 @@ import ( "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/topo/memorytopo" "vitess.io/vitess/go/vt/topo/topoproto" + "vitess.io/vitess/go/vt/topotools" "vitess.io/vitess/go/vt/vtenv" "vitess.io/vitess/go/vt/vttablet/tmclient" @@ -405,11 +407,13 @@ func TestMoveTablesTrafficSwitching(t *testing.T) { sourceKeyspaceName := "sourceks" targetKeyspaceName := "targetks" vrID := 1 + tabletTypes := []topodatapb.TabletType{ topodatapb.TabletType_PRIMARY, topodatapb.TabletType_REPLICA, topodatapb.TabletType_RDONLY, } + schema := map[string]*tabletmanagerdatapb.SchemaDefinition{ tableName: { TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ @@ -420,6 +424,7 @@ func TestMoveTablesTrafficSwitching(t *testing.T) { }, }, } + copyTableQR := &queryResult{ query: fmt.Sprintf("select vrepl_id, table_name, lastpk from _vt.copy_state where vrepl_id in (%d) and id in (select max(id) from _vt.copy_state where vrepl_id in (%d) group by vrepl_id, table_name)", vrID, vrID), @@ -685,11 +690,13 @@ func TestMoveTablesTrafficSwitchingDryRun(t *testing.T) { }, want: []string{ fmt.Sprintf("Lock keyspace %s", sourceKeyspaceName), + fmt.Sprintf("Mirroring 0.00 percent of traffic from keyspace %s to keyspace %s for tablet types [REPLICA,RDONLY]", sourceKeyspaceName, targetKeyspaceName), fmt.Sprintf("Switch reads for tables [%s] to keyspace %s for tablet types [REPLICA,RDONLY]", tablesStr, targetKeyspaceName), fmt.Sprintf("Routing rules for tables [%s] will be updated", tablesStr), fmt.Sprintf("Unlock keyspace %s", sourceKeyspaceName), fmt.Sprintf("Lock keyspace %s", sourceKeyspaceName), fmt.Sprintf("Lock keyspace %s", targetKeyspaceName), + fmt.Sprintf("Mirroring 0.00 percent of traffic from keyspace %s to keyspace %s for tablet types [PRIMARY]", sourceKeyspaceName, targetKeyspaceName), fmt.Sprintf("Stop writes on keyspace %s for tables [%s]: [keyspace:%s;shard:-80;position:%s,keyspace:%s;shard:80-;position:%s]", sourceKeyspaceName, tablesStr, sourceKeyspaceName, position, sourceKeyspaceName, position), "Wait for vreplication on stopped streams to catchup for up to 30s", @@ -724,11 +731,13 @@ func TestMoveTablesTrafficSwitchingDryRun(t *testing.T) { }, want: []string{ fmt.Sprintf("Lock keyspace %s", targetKeyspaceName), + fmt.Sprintf("Mirroring 0.00 percent of traffic from keyspace %s to keyspace %s for tablet types [REPLICA,RDONLY]", targetKeyspaceName, sourceKeyspaceName), fmt.Sprintf("Switch reads for tables [%s] to keyspace %s for tablet types [REPLICA,RDONLY]", tablesStr, targetKeyspaceName), fmt.Sprintf("Routing rules for tables [%s] will be updated", tablesStr), fmt.Sprintf("Unlock keyspace %s", targetKeyspaceName), fmt.Sprintf("Lock keyspace %s", targetKeyspaceName), fmt.Sprintf("Lock keyspace %s", sourceKeyspaceName), + fmt.Sprintf("Mirroring 0.00 percent of traffic from keyspace %s to keyspace %s for tablet types [PRIMARY]", targetKeyspaceName, sourceKeyspaceName), fmt.Sprintf("Stop writes on keyspace %s for tables [%s]: [keyspace:%s;shard:-80;position:%s,keyspace:%s;shard:80-;position:%s]", targetKeyspaceName, tablesStr, targetKeyspaceName, position, targetKeyspaceName, position), "Wait for vreplication on stopped streams to catchup for up to 30s", @@ -780,3 +789,416 @@ func TestMoveTablesTrafficSwitchingDryRun(t *testing.T) { }) } } + +func TestMirrorTraffic(t *testing.T) { + ctx := context.Background() + sourceKs := "source" + sourceShards := []string{"-"} + targetKs := "target" + targetShards := []string{"-80", "80-"} + table1 := "table1" + table2 := "table2" + workflow := "src2target" + + mirrorRules := map[string]map[string]float32{} + routingRules := map[string][]string{ + fmt.Sprintf("%s.%s@rdonly", sourceKs, table1): {fmt.Sprintf("%s.%s", targetKs, table1)}, + fmt.Sprintf("%s.%s@rdonly", sourceKs, table2): {fmt.Sprintf("%s.%s", targetKs, table2)}, + } + + tabletTypes := []topodatapb.TabletType{ + topodatapb.TabletType_PRIMARY, + topodatapb.TabletType_REPLICA, + topodatapb.TabletType_RDONLY, + } + + tests := []struct { + name string + + req *vtctldatapb.WorkflowMirrorTrafficRequest + mirrorRules map[string]map[string]float32 + routingRules map[string][]string + setup func(*testing.T, context.Context, *testMaterializerEnv) + sourceKeyspace string + sourceShards []string + targetKeyspace string + targetShards []string + + wantErr string + wantMirrorRules map[string]map[string]float32 + }{ + { + name: "no such keyspace", + req: &vtctldatapb.WorkflowMirrorTrafficRequest{ + Keyspace: "no_ks", + Workflow: workflow, + TabletTypes: tabletTypes, + Percent: 50.0, + }, + wantErr: "FindAllShardsInKeyspace(no_ks): List: node doesn't exist: keyspaces/no_ks/shards", + wantMirrorRules: make(map[string]map[string]float32), + }, + { + name: "no such workflow", + req: &vtctldatapb.WorkflowMirrorTrafficRequest{ + Keyspace: targetKs, + Workflow: "no_workflow", + TabletTypes: tabletTypes, + Percent: 50.0, + }, + setup: func(t *testing.T, ctx context.Context, te *testMaterializerEnv) { + te.tmc.readVReplicationWorkflow = func( + ctx context.Context, + tablet *topodatapb.Tablet, + request *tabletmanagerdatapb.ReadVReplicationWorkflowRequest, + ) (*tabletmanagerdatapb.ReadVReplicationWorkflowResponse, error) { + return nil, nil + } + }, + wantErr: "no streams found in keyspace target for no_workflow", + wantMirrorRules: make(map[string]map[string]float32), + }, + { + name: "cannot mirror traffic for migrate workflows", + req: &vtctldatapb.WorkflowMirrorTrafficRequest{ + Keyspace: targetKs, + Workflow: "migrate", + TabletTypes: tabletTypes, + Percent: 50.0, + }, + setup: func(t *testing.T, ctx context.Context, te *testMaterializerEnv) { + te.tmc.readVReplicationWorkflow = createReadVReplicationWorkflowFunc(t, binlogdatapb.VReplicationWorkflowType_Migrate, nil, te.tmc.keyspace, sourceShards, []string{table1, table2}) + }, + wantErr: "invalid action for Migrate workflow: MirrorTraffic", + wantMirrorRules: make(map[string]map[string]float32), + }, + { + name: "cannot mirror traffic for reshard workflows", + req: &vtctldatapb.WorkflowMirrorTrafficRequest{ + Keyspace: sourceKs, + Workflow: "reshard", + TabletTypes: tabletTypes, + Percent: 50.0, + }, + sourceKeyspace: sourceKs, + sourceShards: []string{"-80", "80-"}, + targetKeyspace: sourceKs, + targetShards: []string{"-55", "55-aa", "55-"}, + setup: func(t *testing.T, ctx context.Context, te *testMaterializerEnv) { + te.tmc.readVReplicationWorkflow = createReadVReplicationWorkflowFunc(t, binlogdatapb.VReplicationWorkflowType_Reshard, nil, sourceKs, []string{"-80", "80-"}, []string{table1, table2}) + }, + wantErr: "invalid action for Reshard workflow: MirrorTraffic", + wantMirrorRules: make(map[string]map[string]float32), + }, + { + name: "cannot mirror rdonly traffic after switch rdonly traffic", + req: &vtctldatapb.WorkflowMirrorTrafficRequest{ + Keyspace: targetKs, + Workflow: workflow, + TabletTypes: tabletTypes, + Percent: 50.0, + }, + routingRules: map[string][]string{ + fmt.Sprintf("%s.%s@rdonly", targetKs, table1): {fmt.Sprintf("%s.%s@rdonly", targetKs, table1)}, + fmt.Sprintf("%s.%s@rdonly", targetKs, table2): {fmt.Sprintf("%s.%s@rdonly", targetKs, table2)}, + }, + wantErr: "cannot mirror [rdonly] traffic for workflow src2target at this time: traffic for those tablet types is switched", + wantMirrorRules: make(map[string]map[string]float32), + }, + { + name: "cannot mirror replica traffic after switch replica traffic", + req: &vtctldatapb.WorkflowMirrorTrafficRequest{ + Keyspace: targetKs, + Workflow: workflow, + TabletTypes: tabletTypes, + Percent: 50.0, + }, + routingRules: map[string][]string{ + fmt.Sprintf("%s.%s@replica", targetKs, table1): {fmt.Sprintf("%s.%s@replica", targetKs, table1)}, + fmt.Sprintf("%s.%s@replica", targetKs, table2): {fmt.Sprintf("%s.%s@replica", targetKs, table2)}, + }, + wantErr: "cannot mirror [replica] traffic for workflow src2target at this time: traffic for those tablet types is switched", + wantMirrorRules: make(map[string]map[string]float32), + }, + { + name: "cannot mirror write traffic after switch traffic", + req: &vtctldatapb.WorkflowMirrorTrafficRequest{ + Keyspace: targetKs, + Workflow: workflow, + TabletTypes: tabletTypes, + Percent: 50.0, + }, + routingRules: map[string][]string{ + table1: {fmt.Sprintf("%s.%s", targetKs, table1)}, + table2: {fmt.Sprintf("%s.%s", targetKs, table2)}, + }, + wantErr: "cannot mirror [primary] traffic for workflow src2target at this time: traffic for those tablet types is switched", + wantMirrorRules: make(map[string]map[string]float32), + }, + { + name: "does not mirror traffic for partial move tables", + req: &vtctldatapb.WorkflowMirrorTrafficRequest{ + Keyspace: targetKs, + Workflow: workflow, + TabletTypes: tabletTypes, + Percent: 50.0, + }, + setup: func(t *testing.T, ctx context.Context, te *testMaterializerEnv) { + te.tmc.readVReplicationWorkflow = func( + ctx context.Context, + tablet *topodatapb.Tablet, + request *tabletmanagerdatapb.ReadVReplicationWorkflowRequest, + ) (*tabletmanagerdatapb.ReadVReplicationWorkflowResponse, error) { + if tablet.Shard != "-80" { + return nil, nil + } + return &tabletmanagerdatapb.ReadVReplicationWorkflowResponse{ + Workflow: request.Workflow, + WorkflowType: binlogdatapb.VReplicationWorkflowType_MoveTables, + Streams: []*tabletmanagerdatapb.ReadVReplicationWorkflowResponse_Stream{ + { + Id: 1, + Bls: &binlogdatapb.BinlogSource{ + Keyspace: sourceKs, + Shard: "-80", + Filter: &binlogdatapb.Filter{ + Rules: []*binlogdatapb.Rule{ + {Match: table1}, + {Match: table2}, + }, + }, + }, + }, + }, + }, nil + } + }, + sourceShards: []string{"-80", "80-"}, + targetShards: []string{"-80", "80-"}, + wantErr: "invalid action for partial migration: MirrorTraffic", + wantMirrorRules: make(map[string]map[string]float32), + }, + { + name: "does not mirror traffic for multi-tenant move tables", + req: &vtctldatapb.WorkflowMirrorTrafficRequest{ + Keyspace: targetKs, + Workflow: workflow, + TabletTypes: tabletTypes, + Percent: 50.0, + }, + setup: func(t *testing.T, ctx context.Context, te *testMaterializerEnv) { + te.tmc.readVReplicationWorkflow = createReadVReplicationWorkflowFunc(t, binlogdatapb.VReplicationWorkflowType_MoveTables, &vtctldatapb.WorkflowOptions{TenantId: "123"}, te.tmc.keyspace, sourceShards, []string{table1, table2}) + }, + wantErr: "invalid action for multi-tenant migration: MirrorTraffic", + wantMirrorRules: make(map[string]map[string]float32), + }, + { + name: "does not mirror traffic for reverse move tables", + req: &vtctldatapb.WorkflowMirrorTrafficRequest{ + Keyspace: targetKs, + Workflow: workflow + "_reverse", + TabletTypes: tabletTypes, + Percent: 50.0, + }, + wantErr: "invalid action for reverse workflow: MirrorTraffic", + wantMirrorRules: make(map[string]map[string]float32), + }, + { + name: "ok", + req: &vtctldatapb.WorkflowMirrorTrafficRequest{ + Keyspace: targetKs, + Workflow: workflow, + TabletTypes: tabletTypes, + Percent: 50.0, + }, + wantMirrorRules: map[string]map[string]float32{ + fmt.Sprintf("%s.%s", sourceKs, table1): { + fmt.Sprintf("%s.%s", targetKs, table1): 50.0, + }, + fmt.Sprintf("%s.%s@replica", sourceKs, table1): { + fmt.Sprintf("%s.%s", targetKs, table1): 50.0, + }, + fmt.Sprintf("%s.%s@rdonly", sourceKs, table1): { + fmt.Sprintf("%s.%s", targetKs, table1): 50.0, + }, + fmt.Sprintf("%s.%s", sourceKs, table2): { + fmt.Sprintf("%s.%s", targetKs, table2): 50.0, + }, + fmt.Sprintf("%s.%s@replica", sourceKs, table2): { + fmt.Sprintf("%s.%s", targetKs, table2): 50.0, + }, + fmt.Sprintf("%s.%s@rdonly", sourceKs, table2): { + fmt.Sprintf("%s.%s", targetKs, table2): 50.0, + }, + }, + }, + { + name: "does not overwrite unrelated mirror rules", + mirrorRules: map[string]map[string]float32{ + "other_source.table2": { + fmt.Sprintf("%s.table2", targetKs): 25.0, + }, + }, + req: &vtctldatapb.WorkflowMirrorTrafficRequest{ + Keyspace: targetKs, + Workflow: workflow, + TabletTypes: tabletTypes, + Percent: 50.0, + }, + wantMirrorRules: map[string]map[string]float32{ + fmt.Sprintf("%s.%s", sourceKs, table1): { + fmt.Sprintf("%s.%s", targetKs, table1): 50.0, + }, + fmt.Sprintf("%s.%s@replica", sourceKs, table1): { + fmt.Sprintf("%s.%s", targetKs, table1): 50.0, + }, + fmt.Sprintf("%s.%s@rdonly", sourceKs, table1): { + fmt.Sprintf("%s.%s", targetKs, table1): 50.0, + }, + fmt.Sprintf("%s.%s", sourceKs, table2): { + fmt.Sprintf("%s.%s", targetKs, table2): 50.0, + }, + fmt.Sprintf("%s.%s@replica", sourceKs, table2): { + fmt.Sprintf("%s.%s", targetKs, table2): 50.0, + }, + fmt.Sprintf("%s.%s@rdonly", sourceKs, table2): { + fmt.Sprintf("%s.%s", targetKs, table2): 50.0, + }, + "other_source.table2": { + fmt.Sprintf("%s.table2", targetKs): 25.0, + }, + }, + }, + { + name: "does not overwrite when some but not all mirror rules already exist", + mirrorRules: map[string]map[string]float32{ + fmt.Sprintf("%s.%s", sourceKs, table1): { + fmt.Sprintf("%s.%s", targetKs, table1): 25.0, + }, + fmt.Sprintf("%s.%s@replica", sourceKs, table1): { + fmt.Sprintf("%s.%s", targetKs, table1): 25.0, + }, + fmt.Sprintf("%s.%s@rdonly", sourceKs, table1): { + fmt.Sprintf("%s.%s", targetKs, table1): 25.0, + }, + }, + req: &vtctldatapb.WorkflowMirrorTrafficRequest{ + Keyspace: targetKs, + Workflow: workflow, + TabletTypes: tabletTypes, + Percent: 50.0, + }, + wantErr: "wrong number of pre-existing mirror rules", + wantMirrorRules: map[string]map[string]float32{ + fmt.Sprintf("%s.%s", sourceKs, table1): { + fmt.Sprintf("%s.%s", targetKs, table1): 25.0, + }, + fmt.Sprintf("%s.%s@replica", sourceKs, table1): { + fmt.Sprintf("%s.%s", targetKs, table1): 25.0, + }, + fmt.Sprintf("%s.%s@rdonly", sourceKs, table1): { + fmt.Sprintf("%s.%s", targetKs, table1): 25.0, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.mirrorRules == nil { + tt.mirrorRules = mirrorRules + } + if tt.routingRules == nil { + tt.routingRules = routingRules + } + if tt.sourceKeyspace == "" { + tt.sourceKeyspace = sourceKs + } + if tt.sourceShards == nil { + tt.sourceShards = sourceShards + } + if tt.targetKeyspace == "" { + tt.targetKeyspace = targetKs + } + if tt.targetShards == nil { + tt.targetShards = targetShards + } + + te := newTestMaterializerEnv(t, ctx, &vtctldatapb.MaterializeSettings{ + SourceKeyspace: tt.sourceKeyspace, + TargetKeyspace: tt.targetKeyspace, + Workflow: workflow, + TableSettings: []*vtctldatapb.TableMaterializeSettings{ + { + TargetTable: table1, + SourceExpression: fmt.Sprintf("select * from %s", table1), + }, + { + TargetTable: table2, + SourceExpression: fmt.Sprintf("select * from %s", table2), + }, + }, + }, tt.sourceShards, tt.targetShards) + + require.NoError(t, topotools.SaveMirrorRules(ctx, te.topoServ, tt.mirrorRules)) + require.NoError(t, topotools.SaveRoutingRules(ctx, te.topoServ, tt.routingRules)) + require.NoError(t, te.topoServ.RebuildSrvVSchema(ctx, []string{te.cell})) + + if tt.setup != nil { + tt.setup(t, ctx, te) + } + + got, err := te.ws.WorkflowMirrorTraffic(ctx, tt.req) + if tt.wantErr != "" { + require.EqualError(t, err, tt.wantErr) + } else { + require.NoError(t, err) + require.NotNil(t, got) + } + mr, err := topotools.GetMirrorRules(ctx, te.topoServ) + require.NoError(t, err) + wantMirrorRules := tt.mirrorRules + if tt.wantMirrorRules != nil { + wantMirrorRules = tt.wantMirrorRules + } + require.Equal(t, wantMirrorRules, mr) + }) + } +} + +func createReadVReplicationWorkflowFunc(t *testing.T, workflowType binlogdatapb.VReplicationWorkflowType, workflowOptions *vtctldatapb.WorkflowOptions, sourceKeyspace string, sourceShards []string, sourceTables []string) readVReplicationWorkflowFunc { + return func(ctx context.Context, tablet *topodatapb.Tablet, request *tabletmanagerdatapb.ReadVReplicationWorkflowRequest) (*tabletmanagerdatapb.ReadVReplicationWorkflowResponse, error) { + streams := make([]*tabletmanagerdatapb.ReadVReplicationWorkflowResponse_Stream, 0) + for i, shard := range sourceShards { + if shard == tablet.Shard { + return nil, nil + } + rules := make([]*binlogdatapb.Rule, len(sourceTables)) + for i, table := range sourceTables { + rules[i] = &binlogdatapb.Rule{Match: table} + } + streams = append(streams, &tabletmanagerdatapb.ReadVReplicationWorkflowResponse_Stream{ + Id: int32(i + 1), + Bls: &binlogdatapb.BinlogSource{ + Keyspace: sourceKeyspace, + Shard: shard, + Filter: &binlogdatapb.Filter{Rules: rules}, + }, + }) + } + + var err error + var options []byte + if workflowOptions != nil { + options, err = json.Marshal(workflowOptions) + require.NoError(t, err) + } + + return &tabletmanagerdatapb.ReadVReplicationWorkflowResponse{ + Workflow: request.Workflow, + Options: string(options), + WorkflowType: workflowType, + Streams: streams, + }, nil + } +} diff --git a/go/vt/vtctl/workflow/state.go b/go/vt/vtctl/workflow/state.go index 927f5a9db56..9d2d1f23def 100644 --- a/go/vt/vtctl/workflow/state.go +++ b/go/vt/vtctl/workflow/state.go @@ -61,6 +61,7 @@ type State struct { SourceKeyspace string TargetKeyspace string WorkflowType Type + IsReverse bool ReplicaCellsSwitched []string ReplicaCellsNotSwitched []string diff --git a/go/vt/vtctl/workflow/switcher.go b/go/vt/vtctl/workflow/switcher.go index aa41655aab8..789822b5be9 100644 --- a/go/vt/vtctl/workflow/switcher.go +++ b/go/vt/vtctl/workflow/switcher.go @@ -20,6 +20,8 @@ import ( "context" "time" + "vitess.io/vitess/go/vt/topo" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" ) @@ -126,8 +128,8 @@ func (r *switcher) cancelMigration(ctx context.Context, sm *StreamMigrator) { r.ts.cancelMigration(ctx, sm) } -func (r *switcher) lockKeyspace(ctx context.Context, keyspace, action string) (context.Context, func(*error), error) { - return r.s.ts.LockKeyspace(ctx, keyspace, action) +func (r *switcher) lockKeyspace(ctx context.Context, keyspace, action string, opts ...topo.LockOption) (context.Context, func(*error), error) { + return r.s.ts.LockKeyspace(ctx, keyspace, action, opts...) } func (r *switcher) freezeTargetVReplication(ctx context.Context) error { @@ -161,3 +163,7 @@ func (r *switcher) resetSequences(ctx context.Context) error { func (r *switcher) initializeTargetSequences(ctx context.Context, sequencesByBackingTable map[string]*sequenceMetadata) error { return r.ts.initializeTargetSequences(ctx, sequencesByBackingTable) } + +func (r *switcher) mirrorTableTraffic(ctx context.Context, types []topodatapb.TabletType, percent float32) error { + return r.ts.mirrorTableTraffic(ctx, types, percent) +} diff --git a/go/vt/vtctl/workflow/switcher_dry_run.go b/go/vt/vtctl/workflow/switcher_dry_run.go index b8b1369bdf7..29c40f85a69 100644 --- a/go/vt/vtctl/workflow/switcher_dry_run.go +++ b/go/vt/vtctl/workflow/switcher_dry_run.go @@ -27,6 +27,7 @@ import ( "golang.org/x/exp/maps" "vitess.io/vitess/go/mysql/replication" + "vitess.io/vitess/go/vt/topo" binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" topodatapb "vitess.io/vitess/go/vt/proto/topodata" @@ -63,6 +64,17 @@ func (dr *switcherDryRun) deleteKeyspaceRoutingRules(ctx context.Context) error return nil } +func (dr *switcherDryRun) mirrorTableTraffic(ctx context.Context, types []topodatapb.TabletType, percent float32) error { + var tabletTypes []string + for _, servedType := range types { + tabletTypes = append(tabletTypes, servedType.String()) + } + dr.drLog.Logf("Mirroring %.2f percent of traffic from keyspace %s to keyspace %s for tablet types [%s]", + percent, dr.ts.SourceKeyspaceName(), dr.ts.TargetKeyspaceName(), strings.Join(tabletTypes, ",")) + + return nil +} + func (dr *switcherDryRun) switchKeyspaceReads(ctx context.Context, types []topodatapb.TabletType) error { var tabletTypes []string for _, servedType := range types { @@ -293,7 +305,7 @@ func (dr *switcherDryRun) cancelMigration(ctx context.Context, sm *StreamMigrato dr.drLog.Log("Cancel migration as requested") } -func (dr *switcherDryRun) lockKeyspace(ctx context.Context, keyspace, _ string) (context.Context, func(*error), error) { +func (dr *switcherDryRun) lockKeyspace(ctx context.Context, keyspace, _ string, _ ...topo.LockOption) (context.Context, func(*error), error) { dr.drLog.Logf("Lock keyspace %s", keyspace) return ctx, func(e *error) { dr.drLog.Logf("Unlock keyspace %s", keyspace) diff --git a/go/vt/vtctl/workflow/switcher_interface.go b/go/vt/vtctl/workflow/switcher_interface.go index 0780aaf484c..560b7a695fd 100644 --- a/go/vt/vtctl/workflow/switcher_interface.go +++ b/go/vt/vtctl/workflow/switcher_interface.go @@ -20,11 +20,13 @@ import ( "context" "time" + "vitess.io/vitess/go/vt/topo" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" ) type iswitcher interface { - lockKeyspace(ctx context.Context, keyspace, action string) (context.Context, func(*error), error) + lockKeyspace(ctx context.Context, keyspace, action string, opts ...topo.LockOption) (context.Context, func(*error), error) cancelMigration(ctx context.Context, sm *StreamMigrator) stopStreams(ctx context.Context, sm *StreamMigrator) ([]string, error) stopSourceWrites(ctx context.Context) error @@ -34,6 +36,7 @@ type iswitcher interface { createJournals(ctx context.Context, sourceWorkflows []string) error allowTargetWrites(ctx context.Context) error changeRouting(ctx context.Context) error + mirrorTableTraffic(ctx context.Context, types []topodatapb.TabletType, percent float32) error streamMigraterfinalize(ctx context.Context, ts *trafficSwitcher, workflows []string) error startReverseVReplication(ctx context.Context) error switchKeyspaceReads(ctx context.Context, types []topodatapb.TabletType) error diff --git a/go/vt/vtctl/workflow/traffic_switcher.go b/go/vt/vtctl/workflow/traffic_switcher.go index 7511315af15..c9d9952ef8f 100644 --- a/go/vt/vtctl/workflow/traffic_switcher.go +++ b/go/vt/vtctl/workflow/traffic_switcher.go @@ -353,7 +353,7 @@ func (ts *trafficSwitcher) getSourceAndTargetShardsNames() ([]string, []string) return sourceShards, targetShards } -// isPartialMoveTables returns true if whe workflow is MoveTables, has the same +// isPartialMoveTables returns true if the workflow is MoveTables, has the same // number of shards, is not covering the entire shard range, and has one-to-one // shards in source and target. func (ts *trafficSwitcher) isPartialMoveTables(sourceShards, targetShards []string) (bool, error) { @@ -390,7 +390,7 @@ func (ts *trafficSwitcher) addParticipatingTablesToKeyspace(ctx context.Context, if strings.HasPrefix(tableSpecs, "{") { // user defined the vschema snippet, typically for a sharded target wrap := fmt.Sprintf(`{"tables": %s}`, tableSpecs) ks := &vschemapb.Keyspace{} - if err := json2.Unmarshal([]byte(wrap), ks); err != nil { + if err := json2.UnmarshalPB([]byte(wrap), ks); err != nil { return err } for table, vtab := range ks.Tables { @@ -1745,3 +1745,48 @@ func (ts *trafficSwitcher) IsMultiTenantMigration() bool { } return false } + +func (ts *trafficSwitcher) mirrorTableTraffic(ctx context.Context, types []topodatapb.TabletType, percent float32) error { + mrs, err := topotools.GetMirrorRules(ctx, ts.TopoServer()) + if err != nil { + return err + } + + var numExisting int + for _, table := range ts.tables { + for _, tabletType := range types { + fromTable := fmt.Sprintf("%s.%s", ts.SourceKeyspaceName(), table) + if tabletType != topodatapb.TabletType_PRIMARY { + fromTable = fmt.Sprintf("%s@%s", fromTable, topoproto.TabletTypeLString(tabletType)) + } + toTable := fmt.Sprintf("%s.%s", ts.TargetKeyspaceName(), table) + + if _, ok := mrs[fromTable]; !ok { + mrs[fromTable] = make(map[string]float32) + } + + if _, ok := mrs[fromTable][toTable]; ok { + numExisting++ + } + + if percent == 0 { + // When percent is 0, remove mirror rule if it exists. + if _, ok := mrs[fromTable][toTable]; ok { + delete(mrs, fromTable) + } + } else { + mrs[fromTable][toTable] = percent + } + } + } + + if numExisting > 0 && numExisting != (len(types)*len(ts.tables)) { + return vterrors.Errorf(vtrpcpb.Code_ALREADY_EXISTS, "wrong number of pre-existing mirror rules") + } + + if err := topotools.SaveMirrorRules(ctx, ts.TopoServer(), mrs); err != nil { + return err + } + + return ts.TopoServer().RebuildSrvVSchema(ctx, nil) +} diff --git a/go/vt/vtctl/workflow/utils_test.go b/go/vt/vtctl/workflow/utils_test.go index e63ae00aa19..d79c4710b77 100644 --- a/go/vt/vtctl/workflow/utils_test.go +++ b/go/vt/vtctl/workflow/utils_test.go @@ -4,7 +4,7 @@ import ( "context" "fmt" "math" - "math/rand" + "math/rand/v2" "os" "os/exec" "sync" @@ -103,7 +103,7 @@ func testConcurrentKeyspaceRoutingRulesUpdates(t *testing.T, ctx context.Context func update(t *testing.T, ts *topo.Server, id int) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - s := fmt.Sprintf("%d_%d", id, rand.Intn(math.MaxInt)) + s := fmt.Sprintf("%d_%d", id, rand.IntN(math.MaxInt)) routes := make(map[string]string) for _, tabletType := range tabletTypeSuffixes { from := fmt.Sprintf("from%s%s", s, tabletType) diff --git a/go/vt/vterrors/state.go b/go/vt/vterrors/state.go index 8223405fc92..82434df382a 100644 --- a/go/vt/vterrors/state.go +++ b/go/vt/vterrors/state.go @@ -120,6 +120,8 @@ const ( CharacterSetMismatch WrongParametersToNativeFct + VectorConversion + // No state should be added below NumOfStates NumOfStates ) diff --git a/go/vt/vtexplain/testdata/twopc-output/unsharded-output.txt b/go/vt/vtexplain/testdata/twopc-output/unsharded-output.txt index 0db31f10110..b7299002d01 100644 --- a/go/vt/vtexplain/testdata/twopc-output/unsharded-output.txt +++ b/go/vt/vtexplain/testdata/twopc-output/unsharded-output.txt @@ -45,4 +45,4 @@ insert into t1 (id,intval,floatval) values (1,2,3.14) on duplicate key update in 1 ks_unsharded/-: insert into t1(id, intval, floatval) values (1, 2, 3.14) on duplicate key update intval = 3, floatval = 3.14 2 ks_unsharded/-: commit ----------------------------------------------------------------------- +---------------------------------------------------------------------- \ No newline at end of file diff --git a/go/vt/vtexplain/vtexplain_vtgate.go b/go/vt/vtexplain/vtexplain_vtgate.go index 22939efde20..d511e2d2ea0 100644 --- a/go/vt/vtexplain/vtexplain_vtgate.go +++ b/go/vt/vtexplain/vtexplain_vtgate.go @@ -101,7 +101,7 @@ func (vte *VTExplain) buildTopology(ctx context.Context, ts *topo.Server, opts * // handle string->enum conversion correctly. var srvVSchema vschemapb.SrvVSchema wrappedStr := fmt.Sprintf(`{"keyspaces": %s}`, vschemaStr) - err := json2.Unmarshal([]byte(wrappedStr), &srvVSchema) + err := json2.UnmarshalPB([]byte(wrappedStr), &srvVSchema) if err != nil { return err } diff --git a/go/vt/vtexplain/vtexplain_vttablet.go b/go/vt/vtexplain/vtexplain_vttablet.go index 3f9aee0efa3..ed977e7bcb0 100644 --- a/go/vt/vtexplain/vtexplain_vttablet.go +++ b/go/vt/vtexplain/vtexplain_vttablet.go @@ -113,7 +113,6 @@ func (vte *VTExplain) newTablet(ctx context.Context, env *vtenv.Environment, opt config := tabletenv.NewCurrentConfig() config.TrackSchemaVersions = false if opts.ExecutionMode == ModeTwoPC { - config.TwoPCCoordinatorAddress = "XXX" config.TwoPCAbandonAge = 1.0 config.TwoPCEnable = true } diff --git a/go/vt/vtgate/debug_2pc.go b/go/vt/vtgate/debug_2pc.go new file mode 100644 index 00000000000..f31f1413007 --- /dev/null +++ b/go/vt/vtgate/debug_2pc.go @@ -0,0 +1,21 @@ +//go:build debug2PC + +/* +Copyright 2024 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 vtgate + +const DebugTwoPc = true diff --git a/go/vt/vtgate/engine/aggregations.go b/go/vt/vtgate/engine/aggregations.go index 4673a2717e5..769df332b73 100644 --- a/go/vt/vtgate/engine/aggregations.go +++ b/go/vt/vtgate/engine/aggregations.go @@ -42,8 +42,8 @@ type AggregateParams struct { WCol int Type evalengine.Type - Alias string `json:",omitempty"` - Expr sqlparser.Expr + Alias string + Func sqlparser.AggrFunc Original *sqlparser.AliasedExpr // This is based on the function passed in the select expression and @@ -255,8 +255,9 @@ func (a *aggregatorScalar) reset() { } type aggregatorGroupConcat struct { - from int - type_ sqltypes.Type + from int + type_ sqltypes.Type + separator []byte concat []byte n int @@ -267,7 +268,7 @@ func (a *aggregatorGroupConcat) add(row []sqltypes.Value) error { return nil } if a.n > 0 { - a.concat = append(a.concat, ',') + a.concat = append(a.concat, a.separator...) } a.concat = append(a.concat, row[a.from].Raw()...) a.n++ @@ -346,7 +347,8 @@ func isComparable(typ sqltypes.Type) bool { sqltypes.Enum, sqltypes.Set, sqltypes.TypeJSON, - sqltypes.Bit: + sqltypes.Bit, + sqltypes.Vector: return true } return false @@ -434,7 +436,13 @@ func newAggregation(fields []*querypb.Field, aggregates []*AggregateParams) (agg ag = &aggregatorScalar{from: aggr.Col} case AggregateGroupConcat: - ag = &aggregatorGroupConcat{from: aggr.Col, type_: targetType} + gcFunc := aggr.Func.(*sqlparser.GroupConcatExpr) + separator := []byte(gcFunc.Separator) + ag = &aggregatorGroupConcat{ + from: aggr.Col, + type_: targetType, + separator: separator, + } default: panic("BUG: unexpected Aggregation opcode") diff --git a/go/vt/vtgate/engine/cached_size.go b/go/vt/vtgate/engine/cached_size.go index e65ff61a9f6..af9780fe001 100644 --- a/go/vt/vtgate/engine/cached_size.go +++ b/go/vt/vtgate/engine/cached_size.go @@ -41,8 +41,8 @@ func (cached *AggregateParams) CachedSize(alloc bool) int64 { size += cached.Type.CachedSize(false) // field Alias string size += hack.RuntimeAllocSize(int64(len(cached.Alias))) - // field Expr vitess.io/vitess/go/vt/sqlparser.Expr - if cc, ok := cached.Expr.(cachedObject); ok { + // field Func vitess.io/vitess/go/vt/sqlparser.AggrFunc + if cc, ok := cached.Func.(cachedObject); ok { size += cc.CachedSize(true) } // field Original *vitess.io/vitess/go/vt/sqlparser.AliasedExpr @@ -1293,6 +1293,18 @@ func (cached *ThrottleApp) CachedSize(alloc bool) int64 { size += cached.ThrottledAppRule.CachedSize(true) return size } +func (cached *TransactionStatus) CachedSize(alloc bool) int64 { + if cached == nil { + return int64(0) + } + size := int64(0) + if alloc { + size += int64(16) + } + // field TransactionID string + size += hack.RuntimeAllocSize(int64(len(cached.TransactionID))) + return size +} func (cached *UncorrelatedSubquery) CachedSize(alloc bool) int64 { if cached == nil { return int64(0) diff --git a/go/vt/vtgate/engine/fake_vcursor_test.go b/go/vt/vtgate/engine/fake_vcursor_test.go index 1ba0abfa2ef..adc425c0632 100644 --- a/go/vt/vtgate/engine/fake_vcursor_test.go +++ b/go/vt/vtgate/engine/fake_vcursor_test.go @@ -112,6 +112,10 @@ func (t *noopVCursor) CloneForReplicaWarming(ctx context.Context) VCursor { panic("implement me") } +func (t *noopVCursor) ReadTransaction(ctx context.Context, transactionID string) (*querypb.TransactionMetadata, error) { + panic("implement me") +} + func (t *noopVCursor) SetExec(ctx context.Context, name string, value string) error { panic("implement me") } @@ -397,7 +401,8 @@ type loggingVCursor struct { curResult int resultErr error - warnings []*querypb.QueryWarning + warnings []*querypb.QueryWarning + transactionStatusOutput *querypb.TransactionMetadata // Optional errors that can be returned from nextResult() alongside the results for // multi-shard queries @@ -814,6 +819,13 @@ func (f *loggingVCursor) CanUseSetVar() bool { return useSetVar } +func (f *loggingVCursor) ReadTransaction(_ context.Context, _ string) (*querypb.TransactionMetadata, error) { + if f.resultErr != nil { + return nil, f.resultErr + } + return f.transactionStatusOutput, nil +} + // SQLParser implements VCursor func (t *loggingVCursor) SQLParser() *sqlparser.Parser { if t.parser == nil { diff --git a/go/vt/vtgate/engine/hash_join.go b/go/vt/vtgate/engine/hash_join.go index 6ac34e1ab79..6b9425a35d1 100644 --- a/go/vt/vtgate/engine/hash_join.go +++ b/go/vt/vtgate/engine/hash_join.go @@ -44,7 +44,7 @@ type ( // Left and Right are the LHS and RHS primitives // of the Join. They can be any primitive. - Left, Right Primitive `json:",omitempty"` + Left, Right Primitive // Cols defines which columns from the left // or right results should be used to build the @@ -53,7 +53,7 @@ type ( // For the right query, they're 1, 2, etc. // If Cols is {-1, -2, 1, 2}, it means that // the returned result will be {Left0, Left1, Right0, Right1}. - Cols []int `json:",omitempty"` + Cols []int // The keys correspond to the column offset in the inputs where // the join columns can be found diff --git a/go/vt/vtgate/engine/join.go b/go/vt/vtgate/engine/join.go index dc952673cfe..51976396cba 100644 --- a/go/vt/vtgate/engine/join.go +++ b/go/vt/vtgate/engine/join.go @@ -35,7 +35,7 @@ type Join struct { Opcode JoinOpcode // Left and Right are the LHS and RHS primitives // of the Join. They can be any primitive. - Left, Right Primitive `json:",omitempty"` + Left, Right Primitive // Cols defines which columns from the left // or right results should be used to build the @@ -44,12 +44,12 @@ type Join struct { // For the right query, they're 1, 2, etc. // If Cols is {-1, -2, 1, 2}, it means that // the returned result will be {Left0, Left1, Right0, Right1}. - Cols []int `json:",omitempty"` + Cols []int // Vars defines the list of joinVars that need to // be built from the LHS result before invoking // the RHS subqquery. - Vars map[string]int `json:",omitempty"` + Vars map[string]int } // TryExecute performs a non-streaming exec. diff --git a/go/vt/vtgate/engine/memory_sort.go b/go/vt/vtgate/engine/memory_sort.go index d9919045eaf..03e66d0d033 100644 --- a/go/vt/vtgate/engine/memory_sort.go +++ b/go/vt/vtgate/engine/memory_sort.go @@ -41,7 +41,7 @@ type MemorySort struct { // TruncateColumnCount specifies the number of columns to return // in the final result. Rest of the columns are truncated // from the result received. If 0, no truncation happens. - TruncateColumnCount int `json:",omitempty"` + TruncateColumnCount int } // RouteType returns a description of the query routing type used by the primitive. diff --git a/go/vt/vtgate/engine/ordered_aggregate.go b/go/vt/vtgate/engine/ordered_aggregate.go index b67483216cf..324e531c4dd 100644 --- a/go/vt/vtgate/engine/ordered_aggregate.go +++ b/go/vt/vtgate/engine/ordered_aggregate.go @@ -47,7 +47,7 @@ type OrderedAggregate struct { // TruncateColumnCount specifies the number of columns to return // in the final result. Rest of the columns are truncated // from the result received. If 0, no truncation happens. - TruncateColumnCount int `json:",omitempty"` + TruncateColumnCount int // Input is the primitive that will feed into this Primitive. Input Primitive diff --git a/go/vt/vtgate/engine/ordered_aggregate_test.go b/go/vt/vtgate/engine/ordered_aggregate_test.go index 3eaa63819e4..c601654bced 100644 --- a/go/vt/vtgate/engine/ordered_aggregate_test.go +++ b/go/vt/vtgate/engine/ordered_aggregate_test.go @@ -22,6 +22,7 @@ import ( "fmt" "testing" + "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vtgate/evalengine" "github.com/stretchr/testify/assert" @@ -1058,8 +1059,10 @@ func TestGroupConcatWithAggrOnEngine(t *testing.T) { for _, tcase := range tcases { t.Run(tcase.name, func(t *testing.T) { fp := &fakePrimitive{results: []*sqltypes.Result{tcase.inputResult}} + agp := NewAggregateParam(AggregateGroupConcat, 1, "group_concat(c2)", collations.MySQL8()) + agp.Func = &sqlparser.GroupConcatExpr{Separator: ","} oa := &OrderedAggregate{ - Aggregates: []*AggregateParams{NewAggregateParam(AggregateGroupConcat, 1, "group_concat(c2)", collations.MySQL8())}, + Aggregates: []*AggregateParams{agp}, GroupByKeys: []*GroupByParams{{KeyCol: 0}}, Input: fp, } @@ -1137,8 +1140,10 @@ func TestGroupConcat(t *testing.T) { for _, tcase := range tcases { t.Run(tcase.name, func(t *testing.T) { fp := &fakePrimitive{results: []*sqltypes.Result{tcase.inputResult}} + agp := NewAggregateParam(AggregateGroupConcat, 1, "", collations.MySQL8()) + agp.Func = &sqlparser.GroupConcatExpr{Separator: ","} oa := &OrderedAggregate{ - Aggregates: []*AggregateParams{NewAggregateParam(AggregateGroupConcat, 1, "", collations.MySQL8())}, + Aggregates: []*AggregateParams{agp}, GroupByKeys: []*GroupByParams{{KeyCol: 0}}, Input: fp, } diff --git a/go/vt/vtgate/engine/primitive.go b/go/vt/vtgate/engine/primitive.go index 1c0e7de7a19..0c754a00342 100644 --- a/go/vt/vtgate/engine/primitive.go +++ b/go/vt/vtgate/engine/primitive.go @@ -131,6 +131,9 @@ type ( // CloneForReplicaWarming clones the VCursor for re-use in warming queries to replicas CloneForReplicaWarming(ctx context.Context) VCursor + + // ReadTransaction reads the state of the given transaction from the metadata manager + ReadTransaction(ctx context.Context, transactionID string) (*querypb.TransactionMetadata, error) } // SessionActions gives primitives ability to interact with the session state diff --git a/go/vt/vtgate/engine/revert_migration.go b/go/vt/vtgate/engine/revert_migration.go index a7690d07f42..2eb2af061a5 100644 --- a/go/vt/vtgate/engine/revert_migration.go +++ b/go/vt/vtgate/engine/revert_migration.go @@ -80,14 +80,12 @@ func (v *RevertMigration) TryExecute(ctx context.Context, vcursor VCursor, bindV Rows: [][]sqltypes.Value{}, } - sql := fmt.Sprintf("revert %s", v.Stmt.UUID) - ddlStrategySetting, err := schema.ParseDDLStrategy(vcursor.Session().GetDDLStrategy()) if err != nil { return nil, err } ddlStrategySetting.Strategy = schema.DDLStrategyOnline // and we keep the options as they were - onlineDDL, err := schema.NewOnlineDDL(v.GetKeyspaceName(), "", sql, ddlStrategySetting, fmt.Sprintf("vtgate:%s", vcursor.Session().GetSessionUUID()), "", vcursor.Environment().Parser()) + onlineDDL, err := schema.NewOnlineDDL(v.GetKeyspaceName(), "", v.Query, ddlStrategySetting, fmt.Sprintf("vtgate:%s", vcursor.Session().GetSessionUUID()), "", vcursor.Environment().Parser()) if err != nil { return result, err } diff --git a/go/vt/vtgate/engine/scalar_aggregation.go b/go/vt/vtgate/engine/scalar_aggregation.go index 929536b9cdf..e33204f5c58 100644 --- a/go/vt/vtgate/engine/scalar_aggregation.go +++ b/go/vt/vtgate/engine/scalar_aggregation.go @@ -35,7 +35,7 @@ type ScalarAggregate struct { // TruncateColumnCount specifies the number of columns to return // in the final result. Rest of the columns are truncated // from the result received. If 0, no truncation happens. - TruncateColumnCount int `json:",omitempty"` + TruncateColumnCount int // Input is the primitive that will feed into this Primitive. Input Primitive diff --git a/go/vt/vtgate/engine/scalar_aggregation_test.go b/go/vt/vtgate/engine/scalar_aggregation_test.go index 99031c95f34..6fa0c8aecb8 100644 --- a/go/vt/vtgate/engine/scalar_aggregation_test.go +++ b/go/vt/vtgate/engine/scalar_aggregation_test.go @@ -27,6 +27,7 @@ import ( "vitess.io/vitess/go/mysql/collations" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/test/utils" + "vitess.io/vitess/go/vt/sqlparser" . "vitess.io/vitess/go/vt/vtgate/engine/opcode" ) @@ -233,6 +234,7 @@ func TestScalarGroupConcatWithAggrOnEngine(t *testing.T) { Opcode: AggregateGroupConcat, Col: 0, Alias: "group_concat(c2)", + Func: &sqlparser.GroupConcatExpr{Separator: ","}, }}, Input: fp, } @@ -394,6 +396,7 @@ func TestScalarGroupConcat(t *testing.T) { Aggregates: []*AggregateParams{{ Opcode: AggregateGroupConcat, Col: 0, + Func: &sqlparser.GroupConcatExpr{Separator: ","}, }}, Input: fp, } diff --git a/go/vt/vtgate/engine/semi_join.go b/go/vt/vtgate/engine/semi_join.go index de8eeef5a32..f0dd0d09033 100644 --- a/go/vt/vtgate/engine/semi_join.go +++ b/go/vt/vtgate/engine/semi_join.go @@ -29,12 +29,12 @@ var _ Primitive = (*SemiJoin)(nil) type SemiJoin struct { // Left and Right are the LHS and RHS primitives // of the SemiJoin. They can be any primitive. - Left, Right Primitive `json:",omitempty"` + Left, Right Primitive // Vars defines the list of SemiJoinVars that need to // be built from the LHS result before invoking // the RHS subquery. - Vars map[string]int `json:",omitempty"` + Vars map[string]int } // TryExecute performs a non-streaming exec. diff --git a/go/vt/vtgate/engine/transaction_status.go b/go/vt/vtgate/engine/transaction_status.go new file mode 100644 index 00000000000..a087db08256 --- /dev/null +++ b/go/vt/vtgate/engine/transaction_status.go @@ -0,0 +1,117 @@ +/* +Copyright 2024 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" + "fmt" + "strings" + "time" + + "vitess.io/vitess/go/sqltypes" + querypb "vitess.io/vitess/go/vt/proto/query" +) + +var _ Primitive = (*TransactionStatus)(nil) + +// TransactionStatus is a primitive to call into executor via vcursor. +type TransactionStatus struct { + noInputs + noTxNeeded + + TransactionID string +} + +func (t *TransactionStatus) RouteType() string { + return "TransactionStatus" +} + +func (t *TransactionStatus) GetKeyspaceName() string { + return "" +} + +func (t *TransactionStatus) GetTableName() string { + return "" +} + +func (t *TransactionStatus) GetFields(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable) (*sqltypes.Result, error) { + return &sqltypes.Result{ + Fields: t.getFields(), + }, nil +} + +func (t *TransactionStatus) getFields() []*querypb.Field { + return []*querypb.Field{ + { + Name: "id", + Type: sqltypes.VarChar, + }, + { + Name: "state", + Type: sqltypes.VarChar, + }, + { + Name: "record_time", + Type: sqltypes.Datetime, + }, + { + Name: "participants", + Type: sqltypes.VarChar, + }, + } +} + +func (t *TransactionStatus) TryExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool) (*sqltypes.Result, error) { + transactionState, err := vcursor.ReadTransaction(ctx, t.TransactionID) + if err != nil { + return nil, err + } + res := &sqltypes.Result{} + if wantfields { + res.Fields = t.getFields() + } + if transactionState != nil { + var participantString []string + for _, participant := range transactionState.Participants { + participantString = append(participantString, fmt.Sprintf("%s:%s", participant.Keyspace, participant.Shard)) + } + res.Rows = append(res.Rows, sqltypes.Row{ + sqltypes.NewVarChar(transactionState.Dtid), + sqltypes.NewVarChar(transactionState.State.String()), + sqltypes.NewDatetime(time.Unix(0, transactionState.TimeCreated).UTC().String()), + sqltypes.NewVarChar(strings.Join(participantString, ",")), + }) + } + return res, nil +} + +func (t *TransactionStatus) TryStreamExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool, callback func(*sqltypes.Result) error) error { + res, err := t.TryExecute(ctx, vcursor, bindVars, wantfields) + if err != nil { + return err + } + return callback(res) +} + +func (t *TransactionStatus) description() PrimitiveDescription { + return PrimitiveDescription{ + OperatorType: "TransactionStatus", + Other: map[string]any{ + "TransactionID": t.TransactionID, + }, + } +} diff --git a/go/vt/vtgate/engine/transaction_status_test.go b/go/vt/vtgate/engine/transaction_status_test.go new file mode 100644 index 00000000000..5e4e95be8ef --- /dev/null +++ b/go/vt/vtgate/engine/transaction_status_test.go @@ -0,0 +1,89 @@ +/* +Copyright 2024 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" + "fmt" + "testing" + + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/sqltypes" + querypb "vitess.io/vitess/go/vt/proto/query" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" +) + +// TestTransactionStatusOutput tests the output and the fields of the transaction state query engine. +func TestTransactionStatusOutput(t *testing.T) { + tests := []struct { + name string + transactionStatusOutput *querypb.TransactionMetadata + resultErr error + expectedRes *sqltypes.Result + }{ + { + name: "Empty Transaction Status", + transactionStatusOutput: nil, + expectedRes: sqltypes.MakeTestResult(sqltypes.MakeTestFields("id|state|record_time|participants", "varchar|varchar|datetime|varchar")), + }, { + name: "Valid Transaction Status", + transactionStatusOutput: &querypb.TransactionMetadata{ + Dtid: "ks:-80:v24s7843sf78934l3", + State: querypb.TransactionState_PREPARE, + TimeCreated: 1257894000000000000, + Participants: []*querypb.Target{ + { + Keyspace: "ks", + Shard: "-80", + TabletType: topodatapb.TabletType_PRIMARY, + }, { + Keyspace: "ks", + Shard: "80-a0", + TabletType: topodatapb.TabletType_PRIMARY, + }, { + Keyspace: "ks", + Shard: "a0-", + TabletType: topodatapb.TabletType_PRIMARY, + }, + }, + }, + expectedRes: sqltypes.MakeTestResult( + sqltypes.MakeTestFields("id|state|record_time|participants", "varchar|varchar|datetime|varchar"), + "ks:-80:v24s7843sf78934l3|PREPARE|2009-11-10 23:00:00 +0000 UTC|ks:-80,ks:80-a0,ks:a0-"), + }, { + name: "Error getting transaction metadata", + resultErr: fmt.Errorf("failed reading transaction state"), + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + ts := &TransactionStatus{} + res, err := ts.TryExecute(context.Background(), &loggingVCursor{ + transactionStatusOutput: test.transactionStatusOutput, + resultErr: test.resultErr, + }, nil, true) + if test.resultErr != nil { + require.EqualError(t, err, test.resultErr.Error()) + return + } + require.NoError(t, err) + expectResult(t, res, test.expectedRes) + }) + } +} diff --git a/go/vt/vtgate/evalengine/api_coerce.go b/go/vt/vtgate/evalengine/api_coerce.go index eef83c58422..f26ba5ea758 100644 --- a/go/vt/vtgate/evalengine/api_coerce.go +++ b/go/vt/vtgate/evalengine/api_coerce.go @@ -24,7 +24,7 @@ import ( ) func CoerceTo(value sqltypes.Value, typ Type, sqlmode SQLMode) (sqltypes.Value, error) { - cast, err := valueToEvalCast(value, value.Type(), collations.Unknown, typ.values, sqlmode) + cast, err := valueToEvalCast(value, value.Type(), typ.collation, typ.values, sqlmode) if err != nil { return sqltypes.Value{}, err } diff --git a/go/vt/vtgate/evalengine/cached_size.go b/go/vt/vtgate/evalengine/cached_size.go index 65f0bd37d12..6f447f0d1c1 100644 --- a/go/vt/vtgate/evalengine/cached_size.go +++ b/go/vt/vtgate/evalengine/cached_size.go @@ -2068,6 +2068,16 @@ func (cached *evalUint64) CachedSize(alloc bool) int64 { } return size } +func (cached *evalYear) CachedSize(alloc bool) int64 { + if cached == nil { + return int64(0) + } + size := int64(0) + if alloc { + size += int64(16) + } + return size +} func (cached *typedExpr) CachedSize(alloc bool) int64 { if cached == nil { return int64(0) diff --git a/go/vt/vtgate/evalengine/compiler.go b/go/vt/vtgate/evalengine/compiler.go index bcb2281f1a6..b0a7edd285d 100644 --- a/go/vt/vtgate/evalengine/compiler.go +++ b/go/vt/vtgate/evalengine/compiler.go @@ -81,6 +81,10 @@ func (v *EnumSetValues) Equal(other *EnumSetValues) bool { return slices.Equal(*v, *other) } +func NewUnknownType() Type { + return NewType(sqltypes.Unknown, collations.Unknown) +} + func NewType(t sqltypes.Type, collation collations.ID) Type { // New types default to being nullable return NewTypeEx(t, collation, true, 0, 0, nil) diff --git a/go/vt/vtgate/evalengine/compiler_asm.go b/go/vt/vtgate/evalengine/compiler_asm.go index 6c8896bb1f4..0cac66d9e5e 100644 --- a/go/vt/vtgate/evalengine/compiler_asm.go +++ b/go/vt/vtgate/evalengine/compiler_asm.go @@ -2670,15 +2670,22 @@ func (asm *assembler) Fn_MULTICMP_u(args int, lessThan bool) { }, "FN MULTICMP UINT64(SP-%d)...UINT64(SP-1)", args) } -func (asm *assembler) Fn_REPEAT() { +func (asm *assembler) Fn_REPEAT(base sqltypes.Type, fallback sqltypes.Type) { asm.adjustStack(-1) asm.emit(func(env *ExpressionEnv) int { str := env.vm.stack[env.vm.sp-2].(*evalBytes) repeat := env.vm.stack[env.vm.sp-1].(*evalInt64) + if len(str.bytes) == 0 { + str.bytes = nil + env.vm.sp-- + return 1 + } + negative := false if repeat.i < 0 { repeat.i = 0 + negative = true } if !validMaxLength(int64(len(str.bytes)), repeat.i) { @@ -2687,8 +2694,12 @@ func (asm *assembler) Fn_REPEAT() { return 1 } - str.tt = int16(sqltypes.VarChar) str.bytes = bytes.Repeat(str.bytes, int(repeat.i)) + if len(str.bytes) >= repeatTypeChangeLength || negative { + str.tt = int16(fallback) + } else { + str.tt = int16(base) + } env.vm.sp-- return 1 }, "FN REPEAT VARCHAR(SP-2) INT64(SP-1)") @@ -4238,15 +4249,26 @@ func (asm *assembler) Fn_WEEKOFYEAR() { }, "FN WEEKOFYEAR DATE(SP-1)") } -func (asm *assembler) Fn_YEAR() { - asm.emit(func(env *ExpressionEnv) int { - if env.vm.stack[env.vm.sp-1] == nil { +func (asm *assembler) Fn_YEAR(yearType bool) { + if yearType { + asm.emit(func(env *ExpressionEnv) int { + if env.vm.stack[env.vm.sp-1] == nil { + return 1 + } + arg := env.vm.stack[env.vm.sp-1].(*evalTemporal) + env.vm.stack[env.vm.sp-1] = newEvalYear(int64(arg.dt.Date.Year())) return 1 - } - arg := env.vm.stack[env.vm.sp-1].(*evalTemporal) - env.vm.stack[env.vm.sp-1] = env.vm.arena.newEvalInt64(int64(arg.dt.Date.Year())) - return 1 - }, "FN YEAR DATE(SP-1)") + }, "FN YEAR DATE(SP-1)") + } else { + asm.emit(func(env *ExpressionEnv) int { + if env.vm.stack[env.vm.sp-1] == nil { + return 1 + } + arg := env.vm.stack[env.vm.sp-1].(*evalTemporal) + env.vm.stack[env.vm.sp-1] = env.vm.arena.newEvalInt64(int64(arg.dt.Date.Year())) + return 1 + }, "FN YEAR DATE(SP-1)") + } } func (asm *assembler) Fn_YEARWEEK0() { diff --git a/go/vt/vtgate/evalengine/compiler_asm_push.go b/go/vt/vtgate/evalengine/compiler_asm_push.go index 87d2ee9af9b..8f2b5d9f28b 100644 --- a/go/vt/vtgate/evalengine/compiler_asm_push.go +++ b/go/vt/vtgate/evalengine/compiler_asm_push.go @@ -97,6 +97,36 @@ func (asm *assembler) PushBVar_bin(key string) { }, "PUSH VARBINARY(:%q)", key) } +func push_vector(env *ExpressionEnv, raw []byte) int { + env.vm.stack[env.vm.sp] = newEvalVector(raw) + env.vm.sp++ + return 1 +} + +func (asm *assembler) PushColumn_vector(offset int) { + asm.adjustStack(1) + asm.emit(func(env *ExpressionEnv) int { + col := env.Row[offset] + if col.IsNull() { + return push_null(env) + } + return push_vector(env, col.Raw()) + }, "PUSH VECTOR(:%d)", offset) +} + +func (asm *assembler) PushBVar_vector(key string) { + asm.adjustStack(1) + + asm.emit(func(env *ExpressionEnv) int { + var bvar *querypb.BindVariable + bvar, env.vm.err = env.lookupBindVar(key) + if env.vm.err != nil { + return 0 + } + return push_vector(env, bvar.Value) + }, "PUSH VECTOR(:%q)", key) +} + func push_d(env *ExpressionEnv, raw []byte) int { var dec decimal.Decimal dec, env.vm.err = decimal.NewFromMySQL(raw) diff --git a/go/vt/vtgate/evalengine/eval.go b/go/vt/vtgate/evalengine/eval.go index 49423979379..916c5e200f4 100644 --- a/go/vt/vtgate/evalengine/eval.go +++ b/go/vt/vtgate/evalengine/eval.go @@ -394,6 +394,8 @@ func valueToEval(value sqltypes.Value, collation collations.TypedCollation, valu return newEvalEnum(value.Raw(), values), nil case tt == sqltypes.Set: return newEvalSet(value.Raw(), values), nil + case tt == sqltypes.Vector: + return newEvalVector(value.Raw()), nil case sqltypes.IsText(tt): if tt == sqltypes.HexNum { raw, err := parseHexNumber(value.Raw()) diff --git a/go/vt/vtgate/evalengine/eval_bytes.go b/go/vt/vtgate/evalengine/eval_bytes.go index 027c4bb652d..971c0f3c4a6 100644 --- a/go/vt/vtgate/evalengine/eval_bytes.go +++ b/go/vt/vtgate/evalengine/eval_bytes.go @@ -61,6 +61,10 @@ func newEvalText(raw []byte, col collations.TypedCollation) *evalBytes { return newEvalRaw(sqltypes.VarChar, raw, col) } +func newEvalVector(raw []byte) *evalBytes { + return newEvalRaw(sqltypes.Vector, raw, collationBinary) +} + func evalToBinary(e eval) *evalBytes { if e, ok := e.(*evalBytes); ok && e.isBinary() && !e.isHexOrBitLiteral() { return e diff --git a/go/vt/vtgate/evalengine/eval_numeric.go b/go/vt/vtgate/evalengine/eval_numeric.go index 04f844566b1..3ccdfde68fa 100644 --- a/go/vt/vtgate/evalengine/eval_numeric.go +++ b/go/vt/vtgate/evalengine/eval_numeric.go @@ -58,6 +58,10 @@ type ( dec decimal.Decimal length int32 } + + evalYear struct { + evalInt64 + } ) var _ evalNumeric = (*evalInt64)(nil) @@ -102,6 +106,10 @@ func newEvalBool(b bool) *evalInt64 { return evalBoolFalse } +func newEvalYear(i int64) *evalYear { + return &evalYear{evalInt64{i: i}} +} + func evalToNumeric(e eval, preciseDatetime bool) evalNumeric { switch e := e.(type) { case evalNumeric: @@ -616,3 +624,7 @@ func (e *evalDecimal) toUint64() *evalUint64 { } return newEvalUint64(u) } + +func (e *evalYear) SQLType() sqltypes.Type { + return sqltypes.Year +} diff --git a/go/vt/vtgate/evalengine/expr_bvar.go b/go/vt/vtgate/evalengine/expr_bvar.go index 0fffe3140a2..50f231dbe9c 100644 --- a/go/vt/vtgate/evalengine/expr_bvar.go +++ b/go/vt/vtgate/evalengine/expr_bvar.go @@ -83,9 +83,6 @@ func (bv *BindVariable) eval(env *ExpressionEnv) (eval, error) { return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "query argument '%s' cannot be a tuple", bv.Key) } typ := bvar.Type - if bv.typed() { - typ = bv.Type - } return valueToEval(sqltypes.MakeTrusted(typ, bvar.Value), typedCoercionCollation(typ, collations.CollationForType(typ, bv.Collation)), nil) } } @@ -163,6 +160,8 @@ func (bvar *BindVariable) compile(c *compiler) (ctype, error) { c.asm.PushBVar_date(bvar.Key) case tt == sqltypes.Time: c.asm.PushBVar_time(bvar.Key) + case tt == sqltypes.Vector: + c.asm.PushBVar_vector(bvar.Key) default: return ctype{}, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "Type is not supported: %s", tt) } diff --git a/go/vt/vtgate/evalengine/expr_column.go b/go/vt/vtgate/evalengine/expr_column.go index d53585ceb8b..e52c522d973 100644 --- a/go/vt/vtgate/evalengine/expr_column.go +++ b/go/vt/vtgate/evalengine/expr_column.go @@ -151,6 +151,8 @@ func (column *Column) compile(c *compiler) (ctype, error) { c.asm.PushColumn_date(column.Offset) case tt == sqltypes.Time: c.asm.PushColumn_time(column.Offset) + case tt == sqltypes.Vector: + c.asm.PushColumn_vector(column.Offset) default: return ctype{}, vterrors.Errorf(vtrpc.Code_UNIMPLEMENTED, "Type is not supported: %s", tt) } diff --git a/go/vt/vtgate/evalengine/expr_compare.go b/go/vt/vtgate/evalengine/expr_compare.go index f3bd44588ee..ce1e16af787 100644 --- a/go/vt/vtgate/evalengine/expr_compare.go +++ b/go/vt/vtgate/evalengine/expr_compare.go @@ -275,7 +275,7 @@ func evalCompare(left, right eval, collationEnv *collations.Environment) (comp i // TODO: Clean this up as we add more properly supported types and comparisons. func fallbackBinary(t sqltypes.Type) bool { switch t { - case sqltypes.Bit, sqltypes.Enum, sqltypes.Set, sqltypes.Geometry: + case sqltypes.Bit, sqltypes.Enum, sqltypes.Set, sqltypes.Geometry, sqltypes.Vector: return true } return false diff --git a/go/vt/vtgate/evalengine/fn_string.go b/go/vt/vtgate/evalengine/fn_string.go index 663475327e5..6d83d36412d 100644 --- a/go/vt/vtgate/evalengine/fn_string.go +++ b/go/vt/vtgate/evalengine/fn_string.go @@ -20,6 +20,7 @@ import ( "bytes" "math" + "vitess.io/vitess/go/mysql/capabilities" "vitess.io/vitess/go/mysql/collations" "vitess.io/vitess/go/mysql/collations/charset" "vitess.io/vitess/go/mysql/collations/colldata" @@ -889,6 +890,23 @@ func (call *builtinOrd) compile(c *compiler) (ctype, error) { // error: `ERROR 2020 (HY000): Got packet bigger than 'max_allowed_packet' bytes` and the client gets disconnected. // - `> max_allowed_packet`, no error and returns `NULL`. const maxRepeatLength = 1073741824 +const repeatTypeChangeLength = 16384 + +// repeatType returns the type for the REPEAT result. +// MySQL 8.1.x and later has changed this to return TEXT instead of VARCHAR. +func repeatType(version string, base sqltypes.Type) sqltypes.Type { + capability, _ := capabilities.ServerVersionAtLeast(version, 8, 1, 0) + if capability { + if sqltypes.IsBinary(base) { + return sqltypes.Blob + } + return sqltypes.Text + } + if sqltypes.IsBinary(base) { + return sqltypes.VarBinary + } + return sqltypes.VarChar +} func (call *builtinRepeat) eval(env *ExpressionEnv) (eval, error) { arg1, arg2, err := call.arg2(env) @@ -900,22 +918,36 @@ func (call *builtinRepeat) eval(env *ExpressionEnv) (eval, error) { } text, ok := arg1.(*evalBytes) - if !ok { + tt := sqltypes.VarChar + if ok { + tt = text.SQLType() + } else { text, err = evalToVarchar(arg1, call.collate, true) if err != nil { return nil, err } } + if len(text.bytes) == 0 { + return newEvalText(nil, text.col), nil + } + repeat := evalToInt64(arg2).i + negative := false if repeat < 0 { repeat = 0 + negative = true } if !validMaxLength(int64(len(text.bytes)), repeat) { return nil, nil } - return newEvalText(bytes.Repeat(text.bytes, int(repeat)), text.col), nil + b := bytes.Repeat(text.bytes, int(repeat)) + if len(b) >= repeatTypeChangeLength || negative { + tt = repeatType(env.currentVersion(), tt) + } + + return newEvalRaw(tt, b, text.col), nil } func validMaxLength(len, repeat int64) bool { @@ -942,14 +974,16 @@ func (expr *builtinRepeat) compile(c *compiler) (ctype, error) { skip := c.compileNullCheck2(str, repeat) + tt := sqltypes.VarChar switch { case str.isTextual(): + tt = str.Type default: c.asm.Convert_xc(2, sqltypes.VarChar, c.collation, nil) } _ = c.compileToInt64(repeat, 1) - c.asm.Fn_REPEAT() + c.asm.Fn_REPEAT(tt, repeatType(c.env.MySQLVersion(), tt)) c.asm.jumpDestination(skip) return ctype{Type: sqltypes.VarChar, Col: str.Col, Flag: flagNullable}, nil } diff --git a/go/vt/vtgate/evalengine/fn_time.go b/go/vt/vtgate/evalengine/fn_time.go index 5a253799b7f..8d920e9e135 100644 --- a/go/vt/vtgate/evalengine/fn_time.go +++ b/go/vt/vtgate/evalengine/fn_time.go @@ -21,6 +21,7 @@ import ( "time" "vitess.io/vitess/go/hack" + "vitess.io/vitess/go/mysql/capabilities" "vitess.io/vitess/go/mysql/collations" "vitess.io/vitess/go/mysql/datetime" "vitess.io/vitess/go/mysql/decimal" @@ -1859,6 +1860,11 @@ func (call *builtinWeekOfYear) compile(c *compiler) (ctype, error) { return ctype{Type: sqltypes.Int64, Col: collationNumeric, Flag: arg.Flag | flagNullable}, nil } +func yearType(version string) bool { + capability, _ := capabilities.ServerVersionAtLeast(version, 8, 1, 0) + return capability +} + func (b *builtinYear) eval(env *ExpressionEnv) (eval, error) { date, err := b.arg1(env) if err != nil { @@ -1872,6 +1878,9 @@ func (b *builtinYear) eval(env *ExpressionEnv) (eval, error) { return nil, nil } + if yearType(env.currentVersion()) { + return newEvalYear(int64(d.dt.Date.Year())), nil + } return newEvalInt64(int64(d.dt.Date.Year())), nil } @@ -1889,7 +1898,7 @@ func (call *builtinYear) compile(c *compiler) (ctype, error) { c.asm.Convert_xD(1, true) } - c.asm.Fn_YEAR() + c.asm.Fn_YEAR(yearType(c.env.MySQLVersion())) c.asm.jumpDestination(skip) return ctype{Type: sqltypes.Int64, Col: collationNumeric, Flag: arg.Flag | flagNullable}, nil } diff --git a/go/vt/vtgate/evalengine/testcases/cases.go b/go/vt/vtgate/evalengine/testcases/cases.go index c937e7dbbc0..003eb45c0a3 100644 --- a/go/vt/vtgate/evalengine/testcases/cases.go +++ b/go/vt/vtgate/evalengine/testcases/cases.go @@ -1960,6 +1960,9 @@ func FnMaketime(yield Query) { "''", "0", "'3'", "59", "60", "0xFF666F6F626172FF", "18446744073709551615", } for _, h := range inputConversions { + if !(bugs{}).MakeTimeValidHours(h) { + continue + } for _, m := range minutes { for _, s := range inputConversions { yield(fmt.Sprintf("MAKETIME(%s, %s, %s)", h, m, s), nil) diff --git a/go/vt/vtgate/evalengine/testcases/helpers.go b/go/vt/vtgate/evalengine/testcases/helpers.go index a908b8196c8..71602e12c1c 100644 --- a/go/vt/vtgate/evalengine/testcases/helpers.go +++ b/go/vt/vtgate/evalengine/testcases/helpers.go @@ -21,6 +21,7 @@ import ( "math" "reflect" "runtime" + "strconv" "strings" "time" @@ -134,6 +135,18 @@ func (bugs) CanCompare(elems ...string) bool { return true } +// MakeTimeValidHours returns true if the hour input for MAKETIME +// is not an invalid edge case. Starting with MySQL 8.4.0, it somehow +// truncates this value to a negative zero. This seems pretty much +// broken as other large negative values are not truncated. +func (bugs) MakeTimeValidHours(input string) bool { + i, err := strconv.ParseInt(input, 10, 64) + if err != nil { + return true + } + return i != math.MinInt64 +} + type Comparison struct { Decimals uint32 LooseTime bool diff --git a/go/vt/vtgate/executor.go b/go/vt/vtgate/executor.go index cec0dba8274..bc492dd0335 100644 --- a/go/vt/vtgate/executor.go +++ b/go/vt/vtgate/executor.go @@ -1619,6 +1619,10 @@ func (e *Executor) environment() *vtenv.Environment { return e.env } +func (e *Executor) ReadTransaction(ctx context.Context, transactionID string) (*querypb.TransactionMetadata, error) { + return e.txConn.ReadTransaction(ctx, transactionID) +} + type ( errorTransformer interface { TransformError(err error) error diff --git a/go/vt/vtgate/fakerpcvtgateconn/conn.go b/go/vt/vtgate/fakerpcvtgateconn/conn.go index 3f6236ea9ec..372ddfb8cfc 100644 --- a/go/vt/vtgate/fakerpcvtgateconn/conn.go +++ b/go/vt/vtgate/fakerpcvtgateconn/conn.go @@ -182,11 +182,6 @@ func (conn *FakeVTGateConn) CloseSession(ctx context.Context, session *vtgatepb. panic("not implemented") } -// ResolveTransaction please see vtgateconn.Impl.ResolveTransaction -func (conn *FakeVTGateConn) ResolveTransaction(ctx context.Context, dtid string) error { - return nil -} - // VStream streams binlog events. func (conn *FakeVTGateConn) VStream(ctx context.Context, tabletType topodatapb.TabletType, vgtid *binlogdatapb.VGtid, filter *binlogdatapb.Filter, flags *vtgatepb.VStreamFlags) (vtgateconn.VStreamReader, error) { diff --git a/go/vt/vtgate/grpcvtgateconn/conn.go b/go/vt/vtgate/grpcvtgateconn/conn.go index a681e3661cd..fa16fa0d602 100644 --- a/go/vt/vtgate/grpcvtgateconn/conn.go +++ b/go/vt/vtgate/grpcvtgateconn/conn.go @@ -234,15 +234,6 @@ func (conn *vtgateConn) CloseSession(ctx context.Context, session *vtgatepb.Sess return nil } -func (conn *vtgateConn) ResolveTransaction(ctx context.Context, dtid string) error { - request := &vtgatepb.ResolveTransactionRequest{ - CallerId: callerid.EffectiveCallerIDFromContext(ctx), - Dtid: dtid, - } - _, err := conn.c.ResolveTransaction(ctx, request) - return vterrors.FromGRPC(err) -} - type vstreamAdapter struct { stream vtgateservicepb.Vitess_VStreamClient } diff --git a/go/vt/vtgate/grpcvtgateconn/suite_test.go b/go/vt/vtgate/grpcvtgateconn/suite_test.go index e5cd5c3ac81..0e544b05e66 100644 --- a/go/vt/vtgate/grpcvtgateconn/suite_test.go +++ b/go/vt/vtgate/grpcvtgateconn/suite_test.go @@ -23,7 +23,6 @@ package grpcvtgateconn import ( "context" - "errors" "fmt" "io" "strings" @@ -231,21 +230,6 @@ func (f *fakeVTGateService) CloseSession(ctx context.Context, session *vtgatepb. panic("unimplemented") } -// ResolveTransaction is part of the VTGateService interface -func (f *fakeVTGateService) ResolveTransaction(ctx context.Context, dtid string) error { - if f.hasError { - return errTestVtGateError - } - if f.panics { - panic(fmt.Errorf("test forced panic")) - } - f.checkCallerID(ctx, "ResolveTransaction") - if dtid != dtid2 { - return errors.New("ResolveTransaction: dtid mismatch") - } - return nil -} - func (f *fakeVTGateService) VStream(ctx context.Context, tabletType topodatapb.TabletType, vgtid *binlogdatapb.VGtid, filter *binlogdatapb.Filter, flags *vtgatepb.VStreamFlags, send func([]*binlogdatapb.VEvent) error) error { panic("unimplemented") } diff --git a/go/vt/vtgate/grpcvtgateservice/server.go b/go/vt/vtgate/grpcvtgateservice/server.go index bf00db4ea1c..d9fef3d4e31 100644 --- a/go/vt/vtgate/grpcvtgateservice/server.go +++ b/go/vt/vtgate/grpcvtgateservice/server.go @@ -247,18 +247,6 @@ func (vtg *VTGate) CloseSession(ctx context.Context, request *vtgatepb.CloseSess }, nil } -// ResolveTransaction is the RPC version of vtgateservice.VTGateService method -func (vtg *VTGate) ResolveTransaction(ctx context.Context, request *vtgatepb.ResolveTransactionRequest) (response *vtgatepb.ResolveTransactionResponse, err error) { - defer vtg.server.HandlePanic(&err) - ctx = withCallerIDContext(ctx, request.CallerId) - vtgErr := vtg.server.ResolveTransaction(ctx, request.Dtid) - response = &vtgatepb.ResolveTransactionResponse{} - if vtgErr == nil { - return response, nil - } - return nil, vterrors.ToGRPC(vtgErr) -} - // VStream is the RPC version of vtgateservice.VTGateService method func (vtg *VTGate) VStream(request *vtgatepb.VStreamRequest, stream vtgateservicepb.Vitess_VStreamServer) (err error) { defer vtg.server.HandlePanic(&err) diff --git a/go/vt/vtgate/planbuilder/fuzz.go b/go/vt/vtgate/planbuilder/fuzz.go index 79dcca01a53..a3ce38bc0d0 100644 --- a/go/vt/vtgate/planbuilder/fuzz.go +++ b/go/vt/vtgate/planbuilder/fuzz.go @@ -37,7 +37,7 @@ func onceInit() { // loadSchemaForFuzzing is a helper to load *vindexes.VSchema // for fuzzing. func loadSchemaForFuzzing(f *fuzz.ConsumeFuzzer) (*vindexes.VSchema, error) { - //formal, err := vindexes.LoadFormal(filename) + // formal, err := vindexes.LoadFormal(filename) formal, err := loadFormalForFuzzing(f) if err != nil { return nil, err @@ -69,7 +69,7 @@ func loadFormalForFuzzing(f *fuzz.ConsumeFuzzer) (*vschemapb.SrvVSchema, error) if err != nil { return nil, err } - err = json2.Unmarshal(data, formal) + err = json2.UnmarshalPB(data, formal) if err != nil { return nil, err } diff --git a/go/vt/vtgate/planbuilder/operator_transformers.go b/go/vt/vtgate/planbuilder/operator_transformers.go index 60a59ed936a..546a9854f26 100644 --- a/go/vt/vtgate/planbuilder/operator_transformers.go +++ b/go/vt/vtgate/planbuilder/operator_transformers.go @@ -304,11 +304,19 @@ func transformAggregator(ctx *plancontext.PlanningContext, op *operators.Aggrega var groupByKeys []*engine.GroupByParams for _, aggr := range op.Aggregations { - if aggr.OpCode == opcode.AggregateUnassigned { + switch aggr.OpCode { + case opcode.AggregateUnassigned: return nil, vterrors.VT12001(fmt.Sprintf("in scatter query: aggregation function '%s'", sqlparser.String(aggr.Original))) + case opcode.AggregateUDF: + message := fmt.Sprintf("Aggregate UDF '%s' must be pushed down to MySQL", sqlparser.String(aggr.Original.Expr)) + return nil, vterrors.VT12001(message) } + aggrParam := engine.NewAggregateParam(aggr.OpCode, aggr.ColOffset, aggr.Alias, ctx.VSchema.Environment().CollationEnv()) - aggrParam.Expr = aggr.Func + aggrParam.Func = aggr.Func + if gcFunc, isGc := aggrParam.Func.(*sqlparser.GroupConcatExpr); isGc && gcFunc.Separator == "" { + gcFunc.Separator = sqlparser.GroupConcatDefaultSeparator + } aggrParam.Original = aggr.Original aggrParam.OrigOpcode = aggr.OriginalOpCode aggrParam.WCol = aggr.WSOffset diff --git a/go/vt/vtgate/planbuilder/operators/SQL_builder.go b/go/vt/vtgate/planbuilder/operators/SQL_builder.go index 0a2e545ea48..08cf3c4801c 100644 --- a/go/vt/vtgate/planbuilder/operators/SQL_builder.go +++ b/go/vt/vtgate/planbuilder/operators/SQL_builder.go @@ -96,7 +96,7 @@ func (qb *queryBuilder) addPredicate(expr sqlparser.Expr) { switch stmt := qb.stmt.(type) { case *sqlparser.Select: - if ContainsAggr(qb.ctx, expr) { + if qb.ctx.ContainsAggr(expr) { addPred = stmt.AddHaving } else { addPred = stmt.AddWhere @@ -233,7 +233,9 @@ func (qb *queryBuilder) joinWith(other *queryBuilder, onCondition sqlparser.Expr switch joinType { case sqlparser.NormalJoinType: newFromClause = append(stmt.GetFrom(), otherStmt.GetFrom()...) - qb.addPredicate(onCondition) + for _, pred := range sqlparser.SplitAndExpression(nil, onCondition) { + qb.addPredicate(pred) + } default: newFromClause = []sqlparser.TableExpr{buildJoin(stmt, otherStmt, onCondition, joinType)} } @@ -466,6 +468,14 @@ func buildAggregation(op *Aggregator, qb *queryBuilder) { if op.WithRollup { qb.setWithRollup() } + + if op.DT != nil { + sel := qb.asSelectStatement() + qb.stmt = nil + qb.addTableExpr(op.DT.Alias, op.DT.Alias, TableID(op), &sqlparser.DerivedTable{ + Select: sel, + }, nil, op.DT.Columns) + } } func buildOrdering(op *Ordering, qb *queryBuilder) { diff --git a/go/vt/vtgate/planbuilder/operators/aggregation_pushing.go b/go/vt/vtgate/planbuilder/operators/aggregation_pushing.go index 715e27ae9c7..671f4b78954 100644 --- a/go/vt/vtgate/planbuilder/operators/aggregation_pushing.go +++ b/go/vt/vtgate/planbuilder/operators/aggregation_pushing.go @@ -177,6 +177,7 @@ func pushAggregations(ctx *plancontext.PlanningContext, aggregator *Aggregator, if !aggr.Distinct || canPushDistinctAggr { aggrBelowRoute.Aggregations = append(aggrBelowRoute.Aggregations, aggr) aggregateTheAggregate(aggregator, i) + aggregator.Aggregations[i].PushedDown = true continue } @@ -369,7 +370,6 @@ func pushAggregationThroughApplyJoin(ctx *plancontext.PlanningContext, rootAggr columns := &applyJoinColumns{} output, err := splitAggrColumnsToLeftAndRight(ctx, rootAggr, join, !join.JoinType.IsInner(), columns, lhs, rhs) - join.JoinColumns = columns if err != nil { // if we get this error, we just abort the splitting and fall back on simpler ways of solving the same query if errors.Is(err, errAbortAggrPushing) { @@ -377,6 +377,7 @@ func pushAggregationThroughApplyJoin(ctx *plancontext.PlanningContext, rootAggr } panic(err) } + join.JoinColumns = columns splitGroupingToLeftAndRight(ctx, rootAggr, lhs, rhs, join.JoinColumns) diff --git a/go/vt/vtgate/planbuilder/operators/aggregation_pushing_helper.go b/go/vt/vtgate/planbuilder/operators/aggregation_pushing_helper.go index 2c47f426695..2fbf5c32311 100644 --- a/go/vt/vtgate/planbuilder/operators/aggregation_pushing_helper.go +++ b/go/vt/vtgate/planbuilder/operators/aggregation_pushing_helper.go @@ -134,8 +134,8 @@ func (ab *aggBuilder) handleAggr(ctx *plancontext.PlanningContext, aggr Aggr) er return ab.handlePushThroughAggregation(ctx, aggr) case opcode.AggregateGroupConcat: f := aggr.Func.(*sqlparser.GroupConcatExpr) - if f.Distinct || len(f.OrderBy) > 0 || f.Separator != "" { - panic("fail here") + if f.Distinct || len(f.OrderBy) > 0 { + panic(vterrors.VT12001("cannot evaluate group concat with distinct or order by")) } // this needs special handling, currently aborting the push of function // and later will try pushing the column instead. diff --git a/go/vt/vtgate/planbuilder/operators/aggregator.go b/go/vt/vtgate/planbuilder/operators/aggregator.go index 40ba20fe02d..bb969912f4f 100644 --- a/go/vt/vtgate/planbuilder/operators/aggregator.go +++ b/go/vt/vtgate/planbuilder/operators/aggregator.go @@ -101,7 +101,7 @@ func (a *Aggregator) addColumnWithoutPushing(ctx *plancontext.PlanningContext, e case sqlparser.AggrFunc: aggr = createAggrFromAggrFunc(e, expr) case *sqlparser.FuncExpr: - if IsAggr(ctx, e) { + if ctx.IsAggr(e) { aggr = NewAggr(opcode.AggregateUDF, nil, expr, expr.As.String()) } else { aggr = NewAggr(opcode.AggregateAnyValue, nil, expr, expr.As.String()) @@ -115,14 +115,6 @@ func (a *Aggregator) addColumnWithoutPushing(ctx *plancontext.PlanningContext, e return offset } -func (a *Aggregator) addColumnsWithoutPushing(ctx *plancontext.PlanningContext, reuse bool, groupby []bool, exprs []*sqlparser.AliasedExpr) (offsets []int) { - for i, ae := range exprs { - offset := a.addColumnWithoutPushing(ctx, ae, groupby[i]) - offsets = append(offsets, offset) - } - return -} - func (a *Aggregator) isDerived() bool { return a.DT != nil } @@ -379,7 +371,7 @@ func (a *Aggregator) planOffsets(ctx *plancontext.PlanningContext) Operator { a.Grouping[idx].ColOffset = offset gb.ColOffset = offset } - if gb.WSOffset != -1 || !ctx.SemTable.NeedsWeightString(gb.Inner) { + if gb.WSOffset != -1 || !ctx.NeedsWeightString(gb.Inner) { continue } @@ -391,8 +383,16 @@ func (a *Aggregator) planOffsets(ctx *plancontext.PlanningContext) Operator { if !aggr.NeedsWeightString(ctx) { continue } - arg := aggr.getPushColumn() - offset := a.internalAddColumn(ctx, aeWrap(weightStringFor(arg)), true) + var offset int + if aggr.PushedDown { + // if we have already pushed down aggregation, we need to use + // the weight string of the aggregation and not the argument + offset = a.internalAddColumn(ctx, aeWrap(weightStringFor(aggr.Func)), false) + } else { + // If we have not pushed down the aggregation, we need the weight_string of the argument + arg := aggr.getPushColumn() + offset = a.internalAddColumn(ctx, aeWrap(weightStringFor(arg)), true) + } a.Aggregations[idx].WSOffset = offset } return nil @@ -438,6 +438,9 @@ func (aggr Aggr) getPushColumnExprs() sqlparser.Exprs { return sqlparser.Exprs{aggr.Original.Expr} case opcode.AggregateCountStar: return sqlparser.Exprs{sqlparser.NewIntLiteral("1")} + case opcode.AggregateUDF: + // AggregateUDFs can't be evaluated on the vtgate. So either we are able to push everything down, or we will have to fail the query. + return nil default: return aggr.Func.GetArgs() } @@ -508,7 +511,7 @@ func (a *Aggregator) pushRemainingGroupingColumnsAndWeightStrings(ctx *planconte a.Grouping[idx].ColOffset = offset } - if gb.WSOffset != -1 || !ctx.SemTable.NeedsWeightString(gb.Inner) { + if gb.WSOffset != -1 || !ctx.NeedsWeightString(gb.Inner) { continue } diff --git a/go/vt/vtgate/planbuilder/operators/apply_join.go b/go/vt/vtgate/planbuilder/operators/apply_join.go index 0d214c545d1..cd8f7b94dd5 100644 --- a/go/vt/vtgate/planbuilder/operators/apply_join.go +++ b/go/vt/vtgate/planbuilder/operators/apply_join.go @@ -202,19 +202,11 @@ func (aj *ApplyJoin) GetOrdering(ctx *plancontext.PlanningContext) []OrderBy { return aj.LHS.GetOrdering(ctx) } -func joinColumnToExpr(column applyJoinColumn) sqlparser.Expr { - return column.Original -} - func (aj *ApplyJoin) getJoinColumnFor(ctx *plancontext.PlanningContext, orig *sqlparser.AliasedExpr, e sqlparser.Expr, addToGroupBy bool) (col applyJoinColumn) { - defer func() { - col.Original = orig.Expr - }() lhs := TableID(aj.LHS) rhs := TableID(aj.RHS) both := lhs.Merge(rhs) deps := ctx.SemTable.RecursiveDeps(e) - col.GroupBy = addToGroupBy switch { case deps.IsSolvedBy(lhs): @@ -224,9 +216,12 @@ func (aj *ApplyJoin) getJoinColumnFor(ctx *plancontext.PlanningContext, orig *sq case deps.IsSolvedBy(both): col = breakExpressionInLHSandRHS(ctx, e, TableID(aj.LHS)) default: - panic(vterrors.VT13002(sqlparser.String(e))) + panic(vterrors.VT13001(fmt.Sprintf("expression depends on tables outside this join: %s", sqlparser.String(e)))) } + col.GroupBy = addToGroupBy + col.Original = orig.Expr + return } @@ -289,7 +284,7 @@ func (aj *ApplyJoin) AddWSColumn(ctx *plancontext.PlanningContext, offset int, u if out >= 0 { aj.addOffset(out) } else { - col := aj.getJoinColumnFor(ctx, aeWrap(wsExpr), wsExpr, !ContainsAggr(ctx, wsExpr)) + col := aj.getJoinColumnFor(ctx, aeWrap(wsExpr), wsExpr, !ctx.ContainsAggr(wsExpr)) aj.JoinColumns.add(col) aj.planOffsetFor(ctx, col) } @@ -323,33 +318,15 @@ func (aj *ApplyJoin) planOffsets(ctx *plancontext.PlanningContext) Operator { } func (aj *ApplyJoin) planOffsetFor(ctx *plancontext.PlanningContext, col applyJoinColumn) { - if col.DTColName != nil { - // If DTColName is set, then we already pushed the parts of the expression down while planning. - // We need to use this name and ask the correct side of the join for it. Nothing else is required. - if col.IsPureLeft() { - offset := aj.LHS.AddColumn(ctx, true, col.GroupBy, aeWrap(col.DTColName)) - aj.addOffset(ToLeftOffset(offset)) - } else { - for _, lhsExpr := range col.LHSExprs { - offset := aj.LHS.AddColumn(ctx, true, col.GroupBy, aeWrap(lhsExpr.Expr)) - aj.Vars[lhsExpr.Name] = offset - } - offset := aj.RHS.AddColumn(ctx, true, col.GroupBy, aeWrap(col.DTColName)) - aj.addOffset(ToRightOffset(offset)) - } - return - } - for _, lhsExpr := range col.LHSExprs { - offset := aj.LHS.AddColumn(ctx, true, col.GroupBy, aeWrap(lhsExpr.Expr)) - if col.RHSExpr == nil { - // if we don't have an RHS expr, it means that this is a pure LHS expression - aj.addOffset(ToLeftOffset(offset)) - } else { + if col.IsPureLeft() { + offset := aj.LHS.AddColumn(ctx, true, col.GroupBy, aeWrap(col.GetPureLeftExpr())) + aj.addOffset(ToLeftOffset(offset)) + } else { + for _, lhsExpr := range col.LHSExprs { + offset := aj.LHS.AddColumn(ctx, true, col.GroupBy, aeWrap(lhsExpr.Expr)) aj.Vars[lhsExpr.Name] = offset } - } - if col.RHSExpr != nil { - offset := aj.RHS.AddColumn(ctx, true, col.GroupBy, aeWrap(col.RHSExpr)) + offset := aj.RHS.AddColumn(ctx, true, col.GroupBy, aeWrap(col.GetRHSExpr())) aj.addOffset(ToRightOffset(offset)) } } @@ -443,17 +420,17 @@ func (aj *ApplyJoin) findOrAddColNameBindVarName(ctx *plancontext.PlanningContex return bvName } -func (a *ApplyJoin) LHSColumnsNeeded(ctx *plancontext.PlanningContext) (needed sqlparser.Exprs) { +func (aj *ApplyJoin) LHSColumnsNeeded(ctx *plancontext.PlanningContext) (needed sqlparser.Exprs) { f := func(from BindVarExpr) sqlparser.Expr { return from.Expr } - for _, jc := range a.JoinColumns.columns { + for _, jc := range aj.JoinColumns.columns { needed = append(needed, slice.Map(jc.LHSExprs, f)...) } - for _, jc := range a.JoinPredicates.columns { + for _, jc := range aj.JoinPredicates.columns { needed = append(needed, slice.Map(jc.LHSExprs, f)...) } - needed = append(needed, slice.Map(a.ExtraLHSVars, f)...) + needed = append(needed, slice.Map(aj.ExtraLHSVars, f)...) return ctx.SemTable.Uniquify(needed) } @@ -462,7 +439,11 @@ func (jc applyJoinColumn) String() string { lhs := slice.Map(jc.LHSExprs, func(e BindVarExpr) string { return sqlparser.String(e.Expr) }) - return fmt.Sprintf("[%s | %s | %s]", strings.Join(lhs, ", "), rhs, sqlparser.String(jc.Original)) + if jc.DTColName == nil { + return fmt.Sprintf("[%s | %s | %s]", strings.Join(lhs, ", "), rhs, sqlparser.String(jc.Original)) + } + + return fmt.Sprintf("[%s | %s | %s | %s]", strings.Join(lhs, ", "), rhs, sqlparser.String(jc.Original), sqlparser.String(jc.DTColName)) } func (jc applyJoinColumn) IsPureLeft() bool { @@ -477,6 +458,20 @@ func (jc applyJoinColumn) IsMixedLeftAndRight() bool { return len(jc.LHSExprs) > 0 && jc.RHSExpr != nil } +func (jc applyJoinColumn) GetPureLeftExpr() sqlparser.Expr { + if jc.DTColName != nil { + return jc.DTColName + } + return jc.LHSExprs[0].Expr +} + +func (jc applyJoinColumn) GetRHSExpr() sqlparser.Expr { + if jc.DTColName != nil { + return jc.DTColName + } + return jc.RHSExpr +} + func (bve BindVarExpr) String() string { if bve.Name == "" { return sqlparser.String(bve.Expr) diff --git a/go/vt/vtgate/planbuilder/operators/distinct.go b/go/vt/vtgate/planbuilder/operators/distinct.go index 7807b94d491..4fd53725e10 100644 --- a/go/vt/vtgate/planbuilder/operators/distinct.go +++ b/go/vt/vtgate/planbuilder/operators/distinct.go @@ -50,7 +50,7 @@ func (d *Distinct) planOffsets(ctx *plancontext.PlanningContext) Operator { for idx, col := range columns { e := col.Expr var wsCol *int - if ctx.SemTable.NeedsWeightString(e) { + if ctx.NeedsWeightString(e) { offset := d.Source.AddWSColumn(ctx, idx, false) wsCol = &offset } diff --git a/go/vt/vtgate/planbuilder/operators/expressions.go b/go/vt/vtgate/planbuilder/operators/expressions.go index a39ae96fa88..17b4bc7c3f1 100644 --- a/go/vt/vtgate/planbuilder/operators/expressions.go +++ b/go/vt/vtgate/planbuilder/operators/expressions.go @@ -44,7 +44,11 @@ func breakExpressionInLHSandRHS( Name: bvName, Expr: nodeExpr, }) - arg := sqlparser.NewArgument(bvName) + typeForExpr, _ := ctx.TypeForExpr(nodeExpr) + arg := sqlparser.NewTypedArgument(bvName, typeForExpr.Type()) + arg.Scale = typeForExpr.Scale() + arg.Size = typeForExpr.Size() + // we are replacing one of the sides of the comparison with an argument, // but we don't want to lose the type information we have, so we copy it over ctx.SemTable.CopyExprInfo(nodeExpr, arg) diff --git a/go/vt/vtgate/planbuilder/operators/horizon.go b/go/vt/vtgate/planbuilder/operators/horizon.go index c28bc2dd5f0..7539704c2a9 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon.go +++ b/go/vt/vtgate/planbuilder/operators/horizon.go @@ -100,7 +100,7 @@ func (h *Horizon) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser. } newExpr := ctx.RewriteDerivedTableExpression(expr, tableInfo) - if ContainsAggr(ctx, newExpr) { + if ctx.ContainsAggr(newExpr) { return newFilter(h, expr) } h.Source = h.Source.AddPredicate(ctx, newExpr) diff --git a/go/vt/vtgate/planbuilder/operators/horizon_expanding.go b/go/vt/vtgate/planbuilder/operators/horizon_expanding.go index 3f7700eed9d..fd3d992d0ca 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon_expanding.go +++ b/go/vt/vtgate/planbuilder/operators/horizon_expanding.go @@ -75,9 +75,18 @@ func expandUnionHorizon(ctx *plancontext.PlanningContext, horizon *Horizon, unio } func expandSelectHorizon(ctx *plancontext.PlanningContext, horizon *Horizon, sel *sqlparser.Select) (Operator, *ApplyResult) { - op := createProjectionFromSelect(ctx, horizon) qp := horizon.getQP(ctx) var extracted []string + + if horizon.IsDerived() { + // if we are dealing with a derived table, we need to make sure that the ordering columns + // are available outside the derived table + for _, order := range horizon.Query.GetOrderBy() { + qp.addDerivedColumn(ctx, order.Expr) + } + } + + op := createProjectionFromSelect(ctx, horizon) if qp.HasAggr { extracted = append(extracted, "Aggregation") } else { @@ -99,7 +108,7 @@ func expandSelectHorizon(ctx *plancontext.PlanningContext, horizon *Horizon, sel } if len(qp.OrderExprs) > 0 { - op = expandOrderBy(ctx, op, qp) + op = expandOrderBy(ctx, op, qp, horizon.Alias) extracted = append(extracted, "Ordering") } @@ -115,7 +124,7 @@ func expandSelectHorizon(ctx *plancontext.PlanningContext, horizon *Horizon, sel return op, Rewrote(fmt.Sprintf("expand SELECT horizon into (%s)", strings.Join(extracted, ", "))) } -func expandOrderBy(ctx *plancontext.PlanningContext, op Operator, qp *QueryProjection) Operator { +func expandOrderBy(ctx *plancontext.PlanningContext, op Operator, qp *QueryProjection, derived string) Operator { var newOrder []OrderBy sqc := &SubQueryBuilder{} proj, ok := op.(*Projection) @@ -125,17 +134,25 @@ func expandOrderBy(ctx *plancontext.PlanningContext, op Operator, qp *QueryProje newExpr, subqs := sqc.pullOutValueSubqueries(ctx, expr.SimplifiedExpr, TableID(op), false) if newExpr == nil { // If no subqueries are found, retain the original order expression + if derived != "" { + expr = exposeOrderingColumn(ctx, qp, expr, derived) + } newOrder = append(newOrder, expr) continue } - // If the operator is not a projection, we cannot handle subqueries with aggregation + // If the operator is not a projection, we cannot handle subqueries with aggregation if we are unable to push everything into a single route. if !ok { - panic(vterrors.VT12001("subquery with aggregation in order by")) + ctx.SemTable.NotSingleRouteErr = vterrors.VT12001("subquery with aggregation in order by") + return &Ordering{ + Source: op, + Order: qp.OrderExprs, + } + } else { + // Add the new subquery expression to the projection + proj.addSubqueryExpr(ctx, aeWrap(newExpr), newExpr, subqs...) } - // Add the new subquery expression to the projection - proj.addSubqueryExpr(ctx, aeWrap(newExpr), newExpr, subqs...) // Replace the original order expression with the new expression containing subqueries newOrder = append(newOrder, OrderBy{ Inner: &sqlparser.Order{ @@ -158,6 +175,25 @@ func expandOrderBy(ctx *plancontext.PlanningContext, op Operator, qp *QueryProje } } +// exposeOrderingColumn will expose the ordering column to the outer query +func exposeOrderingColumn(ctx *plancontext.PlanningContext, qp *QueryProjection, orderBy OrderBy, derived string) OrderBy { + for _, se := range qp.SelectExprs { + aliasedExpr, err := se.GetAliasedExpr() + if err != nil { + panic(vterrors.VT13001("unexpected expression in select")) + } + if ctx.SemTable.EqualsExprWithDeps(aliasedExpr.Expr, orderBy.SimplifiedExpr) { + newExpr := sqlparser.NewColNameWithQualifier(aliasedExpr.ColumnName(), sqlparser.NewTableName(derived)) + ctx.SemTable.CopySemanticInfo(orderBy.SimplifiedExpr, newExpr) + orderBy.SimplifiedExpr = newExpr + orderBy.Inner = &sqlparser.Order{Expr: newExpr, Direction: orderBy.Inner.Direction} + break + } + } + + return orderBy +} + func createProjectionFromSelect(ctx *plancontext.PlanningContext, horizon *Horizon) Operator { qp := horizon.getQP(ctx) diff --git a/go/vt/vtgate/planbuilder/operators/offset_planning.go b/go/vt/vtgate/planbuilder/operators/offset_planning.go index eb92cdf0920..7a9cedccb89 100644 --- a/go/vt/vtgate/planbuilder/operators/offset_planning.go +++ b/go/vt/vtgate/planbuilder/operators/offset_planning.go @@ -21,7 +21,6 @@ import ( "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" - "vitess.io/vitess/go/vt/vtgate/engine/opcode" "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" "vitess.io/vitess/go/vt/vtgate/semantics" ) @@ -96,62 +95,68 @@ func useOffsets(ctx *plancontext.PlanningContext, expr sqlparser.Expr, op Operat return rewritten.(sqlparser.Expr) } +func findAggregatorInSource(op Operator) *Aggregator { + // we'll just loop through the inputs until we find the aggregator + for { + aggr, ok := op.(*Aggregator) + if ok { + return aggr + } + inputs := op.Inputs() + if len(inputs) != 1 { + panic(vterrors.VT13001("unexpected multiple inputs")) + } + src := inputs[0] + _, isRoute := src.(*Route) + if isRoute { + panic(vterrors.VT13001("failed to find the aggregator")) + } + op = src + } +} + +// addColumnsToInput adds columns needed by an operator to its input. +// This happens only when the filter expression can be retrieved as an offset from the underlying mysql. func addColumnsToInput(ctx *plancontext.PlanningContext, root Operator) Operator { - // addColumnsToInput adds columns needed by an operator to its input. - // This happens only when the filter expression can be retrieved as an offset from the underlying mysql. + addColumnsNeededByFilter := func(in Operator, _ semantics.TableSet, _ bool) (Operator, *ApplyResult) { + addedCols := false filter, ok := in.(*Filter) if !ok { return in, NoRewrite } - proj, areOnTopOfProj := filter.Source.(selectExpressions) - if !areOnTopOfProj { - // not much we can do here - return in, NoRewrite - } - addedColumns := false - found := func(expr sqlparser.Expr, i int) {} - notFound := func(e sqlparser.Expr) { - _, addToGroupBy := e.(*sqlparser.ColName) - proj.addColumnWithoutPushing(ctx, aeWrap(e), addToGroupBy) - addedColumns = true + var neededAggrs []sqlparser.Expr + extractAggrs := func(cursor *sqlparser.CopyOnWriteCursor) { + node := cursor.Node() + if ctx.IsAggr(node) { + neededAggrs = append(neededAggrs, node.(sqlparser.Expr)) + } } - visitor := getOffsetRewritingVisitor(ctx, proj.FindCol, found, notFound) for _, expr := range filter.Predicates { - _ = sqlparser.CopyOnRewrite(expr, visitor, nil, ctx.SemTable.CopySemanticInfo) - } - if addedColumns { - return in, Rewrote("added columns because filter needs it") + _ = sqlparser.CopyOnRewrite(expr, dontEnterSubqueries, extractAggrs, nil) } - return in, NoRewrite - } - - // while we are out here walking the operator tree, if we find a UDF in an aggregation, we should fail - failUDFAggregation := func(in Operator, _ semantics.TableSet, _ bool) (Operator, *ApplyResult) { - aggrOp, ok := in.(*Aggregator) - if !ok { + if neededAggrs == nil { return in, NoRewrite } - for _, aggr := range aggrOp.Aggregations { - if aggr.OpCode == opcode.AggregateUDF { - // we don't support UDFs in aggregation if it's still above a route - message := fmt.Sprintf("Aggregate UDF '%s' must be pushed down to MySQL", sqlparser.String(aggr.Original.Expr)) - panic(vterrors.VT12001(message)) + + aggregator := findAggregatorInSource(filter.Source) + for _, aggr := range neededAggrs { + if aggregator.FindCol(ctx, aggr, false) == -1 { + aggregator.addColumnWithoutPushing(ctx, aeWrap(aggr), false) + addedCols = true } } - return in, NoRewrite - } - visitor := func(in Operator, _ semantics.TableSet, isRoot bool) (Operator, *ApplyResult) { - out, res := addColumnsNeededByFilter(in, semantics.EmptyTableSet(), isRoot) - failUDFAggregation(in, semantics.EmptyTableSet(), isRoot) - return out, res + if addedCols { + return in, Rewrote("added columns because filter needs it") + } + return in, NoRewrite } - return TopDown(root, TableID, visitor, stopAtRoute) + return TopDown(root, TableID, addColumnsNeededByFilter, stopAtRoute) } // isolateDistinctFromUnion will pull out the distinct from a union operator diff --git a/go/vt/vtgate/planbuilder/operators/ordering.go b/go/vt/vtgate/planbuilder/operators/ordering.go index 5414b34fc40..94c4f3dd846 100644 --- a/go/vt/vtgate/planbuilder/operators/ordering.go +++ b/go/vt/vtgate/planbuilder/operators/ordering.go @@ -86,7 +86,7 @@ func (o *Ordering) planOffsets(ctx *plancontext.PlanningContext) Operator { offset := o.Source.AddColumn(ctx, true, false, aeWrap(order.SimplifiedExpr)) o.Offset = append(o.Offset, offset) - if !ctx.SemTable.NeedsWeightString(order.SimplifiedExpr) { + if !ctx.NeedsWeightString(order.SimplifiedExpr) { o.WOffset = append(o.WOffset, -1) continue } diff --git a/go/vt/vtgate/planbuilder/operators/projection.go b/go/vt/vtgate/planbuilder/operators/projection.go index 527991cba26..d8ede63b612 100644 --- a/go/vt/vtgate/planbuilder/operators/projection.go +++ b/go/vt/vtgate/planbuilder/operators/projection.go @@ -308,15 +308,6 @@ func (p *Projection) addColumnWithoutPushing(ctx *plancontext.PlanningContext, e return p.addColumn(ctx, true, false, expr, false) } -func (p *Projection) addColumnsWithoutPushing(ctx *plancontext.PlanningContext, reuse bool, _ []bool, exprs []*sqlparser.AliasedExpr) []int { - offsets := make([]int, len(exprs)) - for idx, expr := range exprs { - offset := p.addColumn(ctx, reuse, false, expr, false) - offsets[idx] = offset - } - return offsets -} - func (p *Projection) AddWSColumn(ctx *plancontext.PlanningContext, offset int, underRoute bool) int { cols, aliased := p.Columns.(AliasedProjections) if !aliased { diff --git a/go/vt/vtgate/planbuilder/operators/projection_pushing.go b/go/vt/vtgate/planbuilder/operators/projection_pushing.go index d1baf6def62..b5c6a10bb78 100644 --- a/go/vt/vtgate/planbuilder/operators/projection_pushing.go +++ b/go/vt/vtgate/planbuilder/operators/projection_pushing.go @@ -284,7 +284,11 @@ func pushProjectionInApplyJoin( src.LHS = createProjectionWithTheseColumns(ctx, src.LHS, lhs, p.DT) src.RHS = createProjectionWithTheseColumns(ctx, src.RHS, rhs, p.DT) - return src, Rewrote("split projection to either side of join") + message := "split projection to either side of join" + if p.DT != nil { + message += " " + p.DT.Alias + } + return src, Rewrote(message) } // splitProjectionAcrossJoin creates JoinPredicates for all projections, @@ -396,14 +400,14 @@ func exposeColumnsThroughDerivedTable(ctx *plancontext.PlanningContext, p *Proje lhsIDs := TableID(src.LHS) rhsIDs := TableID(src.RHS) - rewriteColumnsForJoin(ctx, src.JoinPredicates.columns, lhsIDs, rhsIDs, lhs, rhs) + rewriteColumnsForJoin(ctx, src.JoinPredicates.columns, lhsIDs, rhsIDs, lhs) } func rewriteColumnsForJoin( ctx *plancontext.PlanningContext, columns []applyJoinColumn, lhsIDs, rhsIDs semantics.TableSet, - lhs, rhs *projector, + lhs *projector, ) { for colIdx, column := range columns { for lhsIdx, bve := range column.LHSExprs { diff --git a/go/vt/vtgate/planbuilder/operators/query_planning.go b/go/vt/vtgate/planbuilder/operators/query_planning.go index 2f3259394e2..e88fb53edb3 100644 --- a/go/vt/vtgate/planbuilder/operators/query_planning.go +++ b/go/vt/vtgate/planbuilder/operators/query_planning.go @@ -490,6 +490,11 @@ func setUpperLimit(in *Limit) (Operator, *ApplyResult) { case *Join, *ApplyJoin, *SubQueryContainer, *SubQuery: // we can't push limits down on either side return SkipChildren + case *Aggregator: + if len(op.Grouping) > 0 { + // we can't push limits down if we have a group by + return SkipChildren + } case *Route: newSrc := &Limit{ Source: op.Source, @@ -498,9 +503,8 @@ func setUpperLimit(in *Limit) (Operator, *ApplyResult) { op.Source = newSrc result = result.Merge(Rewrote("push upper limit under route")) return SkipChildren - default: - return VisitChildren } + return VisitChildren } TopDown(in.Source, TableID, visitor, shouldVisit) @@ -532,26 +536,10 @@ func tryPushOrdering(ctx *plancontext.PlanningContext, in *Ordering) (Operator, return pushOrderingUnderAggr(ctx, in, src) case *SubQueryContainer: return pushOrderingToOuterOfSubqueryContainer(ctx, in, src) - case *SubQuery: - return pushOrderingToOuterOfSubquery(ctx, in, src) } return in, NoRewrite } -func pushOrderingToOuterOfSubquery(ctx *plancontext.PlanningContext, in *Ordering, sq *SubQuery) (Operator, *ApplyResult) { - outerTableID := TableID(sq.Outer) - for idx, order := range in.Order { - deps := ctx.SemTable.RecursiveDeps(order.Inner.Expr) - if !deps.IsSolvedBy(outerTableID) { - return in, NoRewrite - } - in.Order[idx].SimplifiedExpr = sq.rewriteColNameToArgument(order.SimplifiedExpr) - in.Order[idx].Inner.Expr = sq.rewriteColNameToArgument(order.Inner.Expr) - } - sq.Outer, in.Source = in, sq.Outer - return sq, Rewrote("push ordering into outer side of subquery") -} - func pushOrderingToOuterOfSubqueryContainer(ctx *plancontext.PlanningContext, in *Ordering, subq *SubQueryContainer) (Operator, *ApplyResult) { outerTableID := TableID(subq.Outer) for _, order := range in.Order { @@ -604,14 +592,23 @@ ordering: return true } +// pushOrderingUnderAggr pushes the ORDER BY clause under the aggregation if possible, +// to optimize the query plan by aligning the GROUP BY and ORDER BY clauses and +// potentially removing redundant ORDER BY clauses. func pushOrderingUnderAggr(ctx *plancontext.PlanningContext, order *Ordering, aggregator *Aggregator) (Operator, *ApplyResult) { - // If Aggregator is a derived table, then we should rewrite the ordering before pushing. + // Avoid pushing down too early to allow for aggregation pushdown to MySQL + if !reachedPhase(ctx, delegateAggregation) { + return order, NoRewrite + } + + // Rewrite ORDER BY if Aggregator is a derived table if aggregator.isDerived() { for idx, orderExpr := range order.Order { ti, err := ctx.SemTable.TableInfoFor(aggregator.DT.TableID) if err != nil { panic(err) } + // Rewrite expressions in ORDER BY to match derived table columns newOrderExpr := orderExpr.Map(func(expr sqlparser.Expr) sqlparser.Expr { return semantics.RewriteDerivedTableExpression(expr, ti) }) @@ -619,9 +616,7 @@ func pushOrderingUnderAggr(ctx *plancontext.PlanningContext, order *Ordering, ag } } - // Step 1: Align the GROUP BY and ORDER BY. - // Reorder the GROUP BY columns to match the ORDER BY columns. - // Since the GB clause is a set, we can reorder these columns freely. + // Align GROUP BY with ORDER BY by reordering GROUP BY columns to match ORDER BY var newGrouping []GroupBy used := make([]bool, len(aggregator.Grouping)) for _, orderExpr := range order.Order { @@ -633,11 +628,8 @@ func pushOrderingUnderAggr(ctx *plancontext.PlanningContext, order *Ordering, ag } } - // Step 2: Add any missing columns from the ORDER BY. - // The ORDER BY column is not a set, but we can add more elements - // to the end without changing the semantics of the query. + // Add any missing GROUP BY columns to ORDER BY if len(newGrouping) != len(aggregator.Grouping) { - // we are missing some groupings. We need to add them both to the new groupings list, but also to the ORDER BY for i, added := range used { if !added { groupBy := aggregator.Grouping[i] @@ -650,7 +642,7 @@ func pushOrderingUnderAggr(ctx *plancontext.PlanningContext, order *Ordering, ag aggregator.Grouping = newGrouping aggrSource, isOrdering := aggregator.Source.(*Ordering) if isOrdering { - // Transform the query plan tree: + // Optimize query plan by removing redundant ORDER BY // From: Ordering(1) To: Aggregation // | | // Aggregation Ordering(1) @@ -658,11 +650,8 @@ func pushOrderingUnderAggr(ctx *plancontext.PlanningContext, order *Ordering, ag // Ordering(2) // | // - // - // Remove Ordering(2) from the plan tree, as it's redundant - // after pushing down the higher ordering. order.Source = aggrSource.Source - aggrSource.Source = nil // removing from plan tree + aggrSource.Source = nil aggregator.Source = order return aggregator, Rewrote("push ordering under aggregation, removing extra ordering") } diff --git a/go/vt/vtgate/planbuilder/operators/queryprojection.go b/go/vt/vtgate/planbuilder/operators/queryprojection.go index 5729dbd0c2e..a245831ca13 100644 --- a/go/vt/vtgate/planbuilder/operators/queryprojection.go +++ b/go/vt/vtgate/planbuilder/operators/queryprojection.go @@ -19,7 +19,6 @@ package operators import ( "encoding/json" "fmt" - "io" "slices" "sort" "strings" @@ -68,36 +67,34 @@ type ( // Aggr encodes all information needed for aggregation functions Aggr struct { - Original *sqlparser.AliasedExpr - Func sqlparser.AggrFunc // if we are missing a Func, it means this is a AggregateAnyValue - OpCode opcode.AggregateOpcode + Original *sqlparser.AliasedExpr // The original SQL expression for the aggregation + Func sqlparser.AggrFunc // The aggregation function (e.g., COUNT, SUM). If nil, it means AggregateAnyValue or AggregateUDF is used + OpCode opcode.AggregateOpcode // The opcode representing the type of aggregation being performed - // OriginalOpCode will contain opcode.AggregateUnassigned unless we are changing opcode while pushing them down + // OriginalOpCode will contain opcode.AggregateUnassigned unless we are changing the opcode while pushing them down OriginalOpCode opcode.AggregateOpcode - Alias string + Alias string // The alias name for the aggregation result - // The index at which the user expects to see this aggregated function. Set to nil, if the user does not ask for it - // Only used in the old Horizon Planner - Index *int + Distinct bool // Whether the aggregation function is DISTINCT - Distinct bool + // Offsets pointing to columns within the same aggregator + ColOffset int // Offset for the column being aggregated + WSOffset int // Offset for the weight string of the column - // the offsets point to columns on the same aggregator - ColOffset int - WSOffset int + SubQueryExpression []*SubQuery // Subqueries associated with this aggregation - SubQueryExpression []*SubQuery + PushedDown bool // Whether the aggregation has been pushed down to the next layer } ) func (aggr Aggr) NeedsWeightString(ctx *plancontext.PlanningContext) bool { - return aggr.OpCode.NeedsComparableValues() && ctx.SemTable.NeedsWeightString(aggr.Func.GetArg()) + return aggr.OpCode.NeedsComparableValues() && ctx.NeedsWeightString(aggr.Func.GetArg()) } func (aggr Aggr) GetTypeCollation(ctx *plancontext.PlanningContext) evalengine.Type { if aggr.Func == nil { - return evalengine.Type{} + return evalengine.NewUnknownType() } switch aggr.OpCode { case opcode.AggregateMin, opcode.AggregateMax, opcode.AggregateSumDistinct, opcode.AggregateCountDistinct: @@ -171,7 +168,7 @@ func createQPFromSelect(ctx *plancontext.PlanningContext, sel *sqlparser.Select) qp.addGroupBy(ctx, sel.GroupBy) qp.addOrderBy(ctx, sel.OrderBy) if !qp.HasAggr && sel.Having != nil { - qp.HasAggr = ContainsAggr(ctx, sel.Having.Expr) + qp.HasAggr = ctx.ContainsAggr(sel.Having.Expr) } qp.calculateDistinct(ctx) @@ -185,7 +182,7 @@ func (qp *QueryProjection) addSelectExpressions(ctx *plancontext.PlanningContext col := SelectExpr{ Col: selExp, } - if ContainsAggr(ctx, selExp.Expr) { + if ctx.ContainsAggr(selExp.Expr) { col.Aggr = true qp.HasAggr = true } @@ -202,41 +199,6 @@ func (qp *QueryProjection) addSelectExpressions(ctx *plancontext.PlanningContext } } -func IsAggr(ctx *plancontext.PlanningContext, e sqlparser.SQLNode) bool { - switch node := e.(type) { - case sqlparser.AggrFunc: - return true - case *sqlparser.FuncExpr: - return node.Name.EqualsAnyString(ctx.VSchema.GetAggregateUDFs()) - } - - return false -} - -func ContainsAggr(ctx *plancontext.PlanningContext, e sqlparser.SQLNode) (hasAggr bool) { - _ = sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { - switch node.(type) { - case *sqlparser.Offset: - // offsets here indicate that a possible aggregation has already been handled by an input, - // so we don't need to worry about aggregation in the original - return false, nil - case sqlparser.AggrFunc: - hasAggr = true - return false, io.EOF - case *sqlparser.Subquery: - return false, nil - case *sqlparser.FuncExpr: - if IsAggr(ctx, node) { - hasAggr = true - return false, io.EOF - } - } - - return true, nil - }, e) - return -} - // createQPFromUnion creates the QueryProjection for the input *sqlparser.Union func createQPFromUnion(ctx *plancontext.PlanningContext, union *sqlparser.Union) *QueryProjection { qp := &QueryProjection{} @@ -279,7 +241,7 @@ func (qp *QueryProjection) addOrderBy(ctx *plancontext.PlanningContext, orderBy Inner: ctx.SemTable.Clone(order).(*sqlparser.Order), SimplifiedExpr: order.Expr, }) - canPushSorting = canPushSorting && !ContainsAggr(ctx, order.Expr) + canPushSorting = canPushSorting && !ctx.ContainsAggr(order.Expr) } } @@ -442,38 +404,34 @@ func (qp *QueryProjection) AggregationExpressions(ctx *plancontext.PlanningConte // Here we go over the expressions we are returning. Since we know we are aggregating, // all expressions have to be either grouping expressions or aggregate expressions. // If we find an expression that is neither, we treat is as a special aggregation function AggrRandom - for idx, expr := range qp.SelectExprs { + for _, expr := range qp.SelectExprs { aliasedExpr, err := expr.GetAliasedExpr() if err != nil { panic(err) } - idxCopy := idx - - if !ContainsAggr(ctx, expr.Col) { + if !ctx.ContainsAggr(expr.Col) { getExpr, err := expr.GetExpr() if err != nil { panic(err) } if !qp.isExprInGroupByExprs(ctx, getExpr) { aggr := NewAggr(opcode.AggregateAnyValue, nil, aliasedExpr, aliasedExpr.ColumnName()) - aggr.Index = &idxCopy out = append(out, aggr) } continue } - if !IsAggr(ctx, aliasedExpr.Expr) && !allowComplexExpression { + if !ctx.IsAggr(aliasedExpr.Expr) && !allowComplexExpression { panic(vterrors.VT12001("in scatter query: complex aggregate expression")) } - sqlparser.CopyOnRewrite(aliasedExpr.Expr, qp.extractAggr(ctx, idx, aliasedExpr, addAggr, makeComplex), nil, nil) + sqlparser.CopyOnRewrite(aliasedExpr.Expr, qp.extractAggr(ctx, aliasedExpr, addAggr, makeComplex), nil, nil) } return } func (qp *QueryProjection) extractAggr( ctx *plancontext.PlanningContext, - idx int, aliasedExpr *sqlparser.AliasedExpr, addAggr func(a Aggr), makeComplex func(), @@ -489,25 +447,22 @@ func (qp *QueryProjection) extractAggr( ae = aliasedExpr } aggrFunc := createAggrFromAggrFunc(aggr, ae) - aggrFunc.Index = &idx addAggr(aggrFunc) return false } - if IsAggr(ctx, node) { + if ctx.IsAggr(node) { // If we are here, we have a function that is an aggregation but not parsed into an AggrFunc. // This is the case for UDFs - we have to be careful with these because we can't evaluate them in VTGate. aggr := NewAggr(opcode.AggregateUDF, nil, aeWrap(ex), "") - aggr.Index = &idx addAggr(aggr) return false } - if ContainsAggr(ctx, node) { + if ctx.ContainsAggr(node) { makeComplex() return true } if !qp.isExprInGroupByExprs(ctx, ex) { aggr := NewAggr(opcode.AggregateAnyValue, nil, aeWrap(ex), "") - aggr.Index = &idx addAggr(aggr) } return false @@ -530,7 +485,7 @@ orderBy: } qp.SelectExprs = append(qp.SelectExprs, SelectExpr{ Col: &sqlparser.AliasedExpr{Expr: orderExpr}, - Aggr: ContainsAggr(ctx, orderExpr), + Aggr: ctx.ContainsAggr(orderExpr), }) qp.AddedColumn++ } @@ -709,9 +664,27 @@ func (qp *QueryProjection) useGroupingOverDistinct(ctx *plancontext.PlanningCont return true } +// addColumn adds a column to the QueryProjection if it is not already present. +// It will use a column name that is available on the outside of the derived table +func (qp *QueryProjection) addDerivedColumn(ctx *plancontext.PlanningContext, expr sqlparser.Expr) { + for _, selectExpr := range qp.SelectExprs { + getExpr, err := selectExpr.GetExpr() + if err != nil { + continue + } + if ctx.SemTable.EqualsExprWithDeps(getExpr, expr) { + return + } + } + qp.SelectExprs = append(qp.SelectExprs, SelectExpr{ + Col: aeWrap(expr), + Aggr: ctx.ContainsAggr(expr), + }) +} + func checkForInvalidGroupingExpressions(ctx *plancontext.PlanningContext, expr sqlparser.Expr) { _ = sqlparser.Walk(func(node sqlparser.SQLNode) (bool, error) { - if IsAggr(ctx, node) { + if ctx.IsAggr(node) { panic(vterrors.VT03005(sqlparser.String(expr))) } _, isSubQ := node.(*sqlparser.Subquery) diff --git a/go/vt/vtgate/planbuilder/operators/rewriters.go b/go/vt/vtgate/planbuilder/operators/rewriters.go index d4d2c15f4ca..ab9fe66e368 100644 --- a/go/vt/vtgate/planbuilder/operators/rewriters.go +++ b/go/vt/vtgate/planbuilder/operators/rewriters.go @@ -232,6 +232,7 @@ func bottomUp( newOp, treeIdentity := rewriter(root, rootID, isRoot) anythingChanged = anythingChanged.Merge(treeIdentity) + return newOp, anythingChanged } diff --git a/go/vt/vtgate/planbuilder/operators/route.go b/go/vt/vtgate/planbuilder/operators/route.go index cc049d22753..1c91077c2e4 100644 --- a/go/vt/vtgate/planbuilder/operators/route.go +++ b/go/vt/vtgate/planbuilder/operators/route.go @@ -587,96 +587,87 @@ func (r *Route) AddColumn(ctx *plancontext.PlanningContext, reuse bool, gb bool, // if at least one column is not already present, we check if we can easily find a projection // or aggregation in our source that we can add to - derived, op, ok, offsets := addMultipleColumnsToInput(ctx, r.Source, reuse, []bool{gb}, []*sqlparser.AliasedExpr{expr}) - r.Source = op - if ok { - return offsets[0] + derived, op, offset := addColumnToInput(ctx, r.Source, expr, reuse, gb) + if op != nil { + r.Source = op + } + if offset >= 0 { + return offset } // If no-one could be found, we probably don't have one yet, so we add one here src := createProjection(ctx, r.Source, derived) r.Source = src - offsets = src.addColumnsWithoutPushing(ctx, reuse, []bool{gb}, []*sqlparser.AliasedExpr{expr}) - return offsets[0] + return src.addColumnWithoutPushing(ctx, expr, gb) } type selectExpressions interface { Operator addColumnWithoutPushing(ctx *plancontext.PlanningContext, expr *sqlparser.AliasedExpr, addToGroupBy bool) int - addColumnsWithoutPushing(ctx *plancontext.PlanningContext, reuse bool, addToGroupBy []bool, exprs []*sqlparser.AliasedExpr) []int derivedName() string } // addColumnToInput adds columns to an operator without pushing them down -func addMultipleColumnsToInput( +func addColumnToInput( ctx *plancontext.PlanningContext, operator Operator, - reuse bool, - addToGroupBy []bool, - exprs []*sqlparser.AliasedExpr, -) (derivedName string, // if we found a derived table, this will contain its name + expr *sqlparser.AliasedExpr, + reuse, addToGroupBy bool, +) ( + derivedName string, // if we found a derived table, this will contain its name projection Operator, // if an operator needed to be built, it will be returned here - found bool, // whether a matching op was found or not - offsets []int, // the offsets the expressions received + offset int, // the offset of the expression, -1 if not found ) { + var src Operator + var updateSrc func(Operator) switch op := operator.(type) { - case *SubQuery: - derivedName, src, added, offset := addMultipleColumnsToInput(ctx, op.Outer, reuse, addToGroupBy, exprs) - if added { - op.Outer = src - } - return derivedName, op, added, offset + // Pass through operators - we can just add the columns to their source + case *SubQuery: + src, updateSrc = op.Outer, func(newSrc Operator) { op.Outer = newSrc } case *Distinct: - derivedName, src, added, offset := addMultipleColumnsToInput(ctx, op.Source, reuse, addToGroupBy, exprs) - if added { - op.Source = src - } - return derivedName, op, added, offset - + src, updateSrc = op.Source, func(newSrc Operator) { op.Source = newSrc } case *Limit: - derivedName, src, added, offset := addMultipleColumnsToInput(ctx, op.Source, reuse, addToGroupBy, exprs) - if added { - op.Source = src - } - return derivedName, op, added, offset - + src, updateSrc = op.Source, func(newSrc Operator) { op.Source = newSrc } case *Ordering: - derivedName, src, added, offset := addMultipleColumnsToInput(ctx, op.Source, reuse, addToGroupBy, exprs) - if added { - op.Source = src - } - return derivedName, op, added, offset - + src, updateSrc = op.Source, func(newSrc Operator) { op.Source = newSrc } case *LockAndComment: - derivedName, src, added, offset := addMultipleColumnsToInput(ctx, op.Source, reuse, addToGroupBy, exprs) - if added { - op.Source = src + src, updateSrc = op.Source, func(newSrc Operator) { op.Source = newSrc } + + // Union needs special handling, we can't really add new columns to all inputs + case *Union: + proj := wrapInDerivedProjection(ctx, op) + dtName, newOp, offset := addColumnToInput(ctx, proj, expr, reuse, addToGroupBy) + if newOp == nil { + newOp = proj } - return derivedName, op, added, offset + return dtName, newOp, offset + // Horizon is another one of these - we can't really add new columns to it case *Horizon: - // if the horizon has an alias, then it is a derived table, - // we have to add a new projection and can't build on this one - return op.Alias, op, false, nil + return op.Alias, nil, -1 case selectExpressions: name := op.derivedName() if name != "" { // if the only thing we can push to is a derived table, // we have to add a new projection and can't build on this one - return name, op, false, nil + return name, nil, -1 } - offset := op.addColumnsWithoutPushing(ctx, reuse, addToGroupBy, exprs) - return "", op, true, offset + offset := op.addColumnWithoutPushing(ctx, expr, addToGroupBy) + return "", nil, offset - case *Union: - proj := addDerivedProj(ctx, op) - return addMultipleColumnsToInput(ctx, proj, reuse, addToGroupBy, exprs) default: - return "", op, false, nil + return "", nil, -1 + } + + // Handle the case where we have a pass-through operator + derivedName, src, offset = addColumnToInput(ctx, src, expr, reuse, addToGroupBy) + if src != nil { + updateSrc(src) } + return derivedName, nil, offset } func (r *Route) AddWSColumn(ctx *plancontext.PlanningContext, offset int, _ bool) int { @@ -691,7 +682,7 @@ func (r *Route) AddWSColumn(ctx *plancontext.PlanningContext, offset int, _ bool ok, foundOffset := addWSColumnToInput(ctx, r.Source, offset) if !ok { - src := addDerivedProj(ctx, r.Source) + src := wrapInDerivedProjection(ctx, r.Source) r.Source = src return src.AddWSColumn(ctx, offset, true) } @@ -714,7 +705,8 @@ func addWSColumnToInput(ctx *plancontext.PlanningContext, source Operator, offse return false, -1 } -func addDerivedProj( +// wrapInDerivedProjection wraps the input in a derived table projection named "dt" +func wrapInDerivedProjection( ctx *plancontext.PlanningContext, op Operator, ) (projection *Projection) { @@ -805,7 +797,7 @@ func (r *Route) planOffsets(ctx *plancontext.PlanningContext) Operator { WOffset: -1, Direction: order.Inner.Direction, } - if ctx.SemTable.NeedsWeightString(order.SimplifiedExpr) { + if ctx.NeedsWeightString(order.SimplifiedExpr) { ws := weightStringFor(order.SimplifiedExpr) offset := r.AddColumn(ctx, true, false, aeWrap(ws)) o.WOffset = offset diff --git a/go/vt/vtgate/planbuilder/operators/subquery.go b/go/vt/vtgate/planbuilder/operators/subquery.go index a950c3720c2..b919bbfaed9 100644 --- a/go/vt/vtgate/planbuilder/operators/subquery.go +++ b/go/vt/vtgate/planbuilder/operators/subquery.go @@ -208,7 +208,9 @@ func (sq *SubQuery) GetMergePredicates() []sqlparser.Expr { } func (sq *SubQuery) settle(ctx *plancontext.PlanningContext, outer Operator) Operator { - if !sq.TopLevel { + // We can allow uncorrelated queries even when subquery isn't the top level construct, + // like if its underneath an Aggregator, because they will be pulled out and run separately. + if !sq.TopLevel && sq.correlated { panic(subqueryNotAtTopErr) } if sq.correlated && sq.FilterType != opcode.PulloutExists { @@ -253,6 +255,20 @@ func (sq *SubQuery) settleFilter(ctx *plancontext.PlanningContext, outer Operato } post := func(cursor *sqlparser.CopyOnWriteCursor) { node := cursor.Node() + // For IN and NOT IN type filters, we have to add a Expression that checks if we got any rows back or not + // for correctness. That expression should be ANDed with the expression that has the IN/NOT IN comparison. + if compExpr, isCompExpr := node.(*sqlparser.ComparisonExpr); sq.FilterType.NeedsListArg() && isCompExpr { + if listArg, isListArg := compExpr.Right.(sqlparser.ListArg); isListArg && listArg.String() == sq.ArgName { + if sq.FilterType == opcode.PulloutIn { + cursor.Replace(sqlparser.AndExpressions(sqlparser.NewArgument(hasValuesArg()), compExpr)) + } else { + cursor.Replace(&sqlparser.OrExpr{ + Left: sqlparser.NewNotExpr(sqlparser.NewArgument(hasValuesArg())), + Right: compExpr, + }) + } + } + } if _, ok := node.(*sqlparser.Subquery); !ok { return } @@ -277,13 +293,18 @@ func (sq *SubQuery) settleFilter(ctx *plancontext.PlanningContext, outer Operato sq.FilterType = opcode.PulloutExists // it's the same pullout as EXISTS, just with a NOT in front of the predicate predicates = append(predicates, sqlparser.NewNotExpr(sqlparser.NewArgument(hasValuesArg()))) case opcode.PulloutIn: - predicates = append(predicates, sqlparser.NewArgument(hasValuesArg()), rhsPred) + // Because we replace the comparison expression with an AND expression, it might be the top level construct there. + // In this case, it is better to send the two sides of the AND expression separately in the predicates because it can + // lead to better routing. This however might not always be true for example we can have the rhsPred to be something like + // `user.id = 2 OR (:__sq_has_values AND user.id IN ::sql1)` + if andExpr, isAndExpr := rhsPred.(*sqlparser.AndExpr); isAndExpr { + predicates = append(predicates, andExpr.Left, andExpr.Right) + } else { + predicates = append(predicates, rhsPred) + } sq.SubqueryValueName = sq.ArgName case opcode.PulloutNotIn: - predicates = append(predicates, &sqlparser.OrExpr{ - Left: sqlparser.NewNotExpr(sqlparser.NewArgument(hasValuesArg())), - Right: rhsPred, - }) + predicates = append(predicates, rhsPred) sq.SubqueryValueName = sq.ArgName case opcode.PulloutValue: predicates = append(predicates, rhsPred) @@ -309,18 +330,3 @@ func (sq *SubQuery) mapExpr(f func(expr sqlparser.Expr) sqlparser.Expr) { sq.Original = f(sq.Original) sq.originalSubquery = f(sq.originalSubquery).(*sqlparser.Subquery) } - -func (sq *SubQuery) rewriteColNameToArgument(expr sqlparser.Expr) sqlparser.Expr { - pre := func(cursor *sqlparser.Cursor) bool { - colName, ok := cursor.Node().(*sqlparser.ColName) - if !ok || colName.Qualifier.NonEmpty() || !colName.Name.EqualString(sq.ArgName) { - // we only want to rewrite the column name to an argument if it's the right column - return true - } - - cursor.Replace(sqlparser.NewArgument(sq.ArgName)) - return true - } - - return sqlparser.Rewrite(expr, pre, nil).(sqlparser.Expr) -} diff --git a/go/vt/vtgate/planbuilder/operators/subquery_planning.go b/go/vt/vtgate/planbuilder/operators/subquery_planning.go index cdc0b8b191a..aef54bd8c41 100644 --- a/go/vt/vtgate/planbuilder/operators/subquery_planning.go +++ b/go/vt/vtgate/planbuilder/operators/subquery_planning.go @@ -56,11 +56,11 @@ func isMergeable(ctx *plancontext.PlanningContext, query sqlparser.SelectStateme // if we have grouping, we have already checked that it's safe, and don't need to check for aggregations // but if we don't have groupings, we need to check if there are aggregations that will mess with us - if ContainsAggr(ctx, node.SelectExprs) { + if ctx.ContainsAggr(node.SelectExprs) { return false } - if ContainsAggr(ctx, node.Having) { + if ctx.ContainsAggr(node.Having) { return false } @@ -364,36 +364,72 @@ func rewriteOriginalPushedToRHS(ctx *plancontext.PlanningContext, expression sql // need to find the argument name for it and use that instead // we can't use the column name directly, because we're in the RHS of the join name := outer.findOrAddColNameBindVarName(ctx, col) - cursor.Replace(sqlparser.NewArgument(name)) + typ, _ := ctx.TypeForExpr(col) + arg := sqlparser.NewTypedArgument(name, typ.Type()) + arg.Scale = typ.Scale() + arg.Size = typ.Size() + cursor.Replace(arg) }, nil) return result.(sqlparser.Expr) } -func rewriteColNameToArgument(ctx *plancontext.PlanningContext, in sqlparser.Expr, se SubQueryExpression, subqueries ...*SubQuery) sqlparser.Expr { +// rewriteColNameToArgument rewrites the column names in the expression to use the argument names instead +// this is used when we push an operator from above the subquery into the outer side of the subquery +func rewriteColNameToArgument( + ctx *plancontext.PlanningContext, + in sqlparser.Expr, // the expression to rewrite + se SubQueryExpression, // the subquery expression we are rewriting + subqueries ...*SubQuery, // the inner subquery operators +) sqlparser.Expr { + // the visitor function that will rewrite the expression tree + // it will be invoked on unqualified column names, and replace them with arguments + // when the column is representing a subquery rewriteIt := func(s string) sqlparser.SQLNode { - for _, sq1 := range se { - if sq1.ArgName != s && sq1.HasValuesName != s { - continue + var sq1, sq2 *SubQuery + for _, sq := range se { + if sq.ArgName == s || sq.HasValuesName == s { + sq1 = sq + break + } + } + for _, sq := range subqueries { + if s == sq.ArgName { + sq2 = sq + break } + } - for _, sq2 := range subqueries { - if s == sq2.ArgName { - switch { - case sq1.FilterType.NeedsListArg(): - return sqlparser.NewListArg(s) - case sq1.FilterType == opcode.PulloutExists: - if sq1.HasValuesName == "" { - sq1.HasValuesName = ctx.ReservedVars.ReserveHasValuesSubQuery() - sq2.HasValuesName = sq1.HasValuesName - } - return sqlparser.NewArgument(sq1.HasValuesName) - default: - return sqlparser.NewArgument(s) - } - } + if sq1 == nil || sq2 == nil { + return nil + } + + switch { + case sq1.FilterType.NeedsListArg(): + return sqlparser.NewListArg(s) + case sq1.FilterType == opcode.PulloutExists: + if sq1.HasValuesName == "" { + sq1.HasValuesName = ctx.ReservedVars.ReserveHasValuesSubQuery() + sq2.HasValuesName = sq1.HasValuesName + } + return sqlparser.NewArgument(sq1.HasValuesName) + default: + // for scalar value subqueries, the argument is typed based on the first expression in the subquery + // so here we make an attempt at figuring out the type of the argument + ae, isAe := sq2.originalSubquery.Select.GetColumns()[0].(*sqlparser.AliasedExpr) + if !isAe { + return sqlparser.NewArgument(s) } + + argType, found := ctx.TypeForExpr(ae.Expr) + if !found { + return sqlparser.NewArgument(s) + } + + arg := sqlparser.NewTypedArgument(s, argType.Type()) + arg.Scale = argType.Scale() + arg.Size = argType.Size() + return arg } - return nil } // replace the ColNames with Argument inside the subquery diff --git a/go/vt/vtgate/planbuilder/plancontext/planning_context.go b/go/vt/vtgate/planbuilder/plancontext/planning_context.go index 90a6bdac6f8..58be17febab 100644 --- a/go/vt/vtgate/planbuilder/plancontext/planning_context.go +++ b/go/vt/vtgate/planbuilder/plancontext/planning_context.go @@ -17,9 +17,13 @@ limitations under the License. package plancontext import ( + "io" + + "vitess.io/vitess/go/sqltypes" querypb "vitess.io/vitess/go/vt/proto/query" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/vt/vtgate/engine/opcode" "vitess.io/vitess/go/vt/vtgate/evalengine" "vitess.io/vitess/go/vt/vtgate/semantics" ) @@ -211,7 +215,12 @@ func (ctx *PlanningContext) RewriteDerivedTableExpression(expr sqlparser.Expr, t func (ctx *PlanningContext) TypeForExpr(e sqlparser.Expr) (evalengine.Type, bool) { t, found := ctx.SemTable.TypeForExpr(e) if !found { - return t, found + typ := ctx.calculateTypeFor(e) + if typ.Valid() { + ctx.SemTable.ExprTypes[e] = typ + return typ, true + } + return evalengine.NewUnknownType(), false } deps := ctx.SemTable.RecursiveDeps(e) // If the expression is from an outer table, it should be nullable @@ -222,3 +231,148 @@ func (ctx *PlanningContext) TypeForExpr(e sqlparser.Expr) (evalengine.Type, bool } return t, true } + +func (ctx *PlanningContext) calculateTypeFor(e sqlparser.Expr) evalengine.Type { + cfg := &evalengine.Config{ + ResolveType: func(expr sqlparser.Expr) (evalengine.Type, bool) { + col, isCol := expr.(*sqlparser.ColName) + if !isCol { + return evalengine.NewUnknownType(), false + } + return ctx.SemTable.TypeForExpr(col) + }, + Collation: ctx.SemTable.Collation, + Environment: ctx.VSchema.Environment(), + ResolveColumn: func(name *sqlparser.ColName) (int, error) { + // We don't need to resolve the column for type calculation + return 0, nil + }, + } + env := evalengine.EmptyExpressionEnv(ctx.VSchema.Environment()) + + // We need to rewrite the aggregate functions to their corresponding types + // The evaluation engine compiler doesn't handle them, so we replace them with Arguments before + // asking the compiler for the type + + // TODO: put this back in when we can calculate the aggregation types correctly + // expr, unknown := ctx.replaceAggrWithArg(e, cfg, env) + // if unknown { + // return evalengine.NewUnknownType() + // } + + translatedExpr, err := evalengine.Translate(e, cfg) + if err != nil { + return evalengine.NewUnknownType() + } + + typ, err := env.TypeOf(translatedExpr) + if err != nil { + return evalengine.NewUnknownType() + } + return typ +} + +// replaceAggrWithArg replaces aggregate functions with Arguments in the given expression. +// this is to prepare for sending the expression to the evalengine compiler to figure out the type +func (ctx *PlanningContext) replaceAggrWithArg(e sqlparser.Expr, cfg *evalengine.Config, env *evalengine.ExpressionEnv) (expr sqlparser.Expr, unknown bool) { + expr = sqlparser.CopyOnRewrite(e, nil, func(cursor *sqlparser.CopyOnWriteCursor) { + agg, ok := cursor.Node().(sqlparser.AggrFunc) + if !ok { + return + } + code, ok := opcode.SupportedAggregates[agg.AggrName()] + if !ok { + // We don't know the type of this aggregate function + // The type calculation will be set to unknown + unknown = true + cursor.StopTreeWalk() + return + } + var inputType evalengine.Type + if arg := agg.GetArg(); arg != nil { + translatedExpr, err := evalengine.Translate(arg, cfg) + if err != nil { + unknown = true + cursor.StopTreeWalk() + return + } + + inputType, err = env.TypeOf(translatedExpr) + if err != nil { + unknown = true + cursor.StopTreeWalk() + return + } + } + typ := code.ResolveType(inputType, ctx.VSchema.Environment().CollationEnv()) + cursor.Replace(&sqlparser.Argument{ + Name: "arg", + Type: typ.Type(), + Size: typ.Size(), + Scale: typ.Scale(), + }) + }, nil).(sqlparser.Expr) + return expr, unknown +} + +// SQLTypeForExpr returns the sql type of the given expression, with nullable set if the expression is from an outer table. +func (ctx *PlanningContext) SQLTypeForExpr(e sqlparser.Expr) sqltypes.Type { + t, found := ctx.TypeForExpr(e) + if !found { + return sqltypes.Unknown + } + return t.Type() +} + +func (ctx *PlanningContext) NeedsWeightString(e sqlparser.Expr) bool { + switch e := e.(type) { + case *sqlparser.WeightStringFuncExpr, *sqlparser.Literal: + return false + default: + typ, found := ctx.TypeForExpr(e) + if !found { + return true + } + + if !sqltypes.IsText(typ.Type()) { + return false + } + + return !ctx.VSchema.Environment().CollationEnv().IsSupported(typ.Collation()) + } +} + +func (ctx *PlanningContext) IsAggr(e sqlparser.SQLNode) bool { + switch node := e.(type) { + case sqlparser.AggrFunc: + return true + case *sqlparser.FuncExpr: + return node.Name.EqualsAnyString(ctx.VSchema.GetAggregateUDFs()) + } + + return false +} + +func (ctx *PlanningContext) ContainsAggr(e sqlparser.SQLNode) (hasAggr bool) { + _ = sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch node.(type) { + case *sqlparser.Offset: + // offsets here indicate that a possible aggregation has already been handled by an input, + // so we don't need to worry about aggregation in the original + return false, nil + case sqlparser.AggrFunc: + hasAggr = true + return false, io.EOF + case *sqlparser.Subquery: + return false, nil + case *sqlparser.FuncExpr: + if ctx.IsAggr(node) { + hasAggr = true + return false, io.EOF + } + } + + return true, nil + }, e) + return +} diff --git a/go/vt/vtgate/planbuilder/plancontext/planning_context_test.go b/go/vt/vtgate/planbuilder/plancontext/planning_context_test.go index b47286abdb2..3ab58cba724 100644 --- a/go/vt/vtgate/planbuilder/plancontext/planning_context_test.go +++ b/go/vt/vtgate/planbuilder/plancontext/planning_context_test.go @@ -17,6 +17,8 @@ limitations under the License. package plancontext import ( + "context" + "fmt" "testing" "github.com/stretchr/testify/assert" @@ -24,12 +26,81 @@ import ( "vitess.io/vitess/go/mysql/collations" "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/vt/key" + querypb "vitess.io/vitess/go/vt/proto/query" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" + vschemapb "vitess.io/vitess/go/vt/proto/vschema" + vtgatepb "vitess.io/vitess/go/vt/proto/vtgate" + "vitess.io/vitess/go/vt/vtenv" + "vitess.io/vitess/go/vt/vtgate/engine" "vitess.io/vitess/go/vt/vtgate/evalengine" + "vitess.io/vitess/go/vt/vtgate/vindexes" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vtgate/semantics" ) +func TestTyping(t *testing.T) { + // this test checks that PlanningContext can take an expression with only columns typed and + // return the type of the full expression + // col1 is a bigint, and col2 is a varchar + expr, err := sqlparser.NewTestParser().ParseExpr("sum(length(col1)) + avg(acos(col2))") + require.NoError(t, err) + semTable := semantics.EmptySemTable() + var sum, avg, col1, col2, length, acos sqlparser.Expr + + // here we walk the expression tree and fetch the two aggregate functions, and set the types for the columns + _ = sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch node := node.(type) { + case *sqlparser.ColName: + switch node.Name.String() { + case "col1": + semTable.ExprTypes[node] = evalengine.NewType(sqltypes.Int64, collations.Unknown) + col1 = node + case "col2": + semTable.ExprTypes[node] = evalengine.NewType(sqltypes.VarChar, collations.Unknown) + col2 = node + } + case *sqlparser.FuncExpr: + switch node.Name.Lowered() { + case "length": + length = node + case "acos": + acos = node + } + + case *sqlparser.Sum: + sum = node + case *sqlparser.Avg: + avg = node + } + + return true, nil + }, expr) + + ctx := createPlanContext(semTable) + + expectations := map[sqlparser.Expr]sqltypes.Type{ + // TODO: re-enable these tests once we can calculate aggregation types + // sum: sqltypes.Decimal, + // avg: sqltypes.Float64, + // expr: sqltypes.Float64, + col1: sqltypes.Int64, + col2: sqltypes.VarChar, + length: sqltypes.Int64, + acos: sqltypes.Float64, + } + fmt.Println(sum, avg, expr, acos, col1, col2) + + for expr, expected := range expectations { + t.Run(sqlparser.String(expr), func(t *testing.T) { + typ, found := ctx.TypeForExpr(expr) + require.True(t, found) + require.Equal(t, expected, typ.Type()) + }) + } +} + func TestOuterTableNullability(t *testing.T) { // Tests that columns from outer tables are nullable, // even though the semantic state says that they are not nullable. @@ -96,13 +167,202 @@ func prepareContextAndFindColumns(t *testing.T, query string) (ctx *PlanningCont return false, nil }, nil, expr) - ctx = &PlanningContext{ - SemTable: semTable, + ctx = createPlanContext(semTable) + ctx.Statement = stmt + ctx.OuterTables = t2 + + return +} + +func createPlanContext(st *semantics.SemTable) *PlanningContext { + return &PlanningContext{ + SemTable: st, joinPredicates: map[sqlparser.Expr][]sqlparser.Expr{}, skipPredicates: map[sqlparser.Expr]any{}, ReservedArguments: map[sqlparser.Expr]string{}, - Statement: stmt, - OuterTables: t2, // t2 is the outer table. + VSchema: &vschema{}, } - return } + +type vschema struct{} + +func (v *vschema) FindTable(tablename sqlparser.TableName) (*vindexes.Table, string, topodatapb.TabletType, key.Destination, error) { + // TODO implement me + panic("implement me") +} + +func (v *vschema) FindView(name sqlparser.TableName) sqlparser.SelectStatement { + // TODO implement me + panic("implement me") +} + +func (v *vschema) FindTableOrVindex(tablename sqlparser.TableName) (*vindexes.Table, vindexes.Vindex, string, topodatapb.TabletType, key.Destination, error) { + // TODO implement me + panic("implement me") +} + +func (v *vschema) DefaultKeyspace() (*vindexes.Keyspace, error) { + // TODO implement me + panic("implement me") +} + +func (v *vschema) TargetString() string { + // TODO implement me + panic("implement me") +} + +func (v *vschema) Destination() key.Destination { + // TODO implement me + panic("implement me") +} + +func (v *vschema) TabletType() topodatapb.TabletType { + // TODO implement me + panic("implement me") +} + +func (v *vschema) TargetDestination(qualifier string) (key.Destination, *vindexes.Keyspace, topodatapb.TabletType, error) { + // TODO implement me + panic("implement me") +} + +func (v *vschema) AnyKeyspace() (*vindexes.Keyspace, error) { + // TODO implement me + panic("implement me") +} + +func (v *vschema) FirstSortedKeyspace() (*vindexes.Keyspace, error) { + // TODO implement me + panic("implement me") +} + +func (v *vschema) SysVarSetEnabled() bool { + // TODO implement me + panic("implement me") +} + +func (v *vschema) KeyspaceExists(keyspace string) bool { + // TODO implement me + panic("implement me") +} + +func (v *vschema) AllKeyspace() ([]*vindexes.Keyspace, error) { + // TODO implement me + panic("implement me") +} + +func (v *vschema) FindKeyspace(keyspace string) (*vindexes.Keyspace, error) { + // TODO implement me + panic("implement me") +} + +func (v *vschema) GetSemTable() *semantics.SemTable { + // TODO implement me + panic("implement me") +} + +func (v *vschema) Planner() PlannerVersion { + // TODO implement me + panic("implement me") +} + +func (v *vschema) SetPlannerVersion(pv PlannerVersion) { + // TODO implement me + panic("implement me") +} + +func (v *vschema) ConnCollation() collations.ID { + // TODO implement me + panic("implement me") +} + +func (v *vschema) Environment() *vtenv.Environment { + return vtenv.NewTestEnv() +} + +func (v *vschema) ErrorIfShardedF(keyspace *vindexes.Keyspace, warn, errFmt string, params ...any) error { + // TODO implement me + panic("implement me") +} + +func (v *vschema) WarnUnshardedOnly(format string, params ...any) { + // TODO implement me + panic("implement me") +} + +func (v *vschema) PlannerWarning(message string) { + // TODO implement me + panic("implement me") +} + +func (v *vschema) ForeignKeyMode(keyspace string) (vschemapb.Keyspace_ForeignKeyMode, error) { + // TODO implement me + panic("implement me") +} + +func (v *vschema) KeyspaceError(keyspace string) error { + // TODO implement me + panic("implement me") +} + +func (v *vschema) GetForeignKeyChecksState() *bool { + // TODO implement me + panic("implement me") +} + +func (v *vschema) GetVSchema() *vindexes.VSchema { + // TODO implement me + panic("implement me") +} + +func (v *vschema) GetSrvVschema() *vschemapb.SrvVSchema { + // TODO implement me + panic("implement me") +} + +func (v *vschema) FindRoutedShard(keyspace, shard string) (string, error) { + // TODO implement me + panic("implement me") +} + +func (v *vschema) IsShardRoutingEnabled() bool { + // TODO implement me + panic("implement me") +} + +func (v *vschema) IsViewsEnabled() bool { + // TODO implement me + panic("implement me") +} + +func (v *vschema) GetUDV(name string) *querypb.BindVariable { + // TODO implement me + panic("implement me") +} + +func (v *vschema) PlanPrepareStatement(ctx context.Context, query string) (*engine.Plan, sqlparser.Statement, error) { + // TODO implement me + panic("implement me") +} + +func (v *vschema) ClearPrepareData(stmtName string) { + // TODO implement me + panic("implement me") +} + +func (v *vschema) GetPrepareData(stmtName string) *vtgatepb.PrepareData { + // TODO implement me + panic("implement me") +} + +func (v *vschema) StorePrepareData(name string, pd *vtgatepb.PrepareData) { + // TODO implement me + panic("implement me") +} + +func (v *vschema) GetAggregateUDFs() []string { + // TODO implement me + panic("implement me") +} + +var _ VSchema = (*vschema)(nil) diff --git a/go/vt/vtgate/planbuilder/rewrite.go b/go/vt/vtgate/planbuilder/rewrite.go index 30423229038..ef9bf099de6 100644 --- a/go/vt/vtgate/planbuilder/rewrite.go +++ b/go/vt/vtgate/planbuilder/rewrite.go @@ -18,7 +18,6 @@ package planbuilder import ( "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/vtgate/planbuilder/operators" "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" ) @@ -88,7 +87,7 @@ func (r *rewriter) rewriteHavingClause(node *sqlparser.Select) { exprs := sqlparser.SplitAndExpression(nil, node.Having.Expr) node.Having = nil for _, expr := range exprs { - if operators.ContainsAggr(r.ctx, expr) { + if r.ctx.ContainsAggr(expr) { node.AddHaving(expr) } else { node.AddWhere(expr) diff --git a/go/vt/vtgate/planbuilder/select.go b/go/vt/vtgate/planbuilder/select.go index 01dfd8aa387..6927c5315ac 100644 --- a/go/vt/vtgate/planbuilder/select.go +++ b/go/vt/vtgate/planbuilder/select.go @@ -242,11 +242,28 @@ func createSelectOperator(ctx *plancontext.PlanningContext, selStmt sqlparser.Se } func isOnlyDual(sel *sqlparser.Select) bool { - if sel.Where != nil || sel.GroupBy != nil || sel.Having != nil || sel.Limit != nil || sel.OrderBy != nil { + if sel.Where != nil || sel.GroupBy != nil || sel.Having != nil || sel.OrderBy != nil { // we can only deal with queries without any other subclauses - just SELECT and FROM, nothing else is allowed return false } + if sel.Limit != nil { + if sel.Limit.Offset != nil { + return false + } + limit := sel.Limit.Rowcount + switch limit := limit.(type) { + case nil: + case *sqlparser.Literal: + if limit.Val == "0" { + // A limit with any value other than zero can still return a row + return false + } + default: + return false + } + } + if len(sel.From) > 1 { return false } diff --git a/go/vt/vtgate/planbuilder/show.go b/go/vt/vtgate/planbuilder/show.go index 734885c9dd9..f79da3a2034 100644 --- a/go/vt/vtgate/planbuilder/show.go +++ b/go/vt/vtgate/planbuilder/show.go @@ -51,6 +51,8 @@ func buildShowPlan(sql string, stmt *sqlparser.Show, _ *sqlparser.ReservedVars, var prim engine.Primitive var err error switch show := stmt.Internal.(type) { + case *sqlparser.ShowTransactionStatus: + prim, err = buildShowTransactionStatusPlan(show, vschema) case *sqlparser.ShowBasic: prim, err = buildShowBasicPlan(show, vschema) case *sqlparser.ShowCreate: @@ -67,6 +69,13 @@ func buildShowPlan(sql string, stmt *sqlparser.Show, _ *sqlparser.ReservedVars, return newPlanResult(prim), nil } +// buildShowTransactionStatusPlan builds the transaction status plan +func buildShowTransactionStatusPlan(show *sqlparser.ShowTransactionStatus, vschema plancontext.VSchema) (engine.Primitive, error) { + return &engine.TransactionStatus{ + TransactionID: show.TransactionID, + }, nil +} + func buildShowOtherPlan(sql string, vschema plancontext.VSchema) (engine.Primitive, error) { ks, err := vschema.AnyKeyspace() if err != nil { diff --git a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json index dac95cfa51f..eca27d81213 100644 --- a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json @@ -667,9 +667,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select col1, min(col2) as `min(distinct col2)`, weight_string(col1), weight_string(col2) from `user` where 1 != 1 group by col1, weight_string(col1), weight_string(col2)", + "FieldQuery": "select col1, min(col2) as `min(distinct col2)`, weight_string(col1), weight_string(min(col2)) from `user` where 1 != 1 group by col1, weight_string(col1)", "OrderBy": "(0|2) ASC", - "Query": "select col1, min(col2) as `min(distinct col2)`, weight_string(col1), weight_string(col2) from `user` group by col1, weight_string(col1), weight_string(col2) order by col1 asc", + "Query": "select col1, min(col2) as `min(distinct col2)`, weight_string(col1), weight_string(min(col2)) from `user` group by col1, weight_string(col1) order by col1 asc", "Table": "`user`" } ] @@ -760,6 +760,58 @@ ] } }, + { + "comment": "Aggregation with derived table", + "query": "select u.id, u.name, t.num_segments from (select id, count(*) as num_segments from user group by 1 order by 2 desc limit 20) t join unsharded u on u.id = t.id", + "plan": { + "QueryType": "SELECT", + "Original": "select u.id, u.name, t.num_segments from (select id, count(*) as num_segments from user group by 1 order by 2 desc limit 20) t join unsharded u on u.id = t.id", + "Instructions": { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "R:0,R:1,L:0", + "JoinVars": { + "t_id": 1 + }, + "TableName": "`user`_unsharded", + "Inputs": [ + { + "OperatorType": "Limit", + "Count": "20", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select t.num_segments, t.id from (select id, count(*) as num_segments from `user` where 1 != 1 group by id) as t where 1 != 1", + "OrderBy": "0 DESC", + "Query": "select t.num_segments, t.id from (select id, count(*) as num_segments from `user` group by id) as t order by t.num_segments desc limit 20", + "Table": "`user`" + } + ] + }, + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select u.id, u.`name` from unsharded as u where 1 != 1", + "Query": "select u.id, u.`name` from unsharded as u where u.id = :t_id", + "Table": "unsharded" + } + ] + }, + "TablesUsed": [ + "main.unsharded", + "user.user" + ] + } + }, { "comment": "scatter aggregate multiple group by (numbers)", "query": "select a, b, count(*) from user group by 2, 1", @@ -824,6 +876,66 @@ ] } }, + { + "comment": "group concat with a separator needing evaluation on vtgate", + "query": "select group_concat(music.name SEPARATOR ', ') as `Group Name` from user join user_extra on user.id = user_extra.user_id left join music on user.id = music.id group by user.id;", + "plan": { + "QueryType": "SELECT", + "Original": "select group_concat(music.name SEPARATOR ', ') as `Group Name` from user join user_extra on user.id = user_extra.user_id left join music on user.id = music.id group by user.id;", + "Instructions": { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "Aggregates": "group_concat(0) AS Group Name", + "GroupBy": "(1|2)", + "ResultColumns": 1, + "Inputs": [ + { + "OperatorType": "Join", + "Variant": "LeftJoin", + "JoinColumnIndexes": "R:0,L:0,L:1", + "JoinVars": { + "user_id": 0 + }, + "TableName": "`user`, user_extra_music", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select `user`.id, weight_string(`user`.id) from `user`, user_extra where 1 != 1", + "OrderBy": "(0|1) ASC", + "Query": "select `user`.id, weight_string(`user`.id) from `user`, user_extra where `user`.id = user_extra.user_id order by `user`.id asc", + "Table": "`user`, user_extra" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select music.`name` from music where 1 != 1", + "Query": "select music.`name` from music where music.id = :user_id", + "Table": "music", + "Values": [ + ":user_id" + ], + "Vindex": "music_user_map" + } + ] + } + ] + }, + "TablesUsed": [ + "user.music", + "user.user", + "user.user_extra" + ] + } + }, { "comment": "scatter aggregate group by column number", "query": "select col from user group by 1", @@ -972,9 +1084,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select a, b, c, d, count(*), weight_string(d), weight_string(b), weight_string(a), weight_string(c) from `user` where 1 != 1 group by d, b, a, c, weight_string(d), weight_string(b), weight_string(a), weight_string(c)", + "FieldQuery": "select a, b, c, d, count(*), weight_string(d), weight_string(b), weight_string(a), weight_string(c) from `user` where 1 != 1 group by a, b, c, d, weight_string(d), weight_string(b), weight_string(a), weight_string(c)", "OrderBy": "(3|5) ASC, (1|6) ASC, (0|7) ASC, (2|8) ASC", - "Query": "select a, b, c, d, count(*), weight_string(d), weight_string(b), weight_string(a), weight_string(c) from `user` group by d, b, a, c, weight_string(d), weight_string(b), weight_string(a), weight_string(c) order by `user`.d asc, `user`.b asc, `user`.a asc, `user`.c asc", + "Query": "select a, b, c, d, count(*), weight_string(d), weight_string(b), weight_string(a), weight_string(c) from `user` group by a, b, c, d, weight_string(d), weight_string(b), weight_string(a), weight_string(c) order by `user`.d asc, `user`.b asc, `user`.a asc, `user`.c asc", "Table": "`user`" } ] @@ -1004,9 +1116,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select a, b, c, d, count(*), weight_string(d), weight_string(b), weight_string(a), weight_string(c) from `user` where 1 != 1 group by d, b, a, c, weight_string(d), weight_string(b), weight_string(a), weight_string(c)", + "FieldQuery": "select a, b, c, d, count(*), weight_string(d), weight_string(b), weight_string(a), weight_string(c) from `user` where 1 != 1 group by c, b, a, d, weight_string(d), weight_string(b), weight_string(a), weight_string(c)", "OrderBy": "(3|5) ASC, (1|6) ASC, (0|7) ASC, (2|8) ASC", - "Query": "select a, b, c, d, count(*), weight_string(d), weight_string(b), weight_string(a), weight_string(c) from `user` group by d, b, a, c, weight_string(d), weight_string(b), weight_string(a), weight_string(c) order by `user`.d asc, `user`.b asc, `user`.a asc, `user`.c asc", + "Query": "select a, b, c, d, count(*), weight_string(d), weight_string(b), weight_string(a), weight_string(c) from `user` group by c, b, a, d, weight_string(d), weight_string(b), weight_string(a), weight_string(c) order by `user`.d asc, `user`.b asc, `user`.a asc, `user`.c asc", "Table": "`user`" } ] @@ -1036,9 +1148,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select a, b, c, count(*), weight_string(a), weight_string(c), weight_string(b) from `user` where 1 != 1 group by a, c, b, weight_string(a), weight_string(c), weight_string(b)", + "FieldQuery": "select a, b, c, count(*), weight_string(a), weight_string(c), weight_string(b) from `user` where 1 != 1 group by c, b, a, weight_string(a), weight_string(c), weight_string(b)", "OrderBy": "(0|4) DESC, (2|5) DESC, (1|6) ASC", - "Query": "select a, b, c, count(*), weight_string(a), weight_string(c), weight_string(b) from `user` group by a, c, b, weight_string(a), weight_string(c), weight_string(b) order by a desc, c desc, `user`.b asc", + "Query": "select a, b, c, count(*), weight_string(a), weight_string(c), weight_string(b) from `user` group by c, b, a, weight_string(a), weight_string(c), weight_string(b) order by a desc, c desc, `user`.b asc", "Table": "`user`" } ] @@ -1615,8 +1727,7 @@ "OperatorType": "Aggregate", "Variant": "Ordered", "Aggregates": "sum_count_star(1) AS count(*)", - "GroupBy": "(0|2)", - "ResultColumns": 2, + "GroupBy": "0 COLLATE latin1_swedish_ci", "Inputs": [ { "OperatorType": "Route", @@ -1625,9 +1736,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select lower(col1) as v, count(*), weight_string(lower(col1)) from authoritative where 1 != 1 group by lower(col1), weight_string(lower(col1))", - "OrderBy": "(0|2) ASC", - "Query": "select lower(col1) as v, count(*), weight_string(lower(col1)) from authoritative group by lower(col1), weight_string(lower(col1)) order by lower(col1) asc", + "FieldQuery": "select lower(col1) as v, count(*) from authoritative where 1 != 1 group by lower(col1)", + "OrderBy": "0 ASC COLLATE latin1_swedish_ci", + "Query": "select lower(col1) as v, count(*) from authoritative group by lower(col1) order by lower(col1) asc", "Table": "authoritative" } ] @@ -1647,8 +1758,7 @@ "OperatorType": "Aggregate", "Variant": "Ordered", "Aggregates": "sum_count_star(1) AS count(*)", - "GroupBy": "(0|2)", - "ResultColumns": 2, + "GroupBy": "0", "Inputs": [ { "OperatorType": "Route", @@ -1657,9 +1767,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select char_length(col1) as a, count(*), weight_string(char_length(col1)) from authoritative where 1 != 1 group by char_length(col1), weight_string(char_length(col1))", - "OrderBy": "(0|2) ASC", - "Query": "select char_length(col1) as a, count(*), weight_string(char_length(col1)) from authoritative group by char_length(col1), weight_string(char_length(col1)) order by char_length(authoritative.col1) asc", + "FieldQuery": "select char_length(col1) as a, count(*) from authoritative where 1 != 1 group by char_length(col1)", + "OrderBy": "0 ASC", + "Query": "select char_length(col1) as a, count(*) from authoritative group by char_length(col1) order by char_length(authoritative.col1) asc", "Table": "authoritative" } ] @@ -2106,6 +2216,54 @@ ] } }, + { + "comment": "User defined aggregation expression being used in order by of a query that is single sharded", + "query": "select col1, udf_aggr( col2 ) r from user where id = 1 group by col1 having r >= 0.3", + "plan": { + "QueryType": "SELECT", + "Original": "select col1, udf_aggr( col2 ) r from user where id = 1 group by col1 having r >= 0.3", + "Instructions": { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select col1, udf_aggr(col2) as r from `user` where 1 != 1 group by col1", + "Query": "select col1, udf_aggr(col2) as r from `user` where id = 1 group by col1 having udf_aggr(`user`.col2) >= 0.3", + "Table": "`user`", + "Values": [ + "1" + ], + "Vindex": "user_index" + }, + "TablesUsed": [ + "user.user" + ] + } + }, + { + "comment": "user defined aggregation such that it can pushed to mysql in a scatter route", + "query": "select id, udf_aggr( col2 ) r from user group by id", + "plan": { + "QueryType": "SELECT", + "Original": "select id, udf_aggr( col2 ) r from user group by id", + "Instructions": { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, udf_aggr(col2) as r from `user` where 1 != 1 group by id", + "Query": "select id, udf_aggr(col2) as r from `user` group by id", + "Table": "`user`" + }, + "TablesUsed": [ + "user.user" + ] + } + }, { "comment": "distinct on text column with collation", "query": "select col, count(distinct textcol1) from user group by col", @@ -2545,9 +2703,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select col1, min(id) as `min(distinct id)`, col3, weight_string(col1), weight_string(id), weight_string(col3) from `user` where 1 != 1 group by col1, col3, weight_string(col1), weight_string(id), weight_string(col3)", + "FieldQuery": "select col1, min(id) as `min(distinct id)`, col3, weight_string(col1), weight_string(min(id)), weight_string(col3) from `user` where 1 != 1 group by col1, col3, weight_string(col1), weight_string(col3)", "OrderBy": "(0|3) ASC, (2|5) ASC", - "Query": "select col1, min(id) as `min(distinct id)`, col3, weight_string(col1), weight_string(id), weight_string(col3) from `user` group by col1, col3, weight_string(col1), weight_string(id), weight_string(col3) order by col1 asc, col3 asc", + "Query": "select col1, min(id) as `min(distinct id)`, col3, weight_string(col1), weight_string(min(id)), weight_string(col3) from `user` group by col1, col3, weight_string(col1), weight_string(col3) order by col1 asc, col3 asc", "Table": "`user`" } ] @@ -3312,7 +3470,7 @@ "Sharded": true }, "FieldQuery": "select 1 from user_extra where 1 != 1 group by .0", - "Query": "select 1 from user_extra where user_extra.col = :user_col group by .0", + "Query": "select 1 from user_extra where user_extra.col = :user_col /* INT16 */ group by .0", "Table": "user_extra" } ] @@ -3592,7 +3750,7 @@ }, "FieldQuery": "select x.id, x.val1, 1, weight_string(x.val1) from (select id, val1 from `user` where 1 != 1) as x where 1 != 1", "OrderBy": "(1|3) ASC", - "Query": "select x.id, x.val1, 1, weight_string(x.val1) from (select id, val1 from `user` where val2 < 4) as x order by `user`.val1 asc limit 2", + "Query": "select x.id, x.val1, 1, weight_string(x.val1) from (select id, val1 from `user` where val2 < 4) as x order by x.val1 asc limit 2", "Table": "`user`" } ] @@ -3802,7 +3960,7 @@ "Sharded": true }, "FieldQuery": "select count(*) from user_extra as ue where 1 != 1 group by .0", - "Query": "select count(*) from user_extra as ue where ue.col = :u_col group by .0", + "Query": "select count(*) from user_extra as ue where ue.col = :u_col /* INT16 */ group by .0", "Table": "user_extra" } ] @@ -3862,7 +4020,7 @@ "Sharded": true }, "FieldQuery": "select count(ue.id) from user_extra as ue where 1 != 1 group by .0", - "Query": "select count(ue.id) from user_extra as ue where ue.col = :u_col group by .0", + "Query": "select count(ue.id) from user_extra as ue where ue.col = :u_col /* INT16 */ group by .0", "Table": "user_extra" } ] @@ -3963,9 +4121,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select foo, max(baz) as bazo, weight_string(foo), weight_string(baz) from (select foo, baz from `user` where 1 != 1) as f where 1 != 1 group by foo, weight_string(foo), weight_string(baz)", + "FieldQuery": "select foo, max(baz) as bazo, weight_string(foo), weight_string(max(baz)) from (select foo, baz from `user` where 1 != 1) as f where 1 != 1 group by foo, weight_string(foo)", "OrderBy": "(0|2) ASC", - "Query": "select foo, max(baz) as bazo, weight_string(foo), weight_string(baz) from (select foo, baz from `user`) as f group by foo, weight_string(foo), weight_string(baz) order by foo asc", + "Query": "select foo, max(baz) as bazo, weight_string(foo), weight_string(max(baz)) from (select foo, baz from `user`) as f group by foo, weight_string(foo) order by foo asc", "Table": "`user`" } ] @@ -4025,13 +4183,13 @@ "Instructions": { "OperatorType": "Sort", "Variant": "Memory", - "OrderBy": "(2|3) ASC", + "OrderBy": "2 ASC", "ResultColumns": 2, "Inputs": [ { "OperatorType": "Aggregate", "Variant": "Ordered", - "Aggregates": "sum_count_star(1) AS count(*), any_value(2) AS col + 1, any_value(3)", + "Aggregates": "sum_count_star(1) AS count(*), any_value(2) AS col + 1", "GroupBy": "0", "Inputs": [ { @@ -4041,9 +4199,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select col, count(*), col + 1, weight_string(col + 1) from `user` where 1 != 1 group by col", + "FieldQuery": "select col, count(*), col + 1 from `user` where 1 != 1 group by col", "OrderBy": "0 ASC", - "Query": "select col, count(*), col + 1, weight_string(col + 1) from `user` group by col order by col asc", + "Query": "select col, count(*), col + 1 from `user` group by col order by col asc", "Table": "`user`" } ] @@ -4699,8 +4857,8 @@ { "OperatorType": "Projection", "Expressions": [ - ":3 as col", - ":2 as intcol", + ":2 as col", + ":3 as intcol", "count(*) * count(*) as count(*)" ], "Inputs": [ @@ -4717,9 +4875,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select count(*), u.intcol, u.col from `user` as u where 1 != 1 group by u.intcol, u.col", - "OrderBy": "1 ASC, 2 ASC", - "Query": "select count(*), u.intcol, u.col from `user` as u group by u.intcol, u.col order by u.intcol asc, u.col asc", + "FieldQuery": "select count(*), u.col, u.intcol from `user` as u where 1 != 1 group by u.col, u.intcol", + "OrderBy": "2 ASC, 1 ASC", + "Query": "select count(*), u.col, u.intcol from `user` as u group by u.col, u.intcol order by u.intcol asc, u.col asc", "Table": "`user`" }, { @@ -4889,9 +5047,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select min(textcol1), max(textcol2), textcol1, textcol1, weight_string(textcol2) from `user` where 1 != 1 group by textcol1, weight_string(textcol2)", + "FieldQuery": "select min(textcol1), max(textcol2), textcol1, textcol1, weight_string(max(textcol2)) from `user` where 1 != 1 group by textcol1", "OrderBy": "2 ASC COLLATE latin1_swedish_ci", - "Query": "select min(textcol1), max(textcol2), textcol1, textcol1, weight_string(textcol2) from `user` group by textcol1, weight_string(textcol2) order by textcol1 asc", + "Query": "select min(textcol1), max(textcol2), textcol1, textcol1, weight_string(max(textcol2)) from `user` group by textcol1 order by textcol1 asc", "Table": "`user`" } ] @@ -4921,9 +5079,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select col, min(textcol1), max(textcol2), textcol1, textcol1, weight_string(textcol2) from `user` where 1 != 1 group by col, textcol1, weight_string(textcol2)", + "FieldQuery": "select col, min(textcol1), max(textcol2), textcol1, textcol1, weight_string(max(textcol2)) from `user` where 1 != 1 group by col, textcol1", "OrderBy": "0 ASC, 3 ASC COLLATE latin1_swedish_ci", - "Query": "select col, min(textcol1), max(textcol2), textcol1, textcol1, weight_string(textcol2) from `user` group by col, textcol1, weight_string(textcol2) order by col asc, textcol1 asc", + "Query": "select col, min(textcol1), max(textcol2), textcol1, textcol1, weight_string(max(textcol2)) from `user` group by col, textcol1 order by col asc, textcol1 asc", "Table": "`user`" } ] @@ -5093,7 +5251,7 @@ "Sharded": true }, "FieldQuery": "select min(user_extra.foo), max(user_extra.bar), weight_string(user_extra.foo), weight_string(user_extra.bar) from user_extra where 1 != 1 group by .0, weight_string(user_extra.foo), weight_string(user_extra.bar)", - "Query": "select min(user_extra.foo), max(user_extra.bar), weight_string(user_extra.foo), weight_string(user_extra.bar) from user_extra where user_extra.bar = :user_col group by .0, weight_string(user_extra.foo), weight_string(user_extra.bar)", + "Query": "select min(user_extra.foo), max(user_extra.bar), weight_string(user_extra.foo), weight_string(user_extra.bar) from user_extra where user_extra.bar = :user_col /* INT16 */ group by .0, weight_string(user_extra.foo), weight_string(user_extra.bar)", "Table": "user_extra" } ] @@ -5264,8 +5422,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select count(*), :user_id + user_extra.id, weight_string(:user_id + user_extra.id) from user_extra where 1 != 1 group by :user_id + user_extra.id", - "Query": "select count(*), :user_id + user_extra.id, weight_string(:user_id + user_extra.id) from user_extra group by :user_id + user_extra.id", + "FieldQuery": "select count(*), :user_id + user_extra.id, weight_string(:user_id + user_extra.id) from user_extra where 1 != 1 group by :user_id + user_extra.id, weight_string(:user_id + user_extra.id)", + "Query": "select count(*), :user_id + user_extra.id, weight_string(:user_id + user_extra.id) from user_extra group by :user_id + user_extra.id, weight_string(:user_id + user_extra.id)", "Table": "user_extra" } ] @@ -5371,7 +5529,7 @@ "Sharded": true }, "FieldQuery": "select count(*), sum(user_extra.bar) from user_extra where 1 != 1 group by .0", - "Query": "select count(*), sum(user_extra.bar) from user_extra where user_extra.col = :user_col group by .0", + "Query": "select count(*), sum(user_extra.bar) from user_extra where user_extra.col = :user_col /* INT16 */ group by .0", "Table": "user_extra" } ] @@ -5721,7 +5879,7 @@ "Sharded": true }, "FieldQuery": "select 1 from music as m where 1 != 1", - "Query": "select 1 from music as m where m.col = :u_col", + "Query": "select 1 from music as m where m.col = :u_col /* INT16 */", "Table": "music" } ] @@ -5808,9 +5966,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select foo, min(bar) as `min(distinct bar)`, baz, baz, max(toto) as `max(distinct toto)`, weight_string(foo), weight_string(bar), weight_string(baz), weight_string(toto) from `user` where 1 != 1 group by foo, baz, weight_string(foo), weight_string(bar), weight_string(baz), weight_string(toto)", + "FieldQuery": "select foo, min(bar) as `min(distinct bar)`, baz, baz, max(toto) as `max(distinct toto)`, weight_string(foo), weight_string(min(bar)), weight_string(baz), weight_string(max(toto)) from `user` where 1 != 1 group by foo, baz, weight_string(foo), weight_string(baz)", "OrderBy": "(0|5) ASC, (2|7) ASC", - "Query": "select foo, min(bar) as `min(distinct bar)`, baz, baz, max(toto) as `max(distinct toto)`, weight_string(foo), weight_string(bar), weight_string(baz), weight_string(toto) from `user` group by foo, baz, weight_string(foo), weight_string(bar), weight_string(baz), weight_string(toto) order by foo asc, baz asc", + "Query": "select foo, min(bar) as `min(distinct bar)`, baz, baz, max(toto) as `max(distinct toto)`, weight_string(foo), weight_string(min(bar)), weight_string(baz), weight_string(max(toto)) from `user` group by foo, baz, weight_string(foo), weight_string(baz) order by foo asc, baz asc", "Table": "`user`" } ] @@ -6054,8 +6212,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select :__sq1 + :__sq2 as `(select count(*) from ``user``) + (select count(*) from user_extra)` from dual where 1 != 1", - "Query": "select :__sq1 + :__sq2 as `(select count(*) from ``user``) + (select count(*) from user_extra)` from dual", + "FieldQuery": "select :__sq1 /* INT64 */ + :__sq2 /* INT64 */ as `(select count(*) from ``user``) + (select count(*) from user_extra)` from dual where 1 != 1", + "Query": "select :__sq1 /* INT64 */ + :__sq2 /* INT64 */ as `(select count(*) from ``user``) + (select count(*) from user_extra)` from dual", "Table": "dual" } ] @@ -6364,7 +6522,7 @@ { "OperatorType": "Aggregate", "Variant": "Scalar", - "Aggregates": "min(0|2) AS min_id, max(1|2) AS max_id", + "Aggregates": "min(0|2) AS min_id, max(1|3) AS max_id", "ResultColumns": 2, "Inputs": [ { @@ -6374,9 +6532,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select min(bb.id) as min_id, max(bb.id) as max_id, weight_string(bb.id) from `user` as bb where 1 != 1 group by weight_string(bb.id)", + "FieldQuery": "select min(bb.id) as min_id, max(bb.id) as max_id, weight_string(min(bb.id)), weight_string(max(bb.id)) from `user` as bb where 1 != 1", "OrderBy": "0 ASC COLLATE utf8mb4_0900_ai_ci", - "Query": "select min(bb.id) as min_id, max(bb.id) as max_id, weight_string(bb.id) from `user` as bb group by weight_string(bb.id) order by min(bb.id) asc", + "Query": "select min(bb.id) as min_id, max(bb.id) as max_id, weight_string(min(bb.id)), weight_string(max(bb.id)) from `user` as bb order by min(bb.id) asc", "Table": "`user`" } ] @@ -6704,8 +6862,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select max(:__sq1), weight_string(:__sq1) from `user` where 1 != 1 group by weight_string(:__sq1)", - "Query": "select max(:__sq1), weight_string(:__sq1) from `user` where id = 2 group by weight_string(:__sq1)", + "FieldQuery": "select max(:__sq1 /* INT16 */), weight_string(:__sq1 /* INT16 */) from `user` where 1 != 1 group by weight_string(:__sq1 /* INT16 */)", + "Query": "select max(:__sq1 /* INT16 */), weight_string(:__sq1 /* INT16 */) from `user` where id = 2 group by weight_string(:__sq1 /* INT16 */)", "Table": "`user`", "Values": [ "2" @@ -6849,8 +7007,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select max((select max(col2) from `user` as u1 where 1 != 1)), weight_string((select max(col2) from `user` as u1 where 1 != 1)) from `user` as u2 where 1 != 1 group by weight_string((select max(col2) from `user` as u1 where 1 != 1))", - "Query": "select max((select max(col2) from `user` as u1 where u1.id = u2.id)), weight_string((select max(col2) from `user` as u1 where u1.id = u2.id)) from `user` as u2 group by weight_string((select max(col2) from `user` as u1 where u1.id = u2.id))", + "FieldQuery": "select max((select max(col2) from `user` as u1 where 1 != 1)), weight_string(max((select max(col2) from `user` as u1 where 1 != 1))) from `user` as u2 where 1 != 1", + "Query": "select max((select max(col2) from `user` as u1 where u1.id = u2.id)), weight_string(max((select max(col2) from `user` as u1 where u1.id = u2.id))) from `user` as u2", "Table": "`user`" } ] @@ -7085,5 +7243,119 @@ "user.user" ] } + }, + { + "comment": "Aggregation over a ORDER BY/LIMIT inside a derived table", + "query": "SELECT COUNT(*) FROM (SELECT 1 AS one FROM `user` WHERE `user`.`is_not_deleted` = true ORDER BY id DESC LIMIT 25 OFFSET 0) subquery_for_count", + "plan": { + "QueryType": "SELECT", + "Original": "SELECT COUNT(*) FROM (SELECT 1 AS one FROM `user` WHERE `user`.`is_not_deleted` = true ORDER BY id DESC LIMIT 25 OFFSET 0) subquery_for_count", + "Instructions": { + "OperatorType": "Aggregate", + "Variant": "Scalar", + "Aggregates": "count_star(0) AS count(*)", + "Inputs": [ + { + "OperatorType": "SimpleProjection", + "Columns": "2", + "Inputs": [ + { + "OperatorType": "Limit", + "Count": "25", + "Offset": "0", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select subquery_for_count.one, subquery_for_count.id, 1, weight_string(subquery_for_count.id) from (select 1 as one, id from `user` where 1 != 1) as subquery_for_count where 1 != 1", + "OrderBy": "(1|3) DESC", + "Query": "select subquery_for_count.one, subquery_for_count.id, 1, weight_string(subquery_for_count.id) from (select 1 as one, id from `user` where `user`.is_not_deleted = true) as subquery_for_count order by subquery_for_count.id desc limit 25", + "Table": "`user`" + } + ] + } + ] + } + ] + }, + "TablesUsed": [ + "user.user" + ] + } + }, + { + "comment": "should be able to push down aggregation", + "query": "select sum(user.type) from user join user_extra on user.team_id = user_extra.id group by user_extra.id order by user_extra.id", + "plan": { + "QueryType": "SELECT", + "Original": "select sum(user.type) from user join user_extra on user.team_id = user_extra.id group by user_extra.id order by user_extra.id", + "Instructions": { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "Aggregates": "sum(0) AS sum(`user`.type)", + "GroupBy": "(1|2)", + "ResultColumns": 1, + "Inputs": [ + { + "OperatorType": "Projection", + "Expressions": [ + "sum(`user`.type) * count(*) as sum(`user`.type)", + ":2 as id", + ":3 as weight_string(user_extra.id)" + ], + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(2|3) ASC", + "Inputs": [ + { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,R:0,R:1,R:2", + "JoinVars": { + "user_team_id": 1 + }, + "TableName": "`user`_user_extra", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select sum(`user`.type), `user`.team_id from `user` where 1 != 1 group by `user`.team_id", + "Query": "select sum(`user`.type), `user`.team_id from `user` group by `user`.team_id", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select count(*), user_extra.id, weight_string(user_extra.id) from user_extra where 1 != 1 group by user_extra.id, weight_string(user_extra.id)", + "Query": "select count(*), user_extra.id, weight_string(user_extra.id) from user_extra where user_extra.id = :user_team_id group by user_extra.id, weight_string(user_extra.id)", + "Table": "user_extra" + } + ] + } + ] + } + ] + } + ] + }, + "TablesUsed": [ + "user.user", + "user.user_extra" + ] + } } ] diff --git a/go/vt/vtgate/planbuilder/testdata/cte_cases.json b/go/vt/vtgate/planbuilder/testdata/cte_cases.json index 09d155b19f6..1fd398012e3 100644 --- a/go/vt/vtgate/planbuilder/testdata/cte_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/cte_cases.json @@ -352,7 +352,7 @@ }, "FieldQuery": "select x.id, x.val1, 1, weight_string(x.val1) from (select id, val1 from `user` where 1 != 1) as x where 1 != 1", "OrderBy": "(1|3) ASC", - "Query": "select x.id, x.val1, 1, weight_string(x.val1) from (select id, val1 from `user` where val2 < 4) as x order by `user`.val1 asc limit 2", + "Query": "select x.id, x.val1, 1, weight_string(x.val1) from (select id, val1 from `user` where val2 < 4) as x order by x.val1 asc limit 2", "Table": "`user`" } ] @@ -488,9 +488,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select foo, max(baz) as bazo, weight_string(foo), weight_string(baz) from (select foo, baz from `user` where 1 != 1) as f where 1 != 1 group by foo, weight_string(foo), weight_string(baz)", + "FieldQuery": "select foo, max(baz) as bazo, weight_string(foo), weight_string(max(baz)) from (select foo, baz from `user` where 1 != 1) as f where 1 != 1 group by foo, weight_string(foo)", "OrderBy": "(0|2) ASC", - "Query": "select foo, max(baz) as bazo, weight_string(foo), weight_string(baz) from (select foo, baz from `user`) as f group by foo, weight_string(foo), weight_string(baz) order by foo asc", + "Query": "select foo, max(baz) as bazo, weight_string(foo), weight_string(max(baz)) from (select foo, baz from `user`) as f group by foo, weight_string(foo) order by foo asc", "Table": "`user`" } ] @@ -1132,7 +1132,7 @@ "Sharded": true }, "FieldQuery": "select 1 from user_extra where 1 != 1", - "Query": "select 1 from user_extra where user_extra.col = :user_col", + "Query": "select 1 from user_extra where user_extra.col = :user_col /* INT16 */", "Table": "user_extra" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/dml_cases.json b/go/vt/vtgate/planbuilder/testdata/dml_cases.json index 9c2ed1920ee..b5d0fa8951f 100644 --- a/go/vt/vtgate/planbuilder/testdata/dml_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/dml_cases.json @@ -5165,7 +5165,7 @@ "Sharded": true }, "FieldQuery": "select 1 from music as m where 1 != 1", - "Query": "select 1 from music as m where m.col = :u_col", + "Query": "select 1 from music as m where m.col = :u_col /* INT16 */", "Table": "music" } ] @@ -5335,7 +5335,7 @@ "Sharded": true }, "FieldQuery": "select 1 from music as m, user_extra as ue where 1 != 1", - "Query": "select 1 from music as m, user_extra as ue where m.bar = 40 and m.col = :u_col and ue.foo = 20 and m.user_id = ue.user_id", + "Query": "select 1 from music as m, user_extra as ue where m.bar = 40 and m.col = :u_col /* INT16 */ and ue.foo = 20 and m.user_id = ue.user_id", "Table": "music, user_extra" } ] @@ -5408,7 +5408,7 @@ "Sharded": true }, "FieldQuery": "select m.id from music as m, user_extra as ue where 1 != 1", - "Query": "select m.id from music as m, user_extra as ue where m.bar = 40 and m.col = :u_col and ue.foo = 20 and m.user_id = ue.user_id", + "Query": "select m.id from music as m, user_extra as ue where m.bar = 40 and m.col = :u_col /* INT16 */ and ue.foo = 20 and m.user_id = ue.user_id", "Table": "music, user_extra" } ] @@ -5880,7 +5880,7 @@ "Sharded": true }, "TargetTabletType": "PRIMARY", - "Query": "update `user` as u set u.col = :ue_col where u.id in ::dml_vals", + "Query": "update `user` as u set u.col = :ue_col /* INT16 */ where u.id in ::dml_vals", "Table": "user", "Values": [ "::dml_vals" @@ -6483,7 +6483,7 @@ "Sharded": true }, "FieldQuery": "select m.id from music as m where 1 != 1", - "Query": "select m.id from music as m where m.baz = 21 and m.bar = :u_foo and m.col = :u_col for update", + "Query": "select m.id from music as m where m.baz = 21 and m.bar = :u_foo and m.col = :u_col /* INT16 */ for update", "Table": "music" } ] @@ -6738,7 +6738,7 @@ "Sharded": true }, "FieldQuery": "select m.id from music as m where 1 != 1", - "Query": "select m.id from music as m where m.col = :u_col for update", + "Query": "select m.id from music as m where m.col = :u_col /* INT16 */ for update", "Table": "music" } ] @@ -6961,7 +6961,7 @@ "Sharded": true }, "FieldQuery": "select m.id from music as m where 1 != 1", - "Query": "select m.id from music as m where m.col = :u_col for update", + "Query": "select m.id from music as m where m.col = :u_col /* INT16 */ for update", "Table": "music" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/filter_cases.json b/go/vt/vtgate/planbuilder/testdata/filter_cases.json index d36c060ed6d..b60e8812dda 100644 --- a/go/vt/vtgate/planbuilder/testdata/filter_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/filter_cases.json @@ -1141,7 +1141,7 @@ "Sharded": true }, "FieldQuery": "select user_extra.id from user_extra where 1 != 1", - "Query": "select user_extra.id from user_extra where user_extra.col = :user_col", + "Query": "select user_extra.id from user_extra where user_extra.col = :user_col /* INT16 */", "Table": "user_extra" } ] @@ -1213,7 +1213,7 @@ "Sharded": true }, "FieldQuery": "select user_extra.id from user_extra where 1 != 1", - "Query": "select user_extra.id from user_extra where user_extra.user_id = :user_col and user_extra.col = :user_col", + "Query": "select user_extra.id from user_extra where user_extra.user_id = :user_col /* INT16 */ and user_extra.col = :user_col /* INT16 */", "Table": "user_extra", "Values": [ ":user_col" @@ -1262,7 +1262,7 @@ "Sharded": true }, "FieldQuery": "select user_extra.id from user_extra where 1 != 1", - "Query": "select user_extra.id from user_extra where user_extra.col = :user_col and 1 = 1", + "Query": "select user_extra.id from user_extra where user_extra.col = :user_col /* INT16 */ and 1 = 1", "Table": "user_extra" } ] @@ -1614,7 +1614,7 @@ "Sharded": true }, "FieldQuery": "select u.m from `user` as u where 1 != 1", - "Query": "select u.m from `user` as u where u.id in ::__vals and u.id in (select m2 from `user` where `user`.id = u.id and `user`.col = :user_extra_col)", + "Query": "select u.m from `user` as u where u.id in ::__vals and u.id in (select m2 from `user` where `user`.id = u.id and `user`.col = :user_extra_col /* INT16 */)", "Table": "`user`", "Values": [ "(:user_extra_col, 1)" @@ -1758,7 +1758,7 @@ "Sharded": true }, "FieldQuery": "select u.m from `user` as u where 1 != 1", - "Query": "select u.m from `user` as u where u.id in ::__vals and u.id in (select m2 from `user` where `user`.id = u.id and `user`.col = :user_extra_col and `user`.id in (select m3 from user_extra where user_extra.user_id = `user`.id))", + "Query": "select u.m from `user` as u where u.id in ::__vals and u.id in (select m2 from `user` where `user`.id = u.id and `user`.col = :user_extra_col /* INT16 */ and `user`.id in (select m3 from user_extra where user_extra.user_id = `user`.id))", "Table": "`user`", "Values": [ "(:user_extra_col, 1)" @@ -3100,7 +3100,7 @@ "Sharded": true }, "FieldQuery": "select id from `user` where 1 != 1", - "Query": "select id from `user` where `user`.id = :user_extra_col", + "Query": "select id from `user` where `user`.id = :user_extra_col /* INT16 */", "Table": "`user`", "Values": [ ":user_extra_col" @@ -3171,7 +3171,7 @@ "Sharded": true }, "FieldQuery": "select 1 from user_extra where 1 != 1", - "Query": "select 1 from user_extra where user_extra.foobar = 5 and user_extra.col = :user_col", + "Query": "select 1 from user_extra where user_extra.foobar = 5 and user_extra.col = :user_col /* INT16 */", "Table": "user_extra" } ] @@ -3226,7 +3226,7 @@ "Sharded": true }, "FieldQuery": "select user_extra.id from user_extra where 1 != 1", - "Query": "select user_extra.id from user_extra where user_extra.col = :user_col", + "Query": "select user_extra.id from user_extra where user_extra.col = :user_col /* INT16 */", "Table": "user_extra" } ] @@ -4228,7 +4228,7 @@ "Sharded": true }, "FieldQuery": "select count(*) from `user` as b where 1 != 1 group by .0", - "Query": "select count(*) from `user` as b where b.textcol2 = :a_textcol1 group by .0", + "Query": "select count(*) from `user` as b where b.textcol2 = :a_textcol1 /* VARCHAR */ group by .0", "Table": "`user`" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/from_cases.json b/go/vt/vtgate/planbuilder/testdata/from_cases.json index 81381f3d7d7..50b56b428ec 100644 --- a/go/vt/vtgate/planbuilder/testdata/from_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/from_cases.json @@ -585,7 +585,7 @@ "Sharded": false }, "FieldQuery": "select m1.col from unsharded as m1 where 1 != 1", - "Query": "select m1.col from unsharded as m1 where m1.col = :user_col", + "Query": "select m1.col from unsharded as m1 where m1.col = :user_col /* INT16 */", "Table": "unsharded" } ] @@ -651,7 +651,7 @@ "Sharded": true }, "FieldQuery": "select e.col from user_extra as e where 1 != 1", - "Query": "select e.col from user_extra as e where e.col = :user_col", + "Query": "select e.col from user_extra as e where e.col = :user_col /* INT16 */", "Table": "user_extra" }, { @@ -662,7 +662,7 @@ "Sharded": false }, "FieldQuery": "select 1 from unsharded as m1 where 1 != 1", - "Query": "select 1 from unsharded as m1 where m1.col = :e_col", + "Query": "select 1 from unsharded as m1 where m1.col = :e_col /* INT16 */", "Table": "unsharded" } ] @@ -1221,7 +1221,7 @@ "Sharded": true }, "FieldQuery": "select `user`.col from `user` where 1 != 1", - "Query": "select `user`.col from `user` where `user`.id = :user_extra_col", + "Query": "select `user`.col from `user` where `user`.id = :user_extra_col /* INT16 */", "Table": "`user`", "Values": [ ":user_extra_col" @@ -1742,6 +1742,47 @@ ] } }, + { + "comment": "Unneeded ORDER BY inside derived table removed", + "query": "select * from (select id from user order by foo) dt1, (select id from user order by baz) dt2", + "plan": { + "QueryType": "SELECT", + "Original": "select * from (select id from user order by foo) dt1, (select id from user order by baz) dt2", + "Instructions": { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,R:0", + "TableName": "`user`_`user`", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select dt1.id from (select id from `user` where 1 != 1) as dt1 where 1 != 1", + "Query": "select dt1.id from (select id from `user`) as dt1", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select dt2.id from (select id from `user` where 1 != 1) as dt2 where 1 != 1", + "Query": "select dt2.id from (select id from `user`) as dt2", + "Table": "`user`" + } + ] + }, + "TablesUsed": [ + "user.user" + ] + } + }, { "comment": "join of information_schema with normal table", "query": "select unsharded.foo from information_schema.CHARACTER_SETS join unsharded", @@ -1783,6 +1824,30 @@ ] } }, + { + "comment": "three table join with join predicate touching all tables", + "query": "select 42 from user u join user_extra ue on u.id = ue.user_id join music m on m.user_id = u.id where u.foo or m.foo or ue.foo", + "plan": { + "QueryType": "SELECT", + "Original": "select 42 from user u join user_extra ue on u.id = ue.user_id join music m on m.user_id = u.id where u.foo or m.foo or ue.foo", + "Instructions": { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select 42 from `user` as u, user_extra as ue, music as m where 1 != 1", + "Query": "select 42 from `user` as u, user_extra as ue, music as m where u.id = ue.user_id and m.user_id = u.id and (u.foo or m.foo or ue.foo)", + "Table": "`user`, music, user_extra" + }, + "TablesUsed": [ + "user.music", + "user.user", + "user.user_extra" + ] + } + }, { "comment": "join of normal table with information_schema", "query": "select unsharded.foo from unsharded join information_schema.CHARACTER_SETS", @@ -1924,7 +1989,7 @@ "Sharded": true }, "FieldQuery": "select 1 from user_extra where 1 != 1", - "Query": "select 1 from user_extra where user_extra.col = :user_col", + "Query": "select 1 from user_extra where user_extra.col = :user_col /* INT16 */", "Table": "user_extra" } ] @@ -2841,6 +2906,62 @@ ] } }, + { + "comment": "Hash join has to be used since we have LIMIT on both sides", + "query": "select id from (select id from user limit 10) u join (select user_id from user_extra limit 10) ue on u.id = ue.user_id", + "plan": { + "QueryType": "SELECT", + "Original": "select id from (select id from user limit 10) u join (select user_id from user_extra limit 10) ue on u.id = ue.user_id", + "Instructions": { + "OperatorType": "Join", + "Variant": "HashJoin", + "ComparisonType": "-1", + "JoinColumnIndexes": "-1", + "Predicate": "u.id = ue.user_id", + "TableName": "`user`_user_extra", + "Inputs": [ + { + "OperatorType": "Limit", + "Count": "10", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select u.id from (select id from `user` where 1 != 1) as u where 1 != 1", + "Query": "select u.id from (select id from `user`) as u limit 10", + "Table": "`user`" + } + ] + }, + { + "OperatorType": "Limit", + "Count": "10", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select ue.user_id from (select user_id from user_extra where 1 != 1) as ue where 1 != 1", + "Query": "select ue.user_id from (select user_id from user_extra) as ue limit 10", + "Table": "user_extra" + } + ] + } + ] + }, + "TablesUsed": [ + "user.user", + "user.user_extra" + ] + } + }, { "comment": "alias on column from derived table. TODO: to support alias in SimpleProjection engine primitive.", "query": "select a as k from (select count(*) as a from user) t", @@ -3244,7 +3365,7 @@ "Sharded": true }, "FieldQuery": "select 1 from `user` as uu where 1 != 1", - "Query": "select 1 from `user` as uu where uu.intcol = :u_intcol", + "Query": "select 1 from `user` as uu where uu.intcol = :u_intcol /* INT16 */", "Table": "`user`" } ] @@ -3357,7 +3478,7 @@ "Sharded": true }, "FieldQuery": "select user_extra.col from user_extra where 1 != 1", - "Query": "select user_extra.col from user_extra where user_extra.col = :user_col", + "Query": "select user_extra.col from user_extra where user_extra.col = :user_col /* INT16 */", "Table": "user_extra" } ] @@ -3594,7 +3715,7 @@ "Sharded": true }, "FieldQuery": "select user_extra.col from user_extra where 1 != 1", - "Query": "select user_extra.col from user_extra where user_extra.col = :user_col", + "Query": "select user_extra.col from user_extra where user_extra.col = :user_col /* INT16 */", "Table": "user_extra" } ] @@ -3654,7 +3775,7 @@ "Sharded": true }, "FieldQuery": "select user_extra.col from user_extra where 1 != 1", - "Query": "select user_extra.col from user_extra where user_extra.col = :user_col", + "Query": "select user_extra.col from user_extra where user_extra.col = :user_col /* INT16 */", "Table": "user_extra" } ] @@ -3720,7 +3841,7 @@ "Sharded": true }, "FieldQuery": "select user_extra.col from user_extra where 1 != 1", - "Query": "select user_extra.col from user_extra where user_extra.col = :user_col", + "Query": "select user_extra.col from user_extra where user_extra.col = :user_col /* INT16 */", "Table": "user_extra" } ] @@ -3799,7 +3920,7 @@ "Sharded": false }, "FieldQuery": "select unsharded_authoritative.col2 from unsharded_authoritative where 1 != 1", - "Query": "select unsharded_authoritative.col2 from unsharded_authoritative where unsharded_authoritative.col1 = :authoritative_col1", + "Query": "select unsharded_authoritative.col2 from unsharded_authoritative where unsharded_authoritative.col1 = :authoritative_col1 /* VARCHAR */", "Table": "unsharded_authoritative" } ] @@ -3921,7 +4042,7 @@ "Sharded": true }, "FieldQuery": "select user_extra.col from user_extra where 1 != 1", - "Query": "select user_extra.col from user_extra where user_extra.col = :user_col", + "Query": "select user_extra.col from user_extra where user_extra.col = :user_col /* INT16 */", "Table": "user_extra" } ] @@ -4430,7 +4551,7 @@ "Sharded": true }, "FieldQuery": "select 1 from music as m where 1 != 1", - "Query": "select 1 from music as m where m.user_id = 5 and m.id = 20 and m.col = :u_col", + "Query": "select 1 from music as m where m.user_id = 5 and m.id = 20 and m.col = :u_col /* INT16 */", "Table": "music", "Values": [ "20" diff --git a/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json b/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json index 12ddfa6e049..31246a2f40f 100644 --- a/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json @@ -319,7 +319,7 @@ "Sharded": false }, "FieldQuery": "select rc.delete_rule as delete_rule, rc.update_rule as update_rule from information_schema.referential_constraints as rc where 1 != 1", - "Query": "select rc.delete_rule as delete_rule, rc.update_rule as update_rule from information_schema.referential_constraints as rc where rc.constraint_schema = :__vtschemaname /* VARCHAR */ and rc.constraint_name = :kcu_constraint_name", + "Query": "select rc.delete_rule as delete_rule, rc.update_rule as update_rule from information_schema.referential_constraints as rc where rc.constraint_schema = :__vtschemaname /* VARCHAR */ and rc.constraint_name = :kcu_constraint_name /* VARCHAR(64) */", "SysTableTableSchema": "[:v2]", "Table": "information_schema.referential_constraints" } @@ -723,7 +723,7 @@ "Sharded": true }, "FieldQuery": "select 1 from `user` where 1 != 1", - "Query": "select 1 from `user` where `user`.id = :x_COLUMN_NAME", + "Query": "select 1 from `user` where `user`.id = :x_COLUMN_NAME /* VARCHAR(64) */", "Table": "`user`", "Values": [ ":x_COLUMN_NAME" diff --git a/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json b/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json index 3eec3685fd2..9553210174c 100644 --- a/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json @@ -319,7 +319,7 @@ "Sharded": false }, "FieldQuery": "select rc.delete_rule as delete_rule, rc.update_rule as update_rule from information_schema.referential_constraints as rc where 1 != 1", - "Query": "select rc.delete_rule as delete_rule, rc.update_rule as update_rule from information_schema.referential_constraints as rc where rc.constraint_schema = :__vtschemaname /* VARCHAR */ and rc.constraint_name = :kcu_constraint_name", + "Query": "select rc.delete_rule as delete_rule, rc.update_rule as update_rule from information_schema.referential_constraints as rc where rc.constraint_schema = :__vtschemaname /* VARCHAR */ and rc.constraint_name = :kcu_constraint_name /* VARCHAR(64) */", "SysTableTableSchema": "[:v2]", "Table": "information_schema.referential_constraints" } @@ -445,7 +445,7 @@ "Sharded": false }, "FieldQuery": "select 1 from information_schema.table_constraints as tc where 1 != 1", - "Query": "select 1 from information_schema.table_constraints as tc where tc.table_schema = :__vtschemaname /* VARCHAR */ and tc.table_name = :tc_table_name /* VARCHAR */ and tc.constraint_name = :cc_constraint_name and tc.constraint_schema = :__vtschemaname /* VARCHAR */", + "Query": "select 1 from information_schema.table_constraints as tc where tc.table_schema = :__vtschemaname /* VARCHAR */ and tc.table_name = :tc_table_name /* VARCHAR */ and tc.constraint_name = :cc_constraint_name /* VARCHAR(64) */ and tc.constraint_schema = :__vtschemaname /* VARCHAR */", "SysTableTableName": "[tc_table_name:'table_name']", "SysTableTableSchema": "['table_schema', :cc_constraint_schema]", "Table": "information_schema.table_constraints" @@ -788,7 +788,7 @@ "Sharded": true }, "FieldQuery": "select 1 from `user` where 1 != 1", - "Query": "select 1 from `user` where `user`.id = :x_COLUMN_NAME", + "Query": "select 1 from `user` where `user`.id = :x_COLUMN_NAME /* VARCHAR(64) */", "Table": "`user`", "Values": [ ":x_COLUMN_NAME" diff --git a/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.json b/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.json index 3281feacc76..f26b160ef69 100644 --- a/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.json @@ -149,7 +149,7 @@ }, "FieldQuery": "select a, b, count(*) as k, weight_string(a) from `user` where 1 != 1 group by a, weight_string(a)", "OrderBy": "(0|3) ASC", - "Query": "select a, b, count(*) as k, weight_string(a) from `user` group by a, weight_string(a) order by a asc limit :__upper_limit", + "Query": "select a, b, count(*) as k, weight_string(a) from `user` group by a, weight_string(a) order by a asc", "Table": "`user`" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json index 454740f0498..74e5229016a 100644 --- a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json @@ -949,7 +949,7 @@ "Sharded": true }, "FieldQuery": "select e.id from user_extra as e where 1 != 1", - "Query": "select e.id from user_extra as e where e.col = :u_col", + "Query": "select e.id from user_extra as e where e.col = :u_col /* INT16 */", "Table": "user_extra" } ] @@ -2030,13 +2030,13 @@ "Instructions": { "OperatorType": "Sort", "Variant": "Memory", - "OrderBy": "(1|2) ASC", + "OrderBy": "1 ASC", "ResultColumns": 1, "Inputs": [ { "OperatorType": "Join", "Variant": "Join", - "JoinColumnIndexes": "L:0,R:0,R:1", + "JoinColumnIndexes": "L:0,R:0", "JoinVars": { "user_col": 1 }, @@ -2060,8 +2060,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select coalesce(:user_col, user_extra.col), weight_string(coalesce(:user_col, user_extra.col)) from user_extra where 1 != 1", - "Query": "select coalesce(:user_col, user_extra.col), weight_string(coalesce(:user_col, user_extra.col)) from user_extra", + "FieldQuery": "select coalesce(:user_col /* INT16 */, user_extra.col) from user_extra where 1 != 1", + "Query": "select coalesce(:user_col /* INT16 */, user_extra.col) from user_extra", "Table": "user_extra" } ] @@ -2185,9 +2185,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select foo, col, weight_string(foo) from `user` where 1 != 1 group by col, foo, weight_string(foo)", + "FieldQuery": "select foo, col, weight_string(foo) from `user` where 1 != 1 group by foo, col, weight_string(foo)", "OrderBy": "1 ASC, (0|2) ASC", - "Query": "select foo, col, weight_string(foo) from `user` where id between :vtg1 and :vtg2 group by col, foo, weight_string(foo) order by `user`.col asc, foo asc", + "Query": "select foo, col, weight_string(foo) from `user` where id between :vtg1 and :vtg2 group by foo, col, weight_string(foo) order by `user`.col asc, foo asc", "Table": "`user`" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/rails_cases.json b/go/vt/vtgate/planbuilder/testdata/rails_cases.json index c8ab8b7b9d8..3887547e628 100644 --- a/go/vt/vtgate/planbuilder/testdata/rails_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/rails_cases.json @@ -62,7 +62,7 @@ "Sharded": true }, "FieldQuery": "select 1 from book6s_order2s where 1 != 1", - "Query": "select 1 from book6s_order2s where book6s_order2s.order2_id = :order2s_id and book6s_order2s.book6_id = :book6s_id", + "Query": "select 1 from book6s_order2s where book6s_order2s.order2_id = :order2s_id /* INT64 */ and book6s_order2s.book6_id = :book6s_id /* INT64 */", "Table": "book6s_order2s", "Values": [ ":book6s_id" @@ -79,7 +79,7 @@ "Sharded": true }, "FieldQuery": "select 1 from supplier5s where 1 != 1", - "Query": "select 1 from supplier5s where supplier5s.id = :book6s_supplier5_id", + "Query": "select 1 from supplier5s where supplier5s.id = :book6s_supplier5_id /* INT64 */", "Table": "supplier5s", "Values": [ ":book6s_supplier5_id" diff --git a/go/vt/vtgate/planbuilder/testdata/select_cases.json b/go/vt/vtgate/planbuilder/testdata/select_cases.json index 38f0cb3044f..1099f62175f 100644 --- a/go/vt/vtgate/planbuilder/testdata/select_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/select_cases.json @@ -466,6 +466,63 @@ ] } }, + { + "comment": "json_arrayagg in single sharded query", + "query": "select count(1) from user where id = 'abc' group by n_id having json_arrayagg(a_id) = '[]'", + "plan": { + "QueryType": "SELECT", + "Original": "select count(1) from user where id = 'abc' group by n_id having json_arrayagg(a_id) = '[]'", + "Instructions": { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select count(1) from `user` where 1 != 1 group by n_id", + "Query": "select count(1) from `user` where id = 'abc' group by n_id having json_arrayagg(a_id) = '[]'", + "Table": "`user`", + "Values": [ + "'abc'" + ], + "Vindex": "user_index" + }, + "TablesUsed": [ + "user.user" + ] + } + }, + { + "comment": "json_objectagg in single sharded query", + "query": "select count(1) from user where id = 'abc' group by n_id having json_objectagg(a_id, b_id) = '[]'", + "plan": { + "QueryType": "SELECT", + "Original": "select count(1) from user where id = 'abc' group by n_id having json_objectagg(a_id, b_id) = '[]'", + "Instructions": { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select count(1) from `user` where 1 != 1 group by n_id", + "Query": "select count(1) from `user` where id = 'abc' group by n_id having json_objectagg(a_id, b_id) = '[]'", + "Table": "`user`", + "Values": [ + "'abc'" + ], + "Vindex": "user_index" + }, + "TablesUsed": [ + "user.user" + ] + } + }, + { + "comment": "unsupported json aggregation expressions in scatter query", + "query": "select count(1) from user where cola = 'abc' group by n_id having json_arrayagg(a_id) = '[]'", + "plan": "VT12001: unsupported: in scatter query: aggregation function 'json_arrayagg(a_id)'" + }, { "comment": "Cannot auto-resolve for cross-shard joins", "query": "select col from user join user_extra", @@ -736,6 +793,33 @@ ] } }, + { + "comment": "subquery with an aggregation in order by that can be merged into a single route", + "query": "select col, trim((select user_name from user where id = 3)) val from user_extra where user_id = 3 group by col order by val", + "plan": { + "QueryType": "SELECT", + "Original": "select col, trim((select user_name from user where id = 3)) val from user_extra where user_id = 3 group by col order by val", + "Instructions": { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select col, trim((select user_name from `user` where 1 != 1)) as val from user_extra where 1 != 1 group by col", + "Query": "select col, trim((select user_name from `user` where id = 3)) as val from user_extra where user_id = 3 group by col order by trim((select `user`.user_name from `user` where `user`.id = 3)) asc", + "Table": "user_extra", + "Values": [ + "3" + ], + "Vindex": "user_index" + }, + "TablesUsed": [ + "user.user", + "user.user_extra" + ] + } + }, { "comment": "Jumbled references", "query": "select user.col, user_extra.id, user.col2 from user join user_extra", @@ -1361,8 +1445,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select a, :__sq1 as `(select col from ``user``)` from unsharded where 1 != 1", - "Query": "select a, :__sq1 as `(select col from ``user``)` from unsharded", + "FieldQuery": "select a, :__sq1 /* INT16 */ as `(select col from ``user``)` from unsharded where 1 != 1", + "Query": "select a, :__sq1 /* INT16 */ as `(select col from ``user``)` from unsharded", "Table": "unsharded" } ] @@ -1406,8 +1490,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select a, 1 + :__sq1 as `1 + (select col from ``user``)` from unsharded where 1 != 1", - "Query": "select a, 1 + :__sq1 as `1 + (select col from ``user``)` from unsharded", + "FieldQuery": "select a, 1 + :__sq1 /* INT16 */ as `1 + (select col from ``user``)` from unsharded where 1 != 1", + "Query": "select a, 1 + :__sq1 /* INT16 */ as `1 + (select col from ``user``)` from unsharded", "Table": "unsharded" } ] @@ -1799,6 +1883,112 @@ ] } }, + { + "comment": "Complex expression in a subquery used in IN clause of an aggregate query", + "query": "select count(*) from user where user.id = 2 or user.id in (select id from unsharded_a where colb = 2)", + "plan": { + "QueryType": "SELECT", + "Original": "select count(*) from user where user.id = 2 or user.id in (select id from unsharded_a where colb = 2)", + "Instructions": { + "OperatorType": "Aggregate", + "Variant": "Scalar", + "Aggregates": "sum_count_star(0) AS count(*)", + "Inputs": [ + { + "OperatorType": "UncorrelatedSubquery", + "Variant": "PulloutIn", + "PulloutVars": [ + "__sq_has_values", + "__sq1" + ], + "Inputs": [ + { + "InputName": "SubQuery", + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select id from unsharded_a where 1 != 1", + "Query": "select id from unsharded_a where colb = 2", + "Table": "unsharded_a" + }, + { + "InputName": "Outer", + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select count(*) from `user` where 1 != 1", + "Query": "select count(*) from `user` where `user`.id = 2 or :__sq_has_values and `user`.id in ::__sq1", + "Table": "`user`" + } + ] + } + ] + }, + "TablesUsed": [ + "main.unsharded_a", + "user.user" + ] + } + }, + { + "comment": "Complex expression in a subquery used in NOT IN clause of an aggregate query", + "query": "select count(*) from user where user.id = 2 or user.id not in (select id from unsharded_a where colb = 2)", + "plan": { + "QueryType": "SELECT", + "Original": "select count(*) from user where user.id = 2 or user.id not in (select id from unsharded_a where colb = 2)", + "Instructions": { + "OperatorType": "Aggregate", + "Variant": "Scalar", + "Aggregates": "sum_count_star(0) AS count(*)", + "Inputs": [ + { + "OperatorType": "UncorrelatedSubquery", + "Variant": "PulloutNotIn", + "PulloutVars": [ + "__sq_has_values", + "__sq1" + ], + "Inputs": [ + { + "InputName": "SubQuery", + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select id from unsharded_a where 1 != 1", + "Query": "select id from unsharded_a where colb = 2", + "Table": "unsharded_a" + }, + { + "InputName": "Outer", + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select count(*) from `user` where 1 != 1", + "Query": "select count(*) from `user` where `user`.id = 2 or (not :__sq_has_values or `user`.id not in ::__sq1)", + "Table": "`user`" + } + ] + } + ] + }, + "TablesUsed": [ + "main.unsharded_a", + "user.user" + ] + } + }, { "comment": "testing SingleRow Projection with arithmetics", "query": "select 42+2", @@ -2176,7 +2366,7 @@ "Sharded": true }, "FieldQuery": "select `user`.col from `user` where 1 != 1", - "Query": "select `user`.col from `user` where `user`.col = :t_title and `user`.id <= 4", + "Query": "select `user`.col from `user` where `user`.col = :t_title /* VARCHAR */ and `user`.id <= 4", "Table": "`user`" } ] @@ -2453,8 +2643,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select t.a from (select :__sq1 as a from `user` where 1 != 1) as t where 1 != 1", - "Query": "select t.a from (select :__sq1 as a from `user`) as t", + "FieldQuery": "select t.a from (select :__sq1 /* INT16 */ as a from `user` where 1 != 1) as t where 1 != 1", + "Query": "select t.a from (select :__sq1 /* INT16 */ as a from `user`) as t", "Table": "`user`" } ] @@ -2523,8 +2713,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select :__sq1 as a from `user` where 1 != 1", - "Query": "select :__sq1 as a from `user`", + "FieldQuery": "select :__sq1 /* INT16 */ as a from `user` where 1 != 1", + "Query": "select :__sq1 /* INT16 */ as a from `user`", "Table": "`user`" } ] @@ -2660,6 +2850,80 @@ ] } }, + { + "comment": "Dual query should be handled on the vtgate even with a LIMIT", + "query": "select last_insert_id() limit 1", + "plan": { + "QueryType": "SELECT", + "Original": "select last_insert_id() limit 1", + "Instructions": { + "OperatorType": "Projection", + "Expressions": [ + ":__lastInsertId as last_insert_id()" + ], + "Inputs": [ + { + "OperatorType": "SingleRow" + } + ] + }, + "TablesUsed": [ + "main.dual" + ] + } + }, + { + "comment": "PullOut subquery with an aggregation that should be typed in the final output", + "query": "select (select sum(col) from user) from user_extra", + "plan": { + "QueryType": "SELECT", + "Original": "select (select sum(col) from user) from user_extra", + "Instructions": { + "OperatorType": "UncorrelatedSubquery", + "Variant": "PulloutValue", + "PulloutVars": [ + "__sq1" + ], + "Inputs": [ + { + "InputName": "SubQuery", + "OperatorType": "Aggregate", + "Variant": "Scalar", + "Aggregates": "sum(0) AS sum(col)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select sum(col) from `user` where 1 != 1", + "Query": "select sum(col) from `user`", + "Table": "`user`" + } + ] + }, + { + "InputName": "Outer", + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select CAST(:__sq1 AS DECIMAL(0, 0)) as `(select sum(col) from ``user``)` from user_extra where 1 != 1", + "Query": "select CAST(:__sq1 AS DECIMAL(0, 0)) as `(select sum(col) from ``user``)` from user_extra", + "Table": "user_extra" + } + ] + }, + "TablesUsed": [ + "user.user", + "user.user_extra" + ] + } + }, { "comment": "Straight Join preserved in MySQL query", "query": "select user.id, user_extra.user_id from user straight_join user_extra where user.id = user_extra.user_id", @@ -2858,7 +3122,7 @@ "Sharded": true }, "FieldQuery": "select 1 from user_extra as ue where 1 != 1", - "Query": "select 1 from user_extra as ue where ue.col = :u1_col and ue.col = :u2_col limit 1", + "Query": "select 1 from user_extra as ue where ue.col = :u1_col /* INT16 */ and ue.col = :u2_col /* INT16 */ limit 1", "Table": "user_extra" } ] @@ -2915,7 +3179,7 @@ "Sharded": true }, "FieldQuery": "select 1 from user_extra as ue where 1 != 1", - "Query": "select 1 from user_extra as ue where ue.col = :u_col and ue.col2 = :u_col limit 1", + "Query": "select 1 from user_extra as ue where ue.col = :u_col /* INT16 */ and ue.col2 = :u_col /* INT16 */ limit 1", "Table": "user_extra" } ] @@ -3054,8 +3318,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select :user_extra_col + `user`.col as `user_extra.col + ``user``.col` from `user` where 1 != 1", - "Query": "select :user_extra_col + `user`.col as `user_extra.col + ``user``.col` from `user` where `user`.id = :user_extra_id", + "FieldQuery": "select :user_extra_col /* INT16 */ + `user`.col as `user_extra.col + ``user``.col` from `user` where 1 != 1", + "Query": "select :user_extra_col /* INT16 */ + `user`.col as `user_extra.col + ``user``.col` from `user` where `user`.id = :user_extra_id", "Table": "`user`", "Values": [ ":user_extra_id" @@ -3195,8 +3459,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select json_quote('null'), json_quote('\\\"null\\\"'), json_object(BIN(1), 2, 'abc', ASCII(4)), json_array(1, 'abc', null, true, curtime()) from dual where 1 != 1", - "Query": "select json_quote('null'), json_quote('\\\"null\\\"'), json_object(BIN(1), 2, 'abc', ASCII(4)), json_array(1, 'abc', null, true, curtime()) from dual", + "FieldQuery": "select json_quote('null'), json_quote('\"null\"'), json_object(BIN(1), 2, 'abc', ASCII(4)), json_array(1, 'abc', null, true, curtime()) from dual where 1 != 1", + "Query": "select json_quote('null'), json_quote('\"null\"'), json_object(BIN(1), 2, 'abc', ASCII(4)), json_array(1, 'abc', null, true, curtime()) from dual", "Table": "dual" }, "TablesUsed": [ @@ -3296,8 +3560,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select json_schema_valid('{\\\"type\\\":\\\"string\\\",\\\"pattern\\\":\\\"(\\\"}', '\\\"abc\\\"'), json_schema_validation_report('{\\\"type\\\":\\\"string\\\",\\\"pattern\\\":\\\"(\\\"}', '\\\"abc\\\"') from dual where 1 != 1", - "Query": "select json_schema_valid('{\\\"type\\\":\\\"string\\\",\\\"pattern\\\":\\\"(\\\"}', '\\\"abc\\\"'), json_schema_validation_report('{\\\"type\\\":\\\"string\\\",\\\"pattern\\\":\\\"(\\\"}', '\\\"abc\\\"') from dual", + "FieldQuery": "select json_schema_valid('{\"type\":\"string\",\"pattern\":\"(\"}', '\"abc\"'), json_schema_validation_report('{\"type\":\"string\",\"pattern\":\"(\"}', '\"abc\"') from dual where 1 != 1", + "Query": "select json_schema_valid('{\"type\":\"string\",\"pattern\":\"(\"}', '\"abc\"'), json_schema_validation_report('{\"type\":\"string\",\"pattern\":\"(\"}', '\"abc\"') from dual", "Table": "dual" }, "TablesUsed": [ @@ -3318,8 +3582,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select json_contains('{\\\"a\\\": 1, \\\"b\\\": 2, \\\"c\\\": {\\\"d\\\": 4}}', '1'), json_contains_path('{\\\"a\\\": 1, \\\"b\\\": 2, \\\"c\\\": {\\\"d\\\": 4}}', 'one', '$.a', '$.e'), json_extract('[10, 20, [30, 40]]', '$[1]'), json_unquote(json_extract('[\\\"a\\\",\\\"b\\\"]', '$[1]')), json_keys('{\\\"a\\\": 1, \\\"b\\\": {\\\"c\\\": 30}}'), json_overlaps('[1,3,5,7]', '[2,5,7]'), json_search('[\\\"abc\\\"]', 'one', 'abc'), json_value('{\\\"fname\\\": \\\"Joe\\\", \\\"lname\\\": \\\"Palmer\\\"}', '$.fname'), json_array(4, 5) member of ('[[3,4],[4,5]]') from dual where 1 != 1", - "Query": "select json_contains('{\\\"a\\\": 1, \\\"b\\\": 2, \\\"c\\\": {\\\"d\\\": 4}}', '1'), json_contains_path('{\\\"a\\\": 1, \\\"b\\\": 2, \\\"c\\\": {\\\"d\\\": 4}}', 'one', '$.a', '$.e'), json_extract('[10, 20, [30, 40]]', '$[1]'), json_unquote(json_extract('[\\\"a\\\",\\\"b\\\"]', '$[1]')), json_keys('{\\\"a\\\": 1, \\\"b\\\": {\\\"c\\\": 30}}'), json_overlaps('[1,3,5,7]', '[2,5,7]'), json_search('[\\\"abc\\\"]', 'one', 'abc'), json_value('{\\\"fname\\\": \\\"Joe\\\", \\\"lname\\\": \\\"Palmer\\\"}', '$.fname'), json_array(4, 5) member of ('[[3,4],[4,5]]') from dual", + "FieldQuery": "select json_contains('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', '1'), json_contains_path('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', 'one', '$.a', '$.e'), json_extract('[10, 20, [30, 40]]', '$[1]'), json_unquote(json_extract('[\"a\",\"b\"]', '$[1]')), json_keys('{\"a\": 1, \"b\": {\"c\": 30}}'), json_overlaps('[1,3,5,7]', '[2,5,7]'), json_search('[\"abc\"]', 'one', 'abc'), json_value('{\"fname\": \"Joe\", \"lname\": \"Palmer\"}', '$.fname'), json_array(4, 5) member of ('[[3,4],[4,5]]') from dual where 1 != 1", + "Query": "select json_contains('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', '1'), json_contains_path('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', 'one', '$.a', '$.e'), json_extract('[10, 20, [30, 40]]', '$[1]'), json_unquote(json_extract('[\"a\",\"b\"]', '$[1]')), json_keys('{\"a\": 1, \"b\": {\"c\": 30}}'), json_overlaps('[1,3,5,7]', '[2,5,7]'), json_search('[\"abc\"]', 'one', 'abc'), json_value('{\"fname\": \"Joe\", \"lname\": \"Palmer\"}', '$.fname'), json_array(4, 5) member of ('[[3,4],[4,5]]') from dual", "Table": "dual" }, "TablesUsed": [ @@ -3384,8 +3648,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select json_depth('{}'), json_length('{\\\"a\\\": 1, \\\"b\\\": {\\\"c\\\": 30}}', '$.b'), json_type(json_extract('{\\\"a\\\": [10, true]}', '$.a')), json_valid('{\\\"a\\\": 1}') from dual where 1 != 1", - "Query": "select json_depth('{}'), json_length('{\\\"a\\\": 1, \\\"b\\\": {\\\"c\\\": 30}}', '$.b'), json_type(json_extract('{\\\"a\\\": [10, true]}', '$.a')), json_valid('{\\\"a\\\": 1}') from dual", + "FieldQuery": "select json_depth('{}'), json_length('{\"a\": 1, \"b\": {\"c\": 30}}', '$.b'), json_type(json_extract('{\"a\": [10, true]}', '$.a')), json_valid('{\"a\": 1}') from dual where 1 != 1", + "Query": "select json_depth('{}'), json_length('{\"a\": 1, \"b\": {\"c\": 30}}', '$.b'), json_type(json_extract('{\"a\": [10, true]}', '$.a')), json_valid('{\"a\": 1}') from dual", "Table": "dual" }, "TablesUsed": [ @@ -3406,8 +3670,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select json_array_append('{\\\"a\\\": 1}', '$', 'z'), json_array_insert('[\\\"a\\\", {\\\"b\\\": [1, 2]}, [3, 4]]', '$[0]', 'x', '$[2][1]', 'y'), json_insert('{ \\\"a\\\": 1, \\\"b\\\": [2, 3]}', '$.a', 10, '$.c', cast('[true, false]' as JSON)) from dual where 1 != 1", - "Query": "select json_array_append('{\\\"a\\\": 1}', '$', 'z'), json_array_insert('[\\\"a\\\", {\\\"b\\\": [1, 2]}, [3, 4]]', '$[0]', 'x', '$[2][1]', 'y'), json_insert('{ \\\"a\\\": 1, \\\"b\\\": [2, 3]}', '$.a', 10, '$.c', cast('[true, false]' as JSON)) from dual", + "FieldQuery": "select json_array_append('{\"a\": 1}', '$', 'z'), json_array_insert('[\"a\", {\"b\": [1, 2]}, [3, 4]]', '$[0]', 'x', '$[2][1]', 'y'), json_insert('{ \"a\": 1, \"b\": [2, 3]}', '$.a', 10, '$.c', cast('[true, false]' as JSON)) from dual where 1 != 1", + "Query": "select json_array_append('{\"a\": 1}', '$', 'z'), json_array_insert('[\"a\", {\"b\": [1, 2]}, [3, 4]]', '$[0]', 'x', '$[2][1]', 'y'), json_insert('{ \"a\": 1, \"b\": [2, 3]}', '$.a', 10, '$.c', cast('[true, false]' as JSON)) from dual", "Table": "dual" }, "TablesUsed": [ @@ -3428,8 +3692,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select json_merge('[1, 2]', '[true, false]'), json_merge_patch('{\\\"name\\\": \\\"x\\\"}', '{\\\"id\\\": 47}'), json_merge_preserve('[1, 2]', '{\\\"id\\\": 47}') from dual where 1 != 1", - "Query": "select json_merge('[1, 2]', '[true, false]'), json_merge_patch('{\\\"name\\\": \\\"x\\\"}', '{\\\"id\\\": 47}'), json_merge_preserve('[1, 2]', '{\\\"id\\\": 47}') from dual", + "FieldQuery": "select json_merge('[1, 2]', '[true, false]'), json_merge_patch('{\"name\": \"x\"}', '{\"id\": 47}'), json_merge_preserve('[1, 2]', '{\"id\": 47}') from dual where 1 != 1", + "Query": "select json_merge('[1, 2]', '[true, false]'), json_merge_patch('{\"name\": \"x\"}', '{\"id\": 47}'), json_merge_preserve('[1, 2]', '{\"id\": 47}') from dual", "Table": "dual" }, "TablesUsed": [ @@ -3450,8 +3714,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select json_remove('[1, [2, 3], 4]', '$[1]'), json_replace('{ \\\"a\\\": 1, \\\"b\\\": [2, 3]}', '$.a', 10, '$.c', '[true, false]'), json_set('{ \\\"a\\\": 1, \\\"b\\\": [2, 3]}', '$.a', 10, '$.c', '[true, false]'), json_unquote('\\\"abc\\\"') from dual where 1 != 1", - "Query": "select json_remove('[1, [2, 3], 4]', '$[1]'), json_replace('{ \\\"a\\\": 1, \\\"b\\\": [2, 3]}', '$.a', 10, '$.c', '[true, false]'), json_set('{ \\\"a\\\": 1, \\\"b\\\": [2, 3]}', '$.a', 10, '$.c', '[true, false]'), json_unquote('\\\"abc\\\"') from dual", + "FieldQuery": "select json_remove('[1, [2, 3], 4]', '$[1]'), json_replace('{ \"a\": 1, \"b\": [2, 3]}', '$.a', 10, '$.c', '[true, false]'), json_set('{ \"a\": 1, \"b\": [2, 3]}', '$.a', 10, '$.c', '[true, false]'), json_unquote('\"abc\"') from dual where 1 != 1", + "Query": "select json_remove('[1, [2, 3], 4]', '$[1]'), json_replace('{ \"a\": 1, \"b\": [2, 3]}', '$.a', 10, '$.c', '[true, false]'), json_set('{ \"a\": 1, \"b\": [2, 3]}', '$.a', 10, '$.c', '[true, false]'), json_unquote('\"abc\"') from dual", "Table": "dual" }, "TablesUsed": [ @@ -3632,7 +3896,7 @@ "Sharded": true }, "FieldQuery": "select user_metadata.user_id from user_extra, user_metadata where 1 != 1", - "Query": "select user_metadata.user_id from user_extra, user_metadata where user_extra.col = :user_col and user_extra.user_id = user_metadata.user_id", + "Query": "select user_metadata.user_id from user_extra, user_metadata where user_extra.col = :user_col /* INT16 */ and user_extra.user_id = user_metadata.user_id", "Table": "user_extra, user_metadata" } ] @@ -4241,8 +4505,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select max(music.id), weight_string(music.id) from music where 1 != 1 group by weight_string(music.id)", - "Query": "select max(music.id), weight_string(music.id) from music where music.user_id in ::__vals group by weight_string(music.id)", + "FieldQuery": "select max(music.id), weight_string(max(music.id)) from music where 1 != 1", + "Query": "select max(music.id), weight_string(max(music.id)) from music where music.user_id in ::__vals", "Table": "music", "Values": [ "(5, 6)" diff --git a/go/vt/vtgate/planbuilder/testdata/show_cases.json b/go/vt/vtgate/planbuilder/testdata/show_cases.json index 45ad277677c..f7fbce608bc 100644 --- a/go/vt/vtgate/planbuilder/testdata/show_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/show_cases.json @@ -838,5 +838,17 @@ "Filter": " like 'x'" } } + }, + { + "comment": "show transaction status plan", + "query": "show transaction status for 'ks:-80:v24s7843sf78934l3'", + "plan": { + "QueryType": "SHOW", + "Original": "show transaction status for 'ks:-80:v24s7843sf78934l3'", + "Instructions": { + "OperatorType": "TransactionStatus", + "TransactionID": "ks:-80:v24s7843sf78934l3" + } + } } ] diff --git a/go/vt/vtgate/planbuilder/testdata/tpch_cases.json b/go/vt/vtgate/planbuilder/testdata/tpch_cases.json index 610a0ba1c23..442f4d6b8b6 100644 --- a/go/vt/vtgate/planbuilder/testdata/tpch_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/tpch_cases.json @@ -566,149 +566,208 @@ "ResultColumns": 4, "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|4) ASC, (1|5) ASC, (2|6) ASC", + "OperatorType": "Projection", + "Expressions": [ + ":2 as supp_nation", + ":3 as cust_nation", + ":4 as l_year", + "sum(volume) * count(*) as revenue", + ":5 as weight_string(supp_nation)", + ":6 as weight_string(cust_nation)", + ":7 as weight_string(l_year)" + ], "Inputs": [ { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "L:0,R:0,L:1,L:2,L:4,R:1,L:5", - "JoinVars": { - "n1_n_name": 0, - "o_custkey": 3 - }, - "TableName": "lineitem_orders_supplier_nation_customer_nation", + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(2|5) ASC, (3|6) ASC, (4|7) ASC", "Inputs": [ { "OperatorType": "Join", "Variant": "Join", - "JoinColumnIndexes": "R:0,L:0,L:1,L:2,R:1,L:4", + "JoinColumnIndexes": "L:0,R:0,L:1,R:1,L:2,L:4,R:2,L:5", "JoinVars": { - "l_suppkey": 3 + "n1_n_name": 1, + "o_custkey": 3 }, - "TableName": "lineitem_orders_supplier_nation", + "TableName": "lineitem_orders_supplier_nation_customer_nation", "Inputs": [ { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "L:0,L:1,R:0,L:2,L:4", - "JoinVars": { - "l_orderkey": 3 - }, - "TableName": "lineitem_orders", + "OperatorType": "Projection", + "Expressions": [ + "sum(volume) * count(*) as revenue", + ":2 as supp_nation", + ":3 as l_year", + ":4 as o_custkey", + ":5 as weight_string(supp_nation)", + ":6 as weight_string(l_year)" + ], "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "FieldQuery": "select shipping.l_year, shipping.volume, shipping.l_suppkey, shipping.l_orderkey, weight_string(shipping.l_year) from (select extract(year from l_shipdate) as l_year, l_extendedprice * (1 - l_discount) as volume, l_suppkey as l_suppkey, l_orderkey as l_orderkey from lineitem where 1 != 1) as shipping where 1 != 1", - "Query": "select shipping.l_year, shipping.volume, shipping.l_suppkey, shipping.l_orderkey, weight_string(shipping.l_year) from (select extract(year from l_shipdate) as l_year, l_extendedprice * (1 - l_discount) as volume, l_suppkey as l_suppkey, l_orderkey as l_orderkey from lineitem where l_shipdate between date('1995-01-01') and date('1996-12-31')) as shipping", - "Table": "lineitem" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "main", - "Sharded": true + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,R:0,R:1,L:1,L:2,R:2,L:4", + "JoinVars": { + "l_suppkey": 3 }, - "FieldQuery": "select shipping.o_custkey from (select o_custkey as o_custkey from orders where 1 != 1) as shipping where 1 != 1", - "Query": "select shipping.o_custkey from (select o_custkey as o_custkey from orders where o_orderkey = :l_orderkey) as shipping", - "Table": "orders", - "Values": [ - ":l_orderkey" - ], - "Vindex": "hash" + "TableName": "lineitem_orders_supplier_nation", + "Inputs": [ + { + "OperatorType": "Projection", + "Expressions": [ + "sum(volume) * count(*) as revenue", + ":2 as l_year", + ":3 as o_custkey", + ":4 as l_suppkey", + ":5 as weight_string(l_year)" + ], + "Inputs": [ + { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,R:0,L:1,R:1,L:2,L:4", + "JoinVars": { + "l_orderkey": 3 + }, + "TableName": "lineitem_orders", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select sum(volume) as revenue, l_year, shipping.l_suppkey, shipping.l_orderkey, weight_string(l_year) from (select extract(year from l_shipdate) as l_year, l_extendedprice * (1 - l_discount) as volume, l_suppkey as l_suppkey, l_orderkey as l_orderkey from lineitem where 1 != 1) as shipping where 1 != 1 group by l_year, shipping.l_suppkey, shipping.l_orderkey, weight_string(l_year)", + "Query": "select sum(volume) as revenue, l_year, shipping.l_suppkey, shipping.l_orderkey, weight_string(l_year) from (select extract(year from l_shipdate) as l_year, l_extendedprice * (1 - l_discount) as volume, l_suppkey as l_suppkey, l_orderkey as l_orderkey from lineitem where l_shipdate between date('1995-01-01') and date('1996-12-31')) as shipping group by l_year, shipping.l_suppkey, shipping.l_orderkey, weight_string(l_year)", + "Table": "lineitem" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select count(*), shipping.o_custkey from (select o_custkey as o_custkey from orders where 1 != 1) as shipping where 1 != 1 group by shipping.o_custkey", + "Query": "select count(*), shipping.o_custkey from (select o_custkey as o_custkey from orders where o_orderkey = :l_orderkey) as shipping group by shipping.o_custkey", + "Table": "orders", + "Values": [ + ":l_orderkey" + ], + "Vindex": "hash" + } + ] + } + ] + }, + { + "OperatorType": "Projection", + "Expressions": [ + "count(*) * count(*) as count(*)", + ":2 as supp_nation", + ":3 as weight_string(supp_nation)" + ], + "Inputs": [ + { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,R:0,R:1,R:2", + "JoinVars": { + "s_nationkey": 1 + }, + "TableName": "supplier_nation", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select count(*), shipping.s_nationkey from (select s_nationkey as s_nationkey from supplier where 1 != 1) as shipping where 1 != 1 group by shipping.s_nationkey", + "Query": "select count(*), shipping.s_nationkey from (select s_nationkey as s_nationkey from supplier where s_suppkey = :l_suppkey) as shipping group by shipping.s_nationkey", + "Table": "supplier", + "Values": [ + ":l_suppkey" + ], + "Vindex": "hash" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select count(*), supp_nation, weight_string(supp_nation) from (select n1.n_name as supp_nation from nation as n1 where 1 != 1) as shipping where 1 != 1 group by supp_nation, weight_string(supp_nation)", + "Query": "select count(*), supp_nation, weight_string(supp_nation) from (select n1.n_name as supp_nation from nation as n1 where n1.n_nationkey = :s_nationkey) as shipping group by supp_nation, weight_string(supp_nation)", + "Table": "nation", + "Values": [ + ":s_nationkey" + ], + "Vindex": "hash" + } + ] + } + ] + } + ] } ] }, { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "R:0,R:1", - "JoinVars": { - "s_nationkey": 0 - }, - "TableName": "supplier_nation", + "OperatorType": "Projection", + "Expressions": [ + "count(*) * count(*) as count(*)", + ":2 as cust_nation", + ":3 as weight_string(cust_nation)" + ], "Inputs": [ { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "FieldQuery": "select shipping.s_nationkey from (select s_nationkey as s_nationkey from supplier where 1 != 1) as shipping where 1 != 1", - "Query": "select shipping.s_nationkey from (select s_nationkey as s_nationkey from supplier where s_suppkey = :l_suppkey) as shipping", - "Table": "supplier", - "Values": [ - ":l_suppkey" - ], - "Vindex": "hash" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "main", - "Sharded": true + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,R:0,R:1,R:2", + "JoinVars": { + "c_nationkey": 1 }, - "FieldQuery": "select shipping.supp_nation, weight_string(shipping.supp_nation) from (select n1.n_name as supp_nation from nation as n1 where 1 != 1) as shipping where 1 != 1", - "Query": "select shipping.supp_nation, weight_string(shipping.supp_nation) from (select n1.n_name as supp_nation from nation as n1 where n1.n_nationkey = :s_nationkey) as shipping", - "Table": "nation", - "Values": [ - ":s_nationkey" - ], - "Vindex": "hash" + "TableName": "customer_nation", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select count(*), shipping.c_nationkey from (select c_nationkey as c_nationkey from customer where 1 != 1) as shipping where 1 != 1 group by shipping.c_nationkey", + "Query": "select count(*), shipping.c_nationkey from (select c_nationkey as c_nationkey from customer where c_custkey = :o_custkey) as shipping group by shipping.c_nationkey", + "Table": "customer", + "Values": [ + ":o_custkey" + ], + "Vindex": "hash" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select count(*), cust_nation, weight_string(cust_nation) from (select n2.n_name as cust_nation from nation as n2 where 1 != 1) as shipping where 1 != 1 group by cust_nation, weight_string(cust_nation)", + "Query": "select count(*), cust_nation, weight_string(cust_nation) from (select n2.n_name as cust_nation from nation as n2 where (:n1_n_name = 'FRANCE' and n2.n_name = 'GERMANY' or :n1_n_name = 'GERMANY' and n2.n_name = 'FRANCE') and n2.n_nationkey = :c_nationkey) as shipping group by cust_nation, weight_string(cust_nation)", + "Table": "nation", + "Values": [ + ":c_nationkey" + ], + "Vindex": "hash" + } + ] } ] } ] - }, - { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "R:0,R:1", - "JoinVars": { - "c_nationkey": 0 - }, - "TableName": "customer_nation", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "FieldQuery": "select shipping.c_nationkey from (select c_nationkey as c_nationkey from customer where 1 != 1) as shipping where 1 != 1", - "Query": "select shipping.c_nationkey from (select c_nationkey as c_nationkey from customer where c_custkey = :o_custkey) as shipping", - "Table": "customer", - "Values": [ - ":o_custkey" - ], - "Vindex": "hash" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "FieldQuery": "select shipping.cust_nation, weight_string(shipping.cust_nation) from (select n2.n_name as cust_nation from nation as n2 where 1 != 1) as shipping where 1 != 1", - "Query": "select shipping.cust_nation, weight_string(shipping.cust_nation) from (select n2.n_name as cust_nation from nation as n2 where (:n1_n_name = 'FRANCE' and n2.n_name = 'GERMANY' or :n1_n_name = 'GERMANY' and n2.n_name = 'FRANCE') and n2.n_nationkey = :c_nationkey) as shipping", - "Table": "nation", - "Values": [ - ":c_nationkey" - ], - "Vindex": "hash" - } - ] } ] } @@ -746,200 +805,245 @@ "ResultColumns": 3, "Inputs": [ { - "OperatorType": "SimpleProjection", - "Columns": "0,3,1,4", + "OperatorType": "Projection", + "Expressions": [ + ":3 as o_year", + "sum(case when nation = 'BRAZIL' then volume else 0 end) * count(*) as sum(case when nation = 'BRAZIL' then volume else 0 end)", + "sum(volume) * count(*) as sum(volume)", + ":4 as weight_string(o_year)" + ], "Inputs": [ { "OperatorType": "Sort", "Variant": "Memory", - "OrderBy": "(0|4) ASC", + "OrderBy": "(3|4) ASC", "Inputs": [ { "OperatorType": "Join", "Variant": "Join", - "JoinColumnIndexes": "R:0,L:0,L:1,L:3,R:1", + "JoinColumnIndexes": "L:0,R:0,L:1,R:1,R:2", "JoinVars": { "l_orderkey": 2 }, "TableName": "lineitem_part_supplier_nation_orders_customer_nation_region", "Inputs": [ { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "L:0,R:0,L:1,R:1", - "JoinVars": { - "l_suppkey": 2, - "volume": 0 - }, - "TableName": "lineitem_part_supplier_nation", + "OperatorType": "Aggregate", + "Variant": "Ordered", + "Aggregates": "sum(0) AS sum(case when nation = 'BRAZIL' then volume else 0 end), sum(1) AS sum(volume)", + "GroupBy": "(2|3)", + "ResultColumns": 3, "Inputs": [ { "OperatorType": "Join", "Variant": "Join", - "JoinColumnIndexes": "L:0,L:1,L:2", + "JoinColumnIndexes": "R:1,L:0,L:1,L:3", "JoinVars": { - "l_partkey": 3 + "l_suppkey": 2, + "volume": 0 }, - "TableName": "lineitem_part", + "TableName": "lineitem_part_supplier_nation", "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "main", - "Sharded": true + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,L:1,L:2,L:4", + "JoinVars": { + "l_partkey": 3 }, - "FieldQuery": "select all_nations.volume, all_nations.l_orderkey, all_nations.l_suppkey, all_nations.l_partkey from (select l_extendedprice * (1 - l_discount) as volume, l_orderkey as l_orderkey, l_suppkey as l_suppkey, l_partkey as l_partkey from lineitem where 1 != 1) as all_nations where 1 != 1", - "Query": "select all_nations.volume, all_nations.l_orderkey, all_nations.l_suppkey, all_nations.l_partkey from (select l_extendedprice * (1 - l_discount) as volume, l_orderkey as l_orderkey, l_suppkey as l_suppkey, l_partkey as l_partkey from lineitem) as all_nations", - "Table": "lineitem" + "TableName": "lineitem_part", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select all_nations.volume, all_nations.l_orderkey, all_nations.l_suppkey, all_nations.l_partkey, weight_string(all_nations.l_orderkey) from (select l_extendedprice * (1 - l_discount) as volume, l_orderkey as l_orderkey, l_suppkey as l_suppkey, l_partkey as l_partkey from lineitem where 1 != 1) as all_nations where 1 != 1", + "OrderBy": "(1|4) ASC", + "Query": "select all_nations.volume, all_nations.l_orderkey, all_nations.l_suppkey, all_nations.l_partkey, weight_string(all_nations.l_orderkey) from (select l_extendedprice * (1 - l_discount) as volume, l_orderkey as l_orderkey, l_suppkey as l_suppkey, l_partkey as l_partkey from lineitem) as all_nations order by all_nations.l_orderkey asc", + "Table": "lineitem" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select 1 from part where 1 != 1", + "Query": "select 1 from part where p_type = 'ECONOMY ANODIZED STEEL' and p_partkey = :l_partkey", + "Table": "part", + "Values": [ + ":l_partkey" + ], + "Vindex": "hash" + } + ] }, { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "main", - "Sharded": true + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "R:0,R:1", + "JoinVars": { + "s_nationkey": 0 }, - "FieldQuery": "select 1 from part where 1 != 1", - "Query": "select 1 from part where p_type = 'ECONOMY ANODIZED STEEL' and p_partkey = :l_partkey", - "Table": "part", - "Values": [ - ":l_partkey" - ], - "Vindex": "hash" - } - ] - }, - { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "R:0,R:1", - "JoinVars": { - "s_nationkey": 0 - }, - "TableName": "supplier_nation", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "FieldQuery": "select all_nations.s_nationkey from (select s_nationkey as s_nationkey from supplier where 1 != 1) as all_nations where 1 != 1", - "Query": "select all_nations.s_nationkey from (select s_nationkey as s_nationkey from supplier where s_suppkey = :l_suppkey) as all_nations", - "Table": "supplier", - "Values": [ - ":l_suppkey" - ], - "Vindex": "hash" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "FieldQuery": "select all_nations.nation, case when nation = 'BRAZIL' then :volume else 0 end from (select n2.n_name as nation from nation as n2 where 1 != 1) as all_nations where 1 != 1", - "Query": "select all_nations.nation, case when nation = 'BRAZIL' then :volume else 0 end from (select n2.n_name as nation from nation as n2 where n2.n_nationkey = :s_nationkey) as all_nations", - "Table": "nation", - "Values": [ - ":s_nationkey" - ], - "Vindex": "hash" + "TableName": "supplier_nation", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select all_nations.s_nationkey from (select s_nationkey as s_nationkey from supplier where 1 != 1) as all_nations where 1 != 1", + "Query": "select all_nations.s_nationkey from (select s_nationkey as s_nationkey from supplier where s_suppkey = :l_suppkey) as all_nations", + "Table": "supplier", + "Values": [ + ":l_suppkey" + ], + "Vindex": "hash" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select all_nations.nation, case when nation = 'BRAZIL' then :volume else 0 end from (select n2.n_name as nation from nation as n2 where 1 != 1) as all_nations where 1 != 1", + "Query": "select all_nations.nation, case when nation = 'BRAZIL' then :volume else 0 end from (select n2.n_name as nation from nation as n2 where n2.n_nationkey = :s_nationkey) as all_nations", + "Table": "nation", + "Values": [ + ":s_nationkey" + ], + "Vindex": "hash" + } + ] } ] } ] }, { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "L:0,L:2", - "JoinVars": { - "c_nationkey": 1 - }, - "TableName": "orders_customer_nation_region", + "OperatorType": "Projection", + "Expressions": [ + "count(*) * count(*) as count(*)", + ":2 as o_year", + ":3 as weight_string(o_year)" + ], "Inputs": [ { "OperatorType": "Join", "Variant": "Join", - "JoinColumnIndexes": "L:0,R:0,L:2", - "JoinVars": { - "o_custkey": 1 - }, - "TableName": "orders_customer", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "FieldQuery": "select all_nations.o_year, all_nations.o_custkey, weight_string(all_nations.o_year) from (select extract(year from o_orderdate) as o_year, o_custkey as o_custkey from orders where 1 != 1) as all_nations where 1 != 1", - "Query": "select all_nations.o_year, all_nations.o_custkey, weight_string(all_nations.o_year) from (select extract(year from o_orderdate) as o_year, o_custkey as o_custkey from orders where o_orderdate between date'1995-01-01' and date('1996-12-31') and o_orderkey = :l_orderkey) as all_nations", - "Table": "orders", - "Values": [ - ":l_orderkey" - ], - "Vindex": "hash" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "FieldQuery": "select all_nations.c_nationkey from (select c_nationkey as c_nationkey from customer where 1 != 1) as all_nations where 1 != 1", - "Query": "select all_nations.c_nationkey from (select c_nationkey as c_nationkey from customer where c_custkey = :o_custkey) as all_nations", - "Table": "customer", - "Values": [ - ":o_custkey" - ], - "Vindex": "hash" - } - ] - }, - { - "OperatorType": "Join", - "Variant": "Join", + "JoinColumnIndexes": "L:0,R:0,L:1,L:3", "JoinVars": { - "n1_n_regionkey": 0 + "c_nationkey": 2 }, - "TableName": "nation_region", + "TableName": "orders_customer_nation_region", "Inputs": [ { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "FieldQuery": "select n1.n_regionkey from nation as n1 where 1 != 1", - "Query": "select n1.n_regionkey from nation as n1 where n1.n_nationkey = :c_nationkey", - "Table": "nation", - "Values": [ - ":c_nationkey" + "OperatorType": "Projection", + "Expressions": [ + "count(*) * count(*) as count(*)", + ":2 as o_year", + ":3 as c_nationkey", + ":4 as weight_string(o_year)" ], - "Vindex": "hash" + "Inputs": [ + { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,R:0,L:1,R:1,L:3", + "JoinVars": { + "o_custkey": 2 + }, + "TableName": "orders_customer", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select count(*), o_year, all_nations.o_custkey, weight_string(o_year) from (select extract(year from o_orderdate) as o_year, o_custkey as o_custkey from orders where 1 != 1) as all_nations where 1 != 1 group by o_year, all_nations.o_custkey, weight_string(o_year)", + "Query": "select count(*), o_year, all_nations.o_custkey, weight_string(o_year) from (select extract(year from o_orderdate) as o_year, o_custkey as o_custkey from orders where o_orderdate between date'1995-01-01' and date('1996-12-31') and o_orderkey = :l_orderkey) as all_nations group by o_year, all_nations.o_custkey, weight_string(o_year)", + "Table": "orders", + "Values": [ + ":l_orderkey" + ], + "Vindex": "hash" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select count(*), all_nations.c_nationkey from (select c_nationkey as c_nationkey from customer where 1 != 1) as all_nations where 1 != 1 group by all_nations.c_nationkey", + "Query": "select count(*), all_nations.c_nationkey from (select c_nationkey as c_nationkey from customer where c_custkey = :o_custkey) as all_nations group by all_nations.c_nationkey", + "Table": "customer", + "Values": [ + ":o_custkey" + ], + "Vindex": "hash" + } + ] + } + ] }, { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "FieldQuery": "select 1 from region where 1 != 1", - "Query": "select 1 from region where r_name = 'AMERICA' and r_regionkey = :n1_n_regionkey", - "Table": "region", - "Values": [ - ":n1_n_regionkey" + "OperatorType": "Projection", + "Expressions": [ + "count(*) * count(*) as count(*)" ], - "Vindex": "hash" + "Inputs": [ + { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,R:0", + "JoinVars": { + "n1_n_regionkey": 1 + }, + "TableName": "nation_region", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select count(*), n1.n_regionkey from nation as n1 where 1 != 1 group by n1.n_regionkey", + "Query": "select count(*), n1.n_regionkey from nation as n1 where n1.n_nationkey = :c_nationkey group by n1.n_regionkey", + "Table": "nation", + "Values": [ + ":c_nationkey" + ], + "Vindex": "hash" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select count(*) from region where 1 != 1 group by .0", + "Query": "select count(*) from region where r_name = 'AMERICA' and r_regionkey = :n1_n_regionkey group by .0", + "Table": "region", + "Values": [ + ":n1_n_regionkey" + ], + "Vindex": "hash" + } + ] + } + ] } ] } @@ -980,61 +1084,144 @@ "ResultColumns": 3, "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|3) ASC, (1|4) DESC", + "OperatorType": "Projection", + "Expressions": [ + ":2 as nation", + ":3 as o_year", + "sum(amount) * count(*) as sum_profit", + ":4 as weight_string(nation)", + ":5 as weight_string(o_year)" + ], "Inputs": [ { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "R:0,L:0,L:1,R:1,L:3", - "JoinVars": { - "l_suppkey": 2 - }, - "TableName": "orders_lineitem_part_partsupp_supplier_nation", + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(2|4) ASC, (3|5) DESC", "Inputs": [ { "OperatorType": "Join", "Variant": "Join", - "JoinColumnIndexes": "L:0,R:0,L:4,L:6", + "JoinColumnIndexes": "L:0,R:0,R:1,L:1,R:2,L:3", "JoinVars": { - "l_discount": 2, - "l_extendedprice": 1, - "l_partkey": 5, - "l_quantity": 3, - "l_suppkey": 4 + "l_suppkey": 2 }, - "TableName": "orders_lineitem_part_partsupp", + "TableName": "orders_lineitem_part_partsupp_supplier_nation", "Inputs": [ { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "L:0,R:0,R:1,R:2,R:3,R:4,L:2", - "JoinVars": { - "o_orderkey": 1 - }, - "TableName": "orders_lineitem_part", + "OperatorType": "Aggregate", + "Variant": "Ordered", + "Aggregates": "sum(0) AS sum_profit", + "GroupBy": "(1|3), (2|4)", + "ResultColumns": 4, "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "FieldQuery": "select profit.o_year, profit.o_orderkey, weight_string(profit.o_year) from (select extract(year from o_orderdate) as o_year, o_orderkey as o_orderkey from orders where 1 != 1) as profit where 1 != 1", - "Query": "select profit.o_year, profit.o_orderkey, weight_string(profit.o_year) from (select extract(year from o_orderdate) as o_year, o_orderkey as o_orderkey from orders) as profit", - "Table": "orders" - }, { "OperatorType": "Join", "Variant": "Join", - "JoinColumnIndexes": "L:0,L:1,L:2,L:3,L:4", + "JoinColumnIndexes": "R:0,L:0,L:4,L:6,L:7", "JoinVars": { - "l_partkey": 4 + "l_discount": 2, + "l_extendedprice": 1, + "l_partkey": 5, + "l_quantity": 3, + "l_suppkey": 4 }, - "TableName": "lineitem_part", + "TableName": "orders_lineitem_part_partsupp", "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|6) ASC, (4|7) ASC", + "Inputs": [ + { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,R:0,R:1,R:2,R:3,R:4,L:2,R:5", + "JoinVars": { + "o_orderkey": 1 + }, + "TableName": "orders_lineitem_part", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select profit.o_year, profit.o_orderkey, weight_string(profit.o_year) from (select extract(year from o_orderdate) as o_year, o_orderkey as o_orderkey from orders where 1 != 1) as profit where 1 != 1", + "Query": "select profit.o_year, profit.o_orderkey, weight_string(profit.o_year) from (select extract(year from o_orderdate) as o_year, o_orderkey as o_orderkey from orders) as profit", + "Table": "orders" + }, + { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,L:1,L:2,L:3,L:4,L:5", + "JoinVars": { + "l_partkey": 4 + }, + "TableName": "lineitem_part", + "Inputs": [ + { + "OperatorType": "VindexLookup", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "Values": [ + ":o_orderkey" + ], + "Vindex": "lineitem_map", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "IN", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select l_orderkey, l_linenumber from lineitem_map where 1 != 1", + "Query": "select l_orderkey, l_linenumber from lineitem_map where l_orderkey in ::__vals", + "Table": "lineitem_map", + "Values": [ + "::l_orderkey" + ], + "Vindex": "md5" + }, + { + "OperatorType": "Route", + "Variant": "ByDestination", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select profit.l_extendedprice, profit.l_discount, profit.l_quantity, profit.l_suppkey, profit.l_partkey, weight_string(profit.l_suppkey) from (select l_extendedprice, l_discount, l_quantity, l_suppkey as l_suppkey, l_partkey as l_partkey from lineitem where 1 != 1) as profit where 1 != 1", + "Query": "select profit.l_extendedprice, profit.l_discount, profit.l_quantity, profit.l_suppkey, profit.l_partkey, weight_string(profit.l_suppkey) from (select l_extendedprice, l_discount, l_quantity, l_suppkey as l_suppkey, l_partkey as l_partkey from lineitem where l_orderkey = :o_orderkey) as profit", + "Table": "lineitem" + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select 1 from part where 1 != 1", + "Query": "select 1 from part where p_name like '%green%' and p_partkey = :l_partkey", + "Table": "part", + "Values": [ + ":l_partkey" + ], + "Vindex": "hash" + } + ] + } + ] + } + ] + }, { "OperatorType": "VindexLookup", "Variant": "EqualUnique", @@ -1043,9 +1230,9 @@ "Sharded": true }, "Values": [ - ":o_orderkey" + ":l_partkey" ], - "Vindex": "lineitem_map", + "Vindex": "partsupp_map", "Inputs": [ { "OperatorType": "Route", @@ -1054,11 +1241,11 @@ "Name": "main", "Sharded": true }, - "FieldQuery": "select l_orderkey, l_linenumber from lineitem_map where 1 != 1", - "Query": "select l_orderkey, l_linenumber from lineitem_map where l_orderkey in ::__vals", - "Table": "lineitem_map", + "FieldQuery": "select ps_partkey, ps_suppkey from partsupp_map where 1 != 1", + "Query": "select ps_partkey, ps_suppkey from partsupp_map where ps_partkey in ::__vals", + "Table": "partsupp_map", "Values": [ - "::l_orderkey" + "::ps_partkey" ], "Vindex": "md5" }, @@ -1069,11 +1256,47 @@ "Name": "main", "Sharded": true }, - "FieldQuery": "select profit.l_extendedprice, profit.l_discount, profit.l_quantity, profit.l_suppkey, profit.l_partkey from (select l_extendedprice, l_discount, l_quantity, l_suppkey as l_suppkey, l_partkey as l_partkey from lineitem where 1 != 1) as profit where 1 != 1", - "Query": "select profit.l_extendedprice, profit.l_discount, profit.l_quantity, profit.l_suppkey, profit.l_partkey from (select l_extendedprice, l_discount, l_quantity, l_suppkey as l_suppkey, l_partkey as l_partkey from lineitem where l_orderkey = :o_orderkey) as profit", - "Table": "lineitem" + "FieldQuery": "select profit.amount from (select :l_extendedprice * (1 - :l_discount) - ps_supplycost * :l_quantity as amount from partsupp where 1 != 1) as profit where 1 != 1", + "Query": "select profit.amount from (select :l_extendedprice * (1 - :l_discount) - ps_supplycost * :l_quantity as amount from partsupp where ps_partkey = :l_partkey and ps_suppkey = :l_suppkey) as profit", + "Table": "partsupp" } ] + } + ] + } + ] + }, + { + "OperatorType": "Projection", + "Expressions": [ + "count(*) * count(*) as count(*)", + ":2 as nation", + ":3 as weight_string(nation)" + ], + "Inputs": [ + { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,R:0,R:1,R:2", + "JoinVars": { + "s_nationkey": 1 + }, + "TableName": "supplier_nation", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select count(*), profit.s_nationkey from (select s_nationkey as s_nationkey from supplier where 1 != 1) as profit where 1 != 1 group by profit.s_nationkey", + "Query": "select count(*), profit.s_nationkey from (select s_nationkey as s_nationkey from supplier where s_suppkey = :l_suppkey) as profit group by profit.s_nationkey", + "Table": "supplier", + "Values": [ + ":l_suppkey" + ], + "Vindex": "hash" }, { "OperatorType": "Route", @@ -1082,98 +1305,17 @@ "Name": "main", "Sharded": true }, - "FieldQuery": "select 1 from part where 1 != 1", - "Query": "select 1 from part where p_name like '%green%' and p_partkey = :l_partkey", - "Table": "part", + "FieldQuery": "select count(*), nation, weight_string(nation) from (select n_name as nation from nation where 1 != 1) as profit where 1 != 1 group by nation, weight_string(nation)", + "Query": "select count(*), nation, weight_string(nation) from (select n_name as nation from nation where n_nationkey = :s_nationkey) as profit group by nation, weight_string(nation)", + "Table": "nation", "Values": [ - ":l_partkey" + ":s_nationkey" ], "Vindex": "hash" } ] } ] - }, - { - "OperatorType": "VindexLookup", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "Values": [ - ":l_partkey" - ], - "Vindex": "partsupp_map", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "IN", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "FieldQuery": "select ps_partkey, ps_suppkey from partsupp_map where 1 != 1", - "Query": "select ps_partkey, ps_suppkey from partsupp_map where ps_partkey in ::__vals", - "Table": "partsupp_map", - "Values": [ - "::ps_partkey" - ], - "Vindex": "md5" - }, - { - "OperatorType": "Route", - "Variant": "ByDestination", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "FieldQuery": "select profit.amount from (select :l_extendedprice * (1 - :l_discount) - ps_supplycost * :l_quantity as amount from partsupp where 1 != 1) as profit where 1 != 1", - "Query": "select profit.amount from (select :l_extendedprice * (1 - :l_discount) - ps_supplycost * :l_quantity as amount from partsupp where ps_partkey = :l_partkey and ps_suppkey = :l_suppkey) as profit", - "Table": "partsupp" - } - ] - } - ] - }, - { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "R:0,R:1", - "JoinVars": { - "s_nationkey": 0 - }, - "TableName": "supplier_nation", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "FieldQuery": "select profit.s_nationkey from (select s_nationkey as s_nationkey from supplier where 1 != 1) as profit where 1 != 1", - "Query": "select profit.s_nationkey from (select s_nationkey as s_nationkey from supplier where s_suppkey = :l_suppkey) as profit", - "Table": "supplier", - "Values": [ - ":l_suppkey" - ], - "Vindex": "hash" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "FieldQuery": "select profit.nation, weight_string(profit.nation) from (select n_name as nation from nation where 1 != 1) as profit where 1 != 1", - "Query": "select profit.nation, weight_string(profit.nation) from (select n_name as nation from nation where n_nationkey = :s_nationkey) as profit", - "Table": "nation", - "Values": [ - ":s_nationkey" - ], - "Vindex": "hash" } ] } @@ -1645,67 +1787,78 @@ "ResultColumns": 3, "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|3) ASC", + "OperatorType": "Projection", + "Expressions": [ + ":3 as l_shipmode", + "sum(case when o_orderpriority = '1-URGENT' or o_orderpriority = '2-HIGH' then 1 else 0 end) * count(*) as high_line_count", + "sum(case when o_orderpriority != '1-URGENT' and o_orderpriority != '2-HIGH' then 1 else 0 end) * count(*) as low_line_count", + ":4 as weight_string(l_shipmode)" + ], "Inputs": [ { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "R:0,L:0,L:1,R:1", - "JoinVars": { - "o_orderkey": 2 - }, - "TableName": "orders_lineitem", + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(3|4) ASC", "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "FieldQuery": "select case when o_orderpriority = '1-URGENT' or o_orderpriority = '2-HIGH' then 1 else 0 end, case when o_orderpriority != '1-URGENT' and o_orderpriority != '2-HIGH' then 1 else 0 end, o_orderkey from orders where 1 != 1", - "Query": "select case when o_orderpriority = '1-URGENT' or o_orderpriority = '2-HIGH' then 1 else 0 end, case when o_orderpriority != '1-URGENT' and o_orderpriority != '2-HIGH' then 1 else 0 end, o_orderkey from orders", - "Table": "orders" - }, - { - "OperatorType": "VindexLookup", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "main", - "Sharded": true + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,R:0,L:1,R:1,R:2", + "JoinVars": { + "o_orderkey": 2 }, - "Values": [ - ":o_orderkey" - ], - "Vindex": "lineitem_map", + "TableName": "orders_lineitem", "Inputs": [ { "OperatorType": "Route", - "Variant": "IN", + "Variant": "Scatter", "Keyspace": { "Name": "main", "Sharded": true }, - "FieldQuery": "select l_orderkey, l_linenumber from lineitem_map where 1 != 1", - "Query": "select l_orderkey, l_linenumber from lineitem_map where l_orderkey in ::__vals", - "Table": "lineitem_map", - "Values": [ - "::l_orderkey" - ], - "Vindex": "md5" + "FieldQuery": "select sum(case when o_orderpriority = '1-URGENT' or o_orderpriority = '2-HIGH' then 1 else 0 end) as high_line_count, sum(case when o_orderpriority != '1-URGENT' and o_orderpriority != '2-HIGH' then 1 else 0 end) as low_line_count, o_orderkey from orders where 1 != 1 group by o_orderkey", + "Query": "select sum(case when o_orderpriority = '1-URGENT' or o_orderpriority = '2-HIGH' then 1 else 0 end) as high_line_count, sum(case when o_orderpriority != '1-URGENT' and o_orderpriority != '2-HIGH' then 1 else 0 end) as low_line_count, o_orderkey from orders group by o_orderkey", + "Table": "orders" }, { - "OperatorType": "Route", - "Variant": "ByDestination", + "OperatorType": "VindexLookup", + "Variant": "EqualUnique", "Keyspace": { "Name": "main", "Sharded": true }, - "FieldQuery": "select l_shipmode, weight_string(l_shipmode) from lineitem where 1 != 1", - "Query": "select l_shipmode, weight_string(l_shipmode) from lineitem where l_shipmode in ('MAIL', 'SHIP') and l_commitdate < l_receiptdate and l_shipdate < l_commitdate and l_receiptdate >= date('1994-01-01') and l_receiptdate < date('1994-01-01') + interval '1' year and l_orderkey = :o_orderkey", - "Table": "lineitem" + "Values": [ + ":o_orderkey" + ], + "Vindex": "lineitem_map", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "IN", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select l_orderkey, l_linenumber from lineitem_map where 1 != 1", + "Query": "select l_orderkey, l_linenumber from lineitem_map where l_orderkey in ::__vals", + "Table": "lineitem_map", + "Values": [ + "::l_orderkey" + ], + "Vindex": "md5" + }, + { + "OperatorType": "Route", + "Variant": "ByDestination", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select count(*), l_shipmode, weight_string(l_shipmode) from lineitem where 1 != 1 group by l_shipmode, weight_string(l_shipmode)", + "Query": "select count(*), l_shipmode, weight_string(l_shipmode) from lineitem where l_shipmode in ('MAIL', 'SHIP') and l_commitdate < l_receiptdate and l_shipdate < l_commitdate and l_receiptdate >= date('1994-01-01') and l_receiptdate < date('1994-01-01') + interval '1' year and l_orderkey = :o_orderkey group by l_shipmode, weight_string(l_shipmode)", + "Table": "lineitem" + } + ] } ] } @@ -1908,8 +2061,8 @@ "Name": "main", "Sharded": true }, - "FieldQuery": "select max(total_revenue), weight_string(total_revenue) from revenue0 where 1 != 1 group by weight_string(total_revenue)", - "Query": "select max(total_revenue), weight_string(total_revenue) from revenue0 group by weight_string(total_revenue)", + "FieldQuery": "select max(total_revenue), weight_string(max(total_revenue)) from revenue0 where 1 != 1", + "Query": "select max(total_revenue), weight_string(max(total_revenue)) from revenue0", "Table": "revenue0" } ] @@ -2078,25 +2231,34 @@ }, { "InputName": "Outer", - "OperatorType": "Filter", - "Predicate": ":__sq_has_values and o_orderkey in ::__sq1", + "OperatorType": "Projection", + "Expressions": [ + ":2 as c_name", + ":3 as c_custkey", + ":4 as o_orderkey", + ":5 as o_orderdate", + ":6 as o_totalprice", + "sum(l_quantity) * count(*) as sum(l_quantity)", + ":7 as weight_string(o_totalprice)", + ":8 as weight_string(o_orderdate)", + ":9 as weight_string(c_name)", + ":10 as weight_string(c_custkey)", + ":11 as weight_string(o_orderkey)" + ], "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "Aggregates": "sum(5) AS sum(l_quantity)", - "GroupBy": "(4|6), (3|7), (0|8), (1|9), (2|10)", - "ResultColumns": 11, + "OperatorType": "Filter", + "Predicate": ":__sq_has_values and o_orderkey in ::__sq1", "Inputs": [ { "OperatorType": "Sort", "Variant": "Memory", - "OrderBy": "(4|6) DESC, (3|7) ASC, (0|8) ASC, (1|9) ASC, (2|10) ASC", + "OrderBy": "(6|7) DESC, (5|8) ASC, (2|9) ASC, (3|10) ASC, (4|11) ASC", "Inputs": [ { "OperatorType": "Join", "Variant": "Join", - "JoinColumnIndexes": "R:0,R:1,R:2,R:3,R:4,L:0,R:5,R:6,R:7,R:8,R:9", + "JoinColumnIndexes": "L:0,R:0,R:1,R:2,R:3,R:4,R:5,R:6,R:7,R:8,R:9,R:10", "JoinVars": { "l_orderkey": 1 }, @@ -2109,48 +2271,66 @@ "Name": "main", "Sharded": true }, - "FieldQuery": "select l_quantity, l_orderkey from lineitem where 1 != 1", - "Query": "select l_quantity, l_orderkey from lineitem", + "FieldQuery": "select sum(l_quantity), l_orderkey from lineitem where 1 != 1 group by l_orderkey", + "Query": "select sum(l_quantity), l_orderkey from lineitem group by l_orderkey", "Table": "lineitem" }, { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "R:0,R:1,L:0,L:1,L:2,L:3,L:4,R:2,R:3,L:5", - "JoinVars": { - "o_custkey": 6 - }, - "TableName": "orders_customer", + "OperatorType": "Projection", + "Expressions": [ + "count(*) * count(*) as count(*)", + ":2 as c_name", + ":3 as c_custkey", + ":4 as o_orderkey", + ":5 as o_orderdate", + ":6 as o_totalprice", + ":7 as weight_string(o_totalprice)", + ":8 as weight_string(o_orderdate)", + ":9 as weight_string(c_name)", + ":10 as weight_string(c_custkey)", + ":11 as weight_string(o_orderkey)" + ], "Inputs": [ { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "FieldQuery": "select o_orderkey, o_orderdate, o_totalprice, weight_string(o_totalprice), weight_string(o_orderdate), weight_string(o_orderkey), o_custkey from orders where 1 != 1", - "Query": "select o_orderkey, o_orderdate, o_totalprice, weight_string(o_totalprice), weight_string(o_orderdate), weight_string(o_orderkey), o_custkey from orders where o_orderkey = :l_orderkey", - "Table": "orders", - "Values": [ - ":l_orderkey" - ], - "Vindex": "hash" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "main", - "Sharded": true + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,R:0,R:1,R:2,L:1,L:2,L:3,L:5,L:6,R:3,R:4,L:7", + "JoinVars": { + "o_custkey": 4 }, - "FieldQuery": "select c_name, c_custkey, weight_string(c_name), weight_string(c_custkey) from customer where 1 != 1", - "Query": "select c_name, c_custkey, weight_string(c_name), weight_string(c_custkey) from customer where c_custkey = :o_custkey", - "Table": "customer", - "Values": [ - ":o_custkey" - ], - "Vindex": "hash" + "TableName": "orders_customer", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select count(*), o_orderkey, o_orderdate, o_totalprice, o_custkey, weight_string(o_totalprice), weight_string(o_orderdate), weight_string(o_orderkey) from orders where 1 != 1 group by o_orderkey, o_orderdate, o_totalprice, o_custkey, weight_string(o_totalprice), weight_string(o_orderdate), weight_string(o_orderkey)", + "Query": "select count(*), o_orderkey, o_orderdate, o_totalprice, o_custkey, weight_string(o_totalprice), weight_string(o_orderdate), weight_string(o_orderkey) from orders where o_orderkey = :l_orderkey group by o_orderkey, o_orderdate, o_totalprice, o_custkey, weight_string(o_totalprice), weight_string(o_orderdate), weight_string(o_orderkey)", + "Table": "orders", + "Values": [ + ":l_orderkey" + ], + "Vindex": "hash" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select count(*), c_name, c_custkey, weight_string(c_name), weight_string(c_custkey) from customer where 1 != 1 group by c_name, c_custkey, weight_string(c_name), weight_string(c_custkey)", + "Query": "select count(*), c_name, c_custkey, weight_string(c_name), weight_string(c_custkey) from customer where c_custkey = :o_custkey group by c_name, c_custkey, weight_string(c_name), weight_string(c_custkey)", + "Table": "customer", + "Values": [ + ":o_custkey" + ], + "Vindex": "hash" + } + ] } ] } diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index 49458f8c608..7feabb0a698 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -376,9 +376,8 @@ "Instructions": { "OperatorType": "Distinct", "Collations": [ - "(0:1)" + "0" ], - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Route", @@ -387,8 +386,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select dt.c0 as id, weight_string(dt.c0) from (select id from `user` where 1 != 1 union select id from music where 1 != 1 union select 1 from dual where 1 != 1) as dt(c0) where 1 != 1", - "Query": "select dt.c0 as id, weight_string(dt.c0) from (select id from `user` union select id from music union select 1 from dual) as dt(c0)", + "FieldQuery": "select id from `user` where 1 != 1 union select id from music where 1 != 1 union select 1 from dual where 1 != 1", + "Query": "select id from `user` union select id from music union select 1 from dual", "Table": "`user`, dual, music" } ] @@ -526,9 +525,8 @@ "Instructions": { "OperatorType": "Distinct", "Collations": [ - "(0:1)" + "0" ], - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Route", @@ -537,8 +535,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select dt.c0 as `1`, weight_string(dt.c0) from (select 1 from dual where 1 != 1 union select null from dual where 1 != 1 union select 1.0 from dual where 1 != 1 union select '1' from dual where 1 != 1 union select 2 from dual where 1 != 1 union select 2.0 from `user` where 1 != 1) as dt(c0) where 1 != 1", - "Query": "select dt.c0 as `1`, weight_string(dt.c0) from (select 1 from dual union select null from dual union select 1.0 from dual union select '1' from dual union select 2 from dual union select 2.0 from `user`) as dt(c0)", + "FieldQuery": "select 1 from dual where 1 != 1 union select null from dual where 1 != 1 union select 1.0 from dual where 1 != 1 union select '1' from dual where 1 != 1 union select 2 from dual where 1 != 1 union select 2.0 from `user` where 1 != 1", + "Query": "select 1 from dual union select null from dual union select 1.0 from dual union select '1' from dual union select 2 from dual union select 2.0 from `user`", "Table": "`user`, dual" } ] @@ -840,9 +838,8 @@ { "OperatorType": "Distinct", "Collations": [ - "(0:1)" + "0" ], - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Route", @@ -851,8 +848,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select dt.c0 as id, weight_string(dt.c0) from (select id from `user` where 1 != 1 union select 3 from dual where 1 != 1) as dt(c0) where 1 != 1", - "Query": "select dt.c0 as id, weight_string(dt.c0) from (select id from `user` union select 3 from dual limit :__upper_limit) as dt(c0)", + "FieldQuery": "select id from `user` where 1 != 1 union select 3 from dual where 1 != 1", + "Query": "select id from `user` union select 3 from dual limit :__upper_limit", "Table": "`user`, dual" } ] @@ -1092,7 +1089,7 @@ { "OperatorType": "Distinct", "Collations": [ - "(0:1)", + "0", "1" ], "Inputs": [ @@ -1663,9 +1660,8 @@ "Instructions": { "OperatorType": "Distinct", "Collations": [ - "(0:1)" + "0" ], - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Route", @@ -1674,8 +1670,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select dt.c0 as col1, weight_string(dt.c0) from (select col1 from `user` where 1 != 1 union select 3 from `user` where 1 != 1) as dt(c0) where 1 != 1", - "Query": "select dt.c0 as col1, weight_string(dt.c0) from (select col1 from `user` union select 3 from `user`) as dt(c0)", + "FieldQuery": "select col1 from `user` where 1 != 1 union select 3 from `user` where 1 != 1", + "Query": "select col1 from `user` union select 3 from `user`", "Table": "`user`" } ] @@ -1694,9 +1690,8 @@ "Instructions": { "OperatorType": "Distinct", "Collations": [ - "(0:1)" + "0" ], - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Route", @@ -1705,8 +1700,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select dt.c0 as `3`, weight_string(dt.c0) from (select 3 from `user` where 1 != 1 union select col1 from `user` where 1 != 1) as dt(c0) where 1 != 1", - "Query": "select dt.c0 as `3`, weight_string(dt.c0) from (select 3 from `user` union select col1 from `user`) as dt(c0)", + "FieldQuery": "select 3 from `user` where 1 != 1 union select col1 from `user` where 1 != 1", + "Query": "select 3 from `user` union select col1 from `user`", "Table": "`user`" } ] @@ -1725,9 +1720,8 @@ "Instructions": { "OperatorType": "Distinct", "Collations": [ - "(0:1)" + "0: binary" ], - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Route", @@ -1736,8 +1730,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select dt.c0 as `3`, weight_string(dt.c0) from (select 3 from `user` where 1 != 1 union select now() from `user` where 1 != 1) as dt(c0) where 1 != 1", - "Query": "select dt.c0 as `3`, weight_string(dt.c0) from (select 3 from `user` union select now() from `user`) as dt(c0)", + "FieldQuery": "select 3 from `user` where 1 != 1 union select now() from `user` where 1 != 1", + "Query": "select 3 from `user` union select now() from `user`", "Table": "`user`" } ] @@ -1756,9 +1750,8 @@ "Instructions": { "OperatorType": "Distinct", "Collations": [ - "(0:1)" + "0: binary" ], - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Route", @@ -1767,8 +1760,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select dt.c0 as `now()`, weight_string(dt.c0) from (select now() from `user` where 1 != 1 union select 3 from `user` where 1 != 1) as dt(c0) where 1 != 1", - "Query": "select dt.c0 as `now()`, weight_string(dt.c0) from (select now() from `user` union select 3 from `user`) as dt(c0)", + "FieldQuery": "select now() from `user` where 1 != 1 union select 3 from `user` where 1 != 1", + "Query": "select now() from `user` union select 3 from `user`", "Table": "`user`" } ] @@ -1787,9 +1780,8 @@ "Instructions": { "OperatorType": "Distinct", "Collations": [ - "(0:1)" + "0" ], - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Route", @@ -1798,8 +1790,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select dt.c0 as `now()`, weight_string(dt.c0) from (select now() from `user` where 1 != 1 union select id from `user` where 1 != 1) as dt(c0) where 1 != 1", - "Query": "select dt.c0 as `now()`, weight_string(dt.c0) from (select now() from `user` union select id from `user`) as dt(c0)", + "FieldQuery": "select now() from `user` where 1 != 1 union select id from `user` where 1 != 1", + "Query": "select now() from `user` union select id from `user`", "Table": "`user`" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json index a8fd082eb7b..e1618d91efb 100644 --- a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json @@ -19,11 +19,21 @@ "query": "select id from user group by id, (select id from user_extra)", "plan": "VT12001: unsupported: subqueries in GROUP BY" }, + { + "comment": "user defined functions used in having clause that needs evaluation on vtgate", + "query": "select col1, udf_aggr( col2 ) r from user group by col1 having r >= 0.3", + "plan": "VT12001: unsupported: Aggregate UDF 'udf_aggr(col2)' must be pushed down to MySQL" + }, { "comment": "update changes primary vindex column", "query": "update user set id = 1 where id = 1", "plan": "VT12001: unsupported: you cannot UPDATE primary vindex columns; invalid update on vindex: user_index" }, + { + "comment": "subquery with an aggregation in order by that cannot be merged into a single route", + "query": "select col, trim((select user_name from user where col = 'a')) val from user_extra where user_id = 3 group by col order by val", + "plan": "VT12001: unsupported: subquery with aggregation in order by" + }, { "comment": "update change in multicol vindex column", "query": "update multicol_tbl set colc = 5, colb = 4 where cola = 1 and colb = 2", @@ -174,6 +184,11 @@ "query": "select id2 from user uu where id in (select id from user where id = uu.id and user.col in (select col from (select id from user_extra where user_id = 5) uu where uu.user_id = uu.id))", "plan": "VT12001: unsupported: correlated subquery is only supported for EXISTS" }, + { + "comment": "group concat with order by requiring evaluation at vtgate", + "query": "select group_concat(music.name ORDER BY 1 asc SEPARATOR ', ') as `Group Name` from user join user_extra on user.id = user_extra.user_id left join music on user.id = music.id group by user.id;", + "plan": "VT12001: unsupported: cannot evaluate group concat with distinct or order by" + }, { "comment": "outer and inner subquery route reference the same \"uu.id\" name\n# but they refer to different things. The first reference is to the outermost query,\n# and the second reference is to the innermost 'from' subquery.\n# changed to project all the columns from the derived tables.", "query": "select id2 from user uu where id in (select id from user where id = uu.id and user.col in (select col from (select col, id, user_id from user_extra where user_id = 5) uu where uu.user_id = uu.id))", @@ -274,11 +289,6 @@ "query": "select 1 from user u where u.col = 6 or exists (select 1 from user_extra ue where ue.col = u.col and u.col = ue.col2)", "plan": "VT12001: unsupported: unmergable subquery can not be inside complex expression" }, - { - "comment": "this query needs better type information to be able to use the hash join", - "query": "select id from (select id from user limit 10) u join (select user_id from user_extra limit 10) ue on u.id = ue.user_id", - "plan": "VT12001: unsupported: missing type information for [u.id, ue.user_id]" - }, { "comment": "multi-shard union", "query": "select 1 from music union (select id from user union all select name from unsharded)", diff --git a/go/vt/vtgate/planbuilder/testdata/vindex_func_cases.json b/go/vt/vtgate/planbuilder/testdata/vindex_func_cases.json index de5356346b2..3ac35761051 100644 --- a/go/vt/vtgate/planbuilder/testdata/vindex_func_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/vindex_func_cases.json @@ -265,7 +265,7 @@ "Sharded": false }, "FieldQuery": "select unsharded.id from unsharded where 1 != 1", - "Query": "select unsharded.id from unsharded where unsharded.id = :user_index_id", + "Query": "select unsharded.id from unsharded where unsharded.id = :user_index_id /* VARBINARY */", "Table": "unsharded" } ] @@ -313,7 +313,7 @@ "Sharded": false }, "FieldQuery": "select unsharded.id from unsharded where 1 != 1", - "Query": "select unsharded.id from unsharded where unsharded.id = :user_index_id", + "Query": "select unsharded.id from unsharded where unsharded.id = :user_index_id /* VARBINARY */", "Table": "unsharded" } ] @@ -361,7 +361,7 @@ "Sharded": false }, "FieldQuery": "select unsharded.id from unsharded where 1 != 1", - "Query": "select unsharded.id from unsharded where unsharded.id = :user_index_id", + "Query": "select unsharded.id from unsharded where unsharded.id = :user_index_id /* VARBINARY */", "Table": "unsharded" } ] @@ -409,7 +409,7 @@ "Sharded": false }, "FieldQuery": "select unsharded.id from unsharded where 1 != 1", - "Query": "select unsharded.id from unsharded where unsharded.id = :ui_id", + "Query": "select unsharded.id from unsharded where unsharded.id = :ui_id /* VARBINARY */", "Table": "unsharded" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/wireup_cases.json b/go/vt/vtgate/planbuilder/testdata/wireup_cases.json index 3aca1f1dc66..62a3e65a35f 100644 --- a/go/vt/vtgate/planbuilder/testdata/wireup_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/wireup_cases.json @@ -148,7 +148,7 @@ "Sharded": true }, "FieldQuery": "select 1 from `user` as u3 where 1 != 1", - "Query": "select 1 from `user` as u3 where u3.col = :u1_col", + "Query": "select 1 from `user` as u3 where u3.col = :u1_col /* INT16 */", "Table": "`user`" } ] @@ -210,7 +210,7 @@ "Sharded": true }, "FieldQuery": "select 1 from `user` as u3 where 1 != 1", - "Query": "select 1 from `user` as u3 where u3.col = :u2_col", + "Query": "select 1 from `user` as u3 where u3.col = :u2_col /* INT16 */", "Table": "`user`" } ] @@ -265,7 +265,7 @@ "Sharded": true }, "FieldQuery": "select u1.id, u1.col from `user` as u1 where 1 != 1", - "Query": "select u1.id, u1.col from `user` as u1 where u1.col = :u3_col", + "Query": "select u1.id, u1.col from `user` as u1 where u1.col = :u3_col /* INT16 */", "Table": "`user`" }, { @@ -276,7 +276,7 @@ "Sharded": true }, "FieldQuery": "select 1 from `user` as u2 where 1 != 1", - "Query": "select 1 from `user` as u2 where u2.col = :u1_col", + "Query": "select 1 from `user` as u2 where u2.col = :u1_col /* INT16 */", "Table": "`user`" } ] @@ -348,7 +348,7 @@ "Sharded": true }, "FieldQuery": "select u1.id, u1.col from `user` as u1 where 1 != 1", - "Query": "select u1.id, u1.col from `user` as u1 where u1.col = :u4_col", + "Query": "select u1.id, u1.col from `user` as u1 where u1.col = :u4_col /* INT16 */", "Table": "`user`" }, { @@ -359,7 +359,7 @@ "Sharded": true }, "FieldQuery": "select 1 from `user` as u3 where 1 != 1", - "Query": "select 1 from `user` as u3 where u3.id = :u1_col", + "Query": "select 1 from `user` as u3 where u3.id = :u1_col /* INT16 */", "Table": "`user`", "Values": [ ":u1_col" @@ -420,7 +420,7 @@ "Sharded": true }, "FieldQuery": "select 1 from `user` as u2 where 1 != 1", - "Query": "select 1 from `user` as u2 where u2.id = :u1_col", + "Query": "select 1 from `user` as u2 where u2.id = :u1_col /* INT16 */", "Table": "`user`", "Values": [ ":u1_col" @@ -437,7 +437,7 @@ "Sharded": true }, "FieldQuery": "select 1 from `user` as u3 where 1 != 1", - "Query": "select 1 from `user` as u3 where u3.id = :u1_col", + "Query": "select 1 from `user` as u3 where u3.id = :u1_col /* INT16 */", "Table": "`user`", "Values": [ ":u1_col" @@ -591,7 +591,7 @@ "Sharded": true }, "FieldQuery": "select e.id from user_extra as e where 1 != 1", - "Query": "select e.id from user_extra as e where e.id = :u_col limit 10", + "Query": "select e.id from user_extra as e where e.id = :u_col /* INT16 */ limit 10", "Table": "user_extra" } ] @@ -658,7 +658,7 @@ "Sharded": true }, "FieldQuery": "select :u_id + e.id as `u.id + e.id` from user_extra as e where 1 != 1", - "Query": "select :u_id + e.id as `u.id + e.id` from user_extra as e where e.id = :u_col limit 10", + "Query": "select :u_id + e.id as `u.id + e.id` from user_extra as e where e.id = :u_col /* INT16 */ limit 10", "Table": "user_extra" } ] @@ -737,8 +737,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select u.id, :__sq1 as `(select col from ``user``)`, u.col from `user` as u where 1 != 1", - "Query": "select u.id, :__sq1 as `(select col from ``user``)`, u.col from `user` as u", + "FieldQuery": "select u.id, :__sq1 /* INT16 */ as `(select col from ``user``)`, u.col from `user` as u where 1 != 1", + "Query": "select u.id, :__sq1 /* INT16 */ as `(select col from ``user``)`, u.col from `user` as u", "Table": "`user`" } ] @@ -751,7 +751,7 @@ "Sharded": true }, "FieldQuery": "select e.id from user_extra as e where 1 != 1", - "Query": "select e.id from user_extra as e where e.id = :u_col", + "Query": "select e.id from user_extra as e where e.id = :u_col /* INT16 */", "Table": "user_extra" } ] diff --git a/go/vt/vtgate/plugin_mysql_server.go b/go/vt/vtgate/plugin_mysql_server.go index 175f4b2cc8f..4004ae24566 100644 --- a/go/vt/vtgate/plugin_mysql_server.go +++ b/go/vt/vtgate/plugin_mysql_server.go @@ -75,6 +75,7 @@ var ( mysqlDefaultWorkloadName = "OLTP" mysqlDefaultWorkload int32 + mysqlDrainOnTerm bool mysqlServerFlushDelay = 100 * time.Millisecond ) @@ -102,6 +103,7 @@ func registerPluginFlags(fs *pflag.FlagSet) { fs.DurationVar(&mysqlKeepAlivePeriod, "mysql-server-keepalive-period", mysqlKeepAlivePeriod, "TCP period between keep-alives") fs.DurationVar(&mysqlServerFlushDelay, "mysql_server_flush_delay", mysqlServerFlushDelay, "Delay after which buffered response will be flushed to the client.") fs.StringVar(&mysqlDefaultWorkloadName, "mysql_default_workload", mysqlDefaultWorkloadName, "Default session workload (OLTP, OLAP, DBA)") + fs.BoolVar(&mysqlDrainOnTerm, "mysql-server-drain-onterm", mysqlDrainOnTerm, "If set, the server waits for --onterm_timeout for already connected clients to complete their in flight work") } // vtgateHandler implements the Listener interface. @@ -621,18 +623,34 @@ func newMysqlUnixSocket(address string, authServer mysql.AuthServer, handler mys } func (srv *mysqlServer) shutdownMysqlProtocolAndDrain() { - if srv.tcpListener != nil { - srv.tcpListener.Shutdown() - srv.tcpListener = nil + if srv.sigChan != nil { + signal.Stop(srv.sigChan) } - if srv.unixListener != nil { - srv.unixListener.Shutdown() + setListenerToNil := func() { + srv.tcpListener = nil srv.unixListener = nil } - if srv.sigChan != nil { - signal.Stop(srv.sigChan) + + if mysqlDrainOnTerm { + stopListener(srv.unixListener, false) + stopListener(srv.tcpListener, false) + setListenerToNil() + // We wait for connected clients to drain by themselves or to run into the onterm timeout + log.Infof("Starting drain loop, waiting for all clients to disconnect") + reported := time.Now() + for srv.vtgateHandle.numConnections() > 0 { + if time.Since(reported) > 2*time.Second { + log.Infof("Still waiting for client connections to drain (%d connected)...", srv.vtgateHandle.numConnections()) + reported = time.Now() + } + time.Sleep(1000 * time.Millisecond) + } + return } + stopListener(srv.unixListener, true) + stopListener(srv.tcpListener, true) + setListenerToNil() if busy := srv.vtgateHandle.busyConnections.Load(); busy > 0 { log.Infof("Waiting for all client connections to be idle (%d active)...", busy) start := time.Now() @@ -649,6 +667,18 @@ func (srv *mysqlServer) shutdownMysqlProtocolAndDrain() { } } +// stopListener Close or Shutdown a mysql listener depending on the shutdown argument. +func stopListener(listener *mysql.Listener, shutdown bool) { + if listener == nil { + return + } + if shutdown { + listener.Shutdown() + } else { + listener.Close() + } +} + func (srv *mysqlServer) rollbackAtShutdown() { defer log.Flush() if srv.vtgateHandle == nil { diff --git a/go/vt/vtgate/production.go b/go/vt/vtgate/production.go new file mode 100644 index 00000000000..83e0cbdddf5 --- /dev/null +++ b/go/vt/vtgate/production.go @@ -0,0 +1,28 @@ +//go:build !debug2PC + +/* +Copyright 2024 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 vtgate + +// This file defines debug constants that are always false. +// This file is used for building production code. +// We use go build directives to include a file that defines the constant to true +// when certain tags are provided while building binaries. +// This allows to have debugging code written in normal code flow without affecting +// production performance. + +const DebugTwoPc = false diff --git a/go/vt/vtgate/sandbox_test.go b/go/vt/vtgate/sandbox_test.go index dc3c1f103af..70b96a63126 100644 --- a/go/vt/vtgate/sandbox_test.go +++ b/go/vt/vtgate/sandbox_test.go @@ -81,7 +81,7 @@ func getSandboxSrvVSchema() *vschemapb.SrvVSchema { defer sandboxMu.Unlock() for keyspace, sandbox := range ksToSandbox { var vs vschemapb.Keyspace - if err := json2.Unmarshal([]byte(sandbox.VSchema), &vs); err != nil { + if err := json2.UnmarshalPB([]byte(sandbox.VSchema), &vs); err != nil { panic(err) } result.Keyspaces[keyspace] = &vs diff --git a/go/vt/vtgate/semantics/binder.go b/go/vt/vtgate/semantics/binder.go index 90a36b1f0d7..78148f4bb1f 100644 --- a/go/vt/vtgate/semantics/binder.go +++ b/go/vt/vtgate/semantics/binder.go @@ -169,7 +169,7 @@ func (b *binder) findDependentTableSet(current *scope, target sqlparser.TableNam continue } ts := b.org.tableSetFor(table.GetAliasedTableExpr()) - c := createCertain(ts, ts, evalengine.Type{}) + c := createCertain(ts, ts, evalengine.NewUnknownType()) deps = deps.merge(c, false) } finalDep, err := deps.get(nil) diff --git a/go/vt/vtgate/semantics/early_rewriter.go b/go/vt/vtgate/semantics/early_rewriter.go index 568e1900d44..611c91e512c 100644 --- a/go/vt/vtgate/semantics/early_rewriter.go +++ b/go/vt/vtgate/semantics/early_rewriter.go @@ -62,6 +62,20 @@ func (r *earlyRewriter) down(cursor *sqlparser.Cursor) error { return r.handleAliasedTable(node) case *sqlparser.Delete: return handleDelete(node) + case *sqlparser.DerivedTable: + return r.handleDerivedTable(node) + } + return nil +} + +func (r *earlyRewriter) handleDerivedTable(dt *sqlparser.DerivedTable) error { + sel, ok := dt.Select.(*sqlparser.Select) + if !ok { + return nil + } + if len(sel.OrderBy) > 0 && sel.Limit == nil { + // inside derived tables, we can safely remove ORDER BY clauses if there is no LIMIT clause + sel.OrderBy = nil } return nil } diff --git a/go/vt/vtgate/semantics/early_rewriter_test.go b/go/vt/vtgate/semantics/early_rewriter_test.go index 81d3ed8c450..16b3756189f 100644 --- a/go/vt/vtgate/semantics/early_rewriter_test.go +++ b/go/vt/vtgate/semantics/early_rewriter_test.go @@ -854,6 +854,54 @@ func TestRewriteNot(t *testing.T) { } } +func TestOrderByDerivedTable(t *testing.T) { + ks := &vindexes.Keyspace{ + Name: "main", + Sharded: true, + } + schemaInfo := &FakeSI{ + Tables: map[string]*vindexes.Table{ + "t1": { + Keyspace: ks, + Name: sqlparser.NewIdentifierCS("t1"), + Columns: []vindexes.Column{{ + Name: sqlparser.NewIdentifierCI("a"), + Type: sqltypes.VarChar, + }, { + Name: sqlparser.NewIdentifierCI("b"), + Type: sqltypes.VarChar, + }, { + Name: sqlparser.NewIdentifierCI("c"), + Type: sqltypes.VarChar, + }}, + ColumnListAuthoritative: true, + }, + }, + } + cDB := "db" + tcases := []struct { + sql string + expected string + }{{ + sql: "select a, b, c from (select a, b, c from t1 order by b, a, c) as dt", + expected: "select a, b, c from (select a, b, c from t1) as dt", + }, { + sql: "select a, b, c from (select a, b, c from t1 order by b, a, c limit 5) as dt", + expected: "select a, b, c from (select a, b, c from t1 order by t1.b asc, t1.a asc, t1.c asc limit 5) as dt", + }} + for _, tcase := range tcases { + t.Run(tcase.sql, func(t *testing.T) { + ast, err := sqlparser.NewTestParser().Parse(tcase.sql) + require.NoError(t, err) + selectStatement, isSelectStatement := ast.(*sqlparser.Select) + require.True(t, isSelectStatement, "analyzer expects a select statement") + _, err = AnalyzeStrict(selectStatement, cDB, schemaInfo) + require.NoError(t, err) + assert.Equal(t, tcase.expected, sqlparser.String(selectStatement)) + }) + } +} + // TestConstantFolding tests that the rewriter is able to do various constant foldings properly. func TestConstantFolding(t *testing.T) { ks := &vindexes.Keyspace{ diff --git a/go/vt/vtgate/semantics/semantic_state.go b/go/vt/vtgate/semantics/semantic_state.go index 1dcaaf87061..ac2fd9c1604 100644 --- a/go/vt/vtgate/semantics/semantic_state.go +++ b/go/vt/vtgate/semantics/semantic_state.go @@ -671,26 +671,7 @@ func (st *SemTable) TypeForExpr(e sqlparser.Expr) (evalengine.Type, bool) { return evalengine.NewTypeEx(sqltypes.VarBinary, collations.CollationBinaryID, wt.Nullable(), 0, 0, nil), true } - return evalengine.Type{}, false -} - -// NeedsWeightString returns true if the given expression needs weight_string to do safe comparisons -func (st *SemTable) NeedsWeightString(e sqlparser.Expr) bool { - switch e := e.(type) { - case *sqlparser.WeightStringFuncExpr, *sqlparser.Literal: - return false - default: - typ, found := st.ExprTypes[e] - if !found { - return true - } - - if !sqltypes.IsText(typ.Type()) { - return false - } - - return !st.collEnv.IsSupported(typ.Collation()) - } + return evalengine.NewUnknownType(), false } func (st *SemTable) DefaultCollation() collations.ID { diff --git a/go/vt/vtgate/semantics/table_collector.go b/go/vt/vtgate/semantics/table_collector.go index ae107cc070c..948edb37d47 100644 --- a/go/vt/vtgate/semantics/table_collector.go +++ b/go/vt/vtgate/semantics/table_collector.go @@ -19,8 +19,6 @@ package semantics import ( "fmt" - "vitess.io/vitess/go/mysql/collations" - "vitess.io/vitess/go/sqltypes" vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" querypb "vitess.io/vitess/go/vt/proto/query" @@ -234,7 +232,7 @@ for2: continue for2 } } - types = append(types, evalengine.NewType(sqltypes.Unknown, collations.Unknown)) + types = append(types, evalengine.NewUnknownType()) } return colNames, types } diff --git a/go/vt/vtgate/tx_conn.go b/go/vt/vtgate/tx_conn.go index 2eccdc54992..56d45799175 100644 --- a/go/vt/vtgate/tx_conn.go +++ b/go/vt/vtgate/tx_conn.go @@ -22,18 +22,20 @@ import ( "strings" "sync" + "github.com/pkg/errors" + "vitess.io/vitess/go/mysql/sqlerror" + "vitess.io/vitess/go/vt/callerid" "vitess.io/vitess/go/vt/concurrency" "vitess.io/vitess/go/vt/dtids" "vitess.io/vitess/go/vt/log" - "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/vterrors" - "vitess.io/vitess/go/vt/vttablet/queryservice" - querypb "vitess.io/vitess/go/vt/proto/query" topodatapb "vitess.io/vitess/go/vt/proto/topodata" vtgatepb "vitess.io/vitess/go/vt/proto/vtgate" vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" + "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/vt/vttablet/queryservice" ) // nonAtomicCommitWarnMaxShards limits the number of shard names reported in @@ -201,25 +203,58 @@ func (txc *TxConn) commit2PC(ctx context.Context, session *SafeSession) error { return err } + if DebugTwoPc { + // Test code to simulate a failure after RM prepare + if failNow, err := checkTestFailure(callerid.EffectiveCallerIDFromContext(ctx), "TRCreated_FailNow", nil); failNow { + return errors.Wrapf(err, "%v", dtid) + } + } + err = txc.runSessions(ctx, session.ShardSessions[1:], session.logging, func(ctx context.Context, s *vtgatepb.Session_ShardSession, logging *executeLogger) error { + if DebugTwoPc { + // Test code to simulate a failure during RM prepare + if failNow, err := checkTestFailure(callerid.EffectiveCallerIDFromContext(ctx), "RMPrepare_-40_FailNow", s.Target); failNow { + return err + } + } return txc.tabletGateway.Prepare(ctx, s.Target, s.TransactionId, dtid) }) if err != nil { // TODO(sougou): Perform a more fine-grained cleanup // including unprepared transactions. - if resumeErr := txc.Resolve(ctx, dtid); resumeErr != nil { + if resumeErr := txc.rollbackTx(ctx, dtid, mmShard, session.ShardSessions[1:], session.logging); resumeErr != nil { log.Warningf("Rollback failed after Prepare failure: %v", resumeErr) } // Return the original error even if the previous operation fails. return err } + if DebugTwoPc { + // Test code to simulate a failure after RM prepare + if failNow, err := checkTestFailure(callerid.EffectiveCallerIDFromContext(ctx), "RMPrepared_FailNow", nil); failNow { + return err + } + } + err = txc.tabletGateway.StartCommit(ctx, mmShard.Target, mmShard.TransactionId, dtid) if err != nil { return err } + if DebugTwoPc { + // Test code to simulate a failure after MM commit + if failNow, err := checkTestFailure(callerid.EffectiveCallerIDFromContext(ctx), "MMCommitted_FailNow", nil); failNow { + return err + } + } + err = txc.runSessions(ctx, session.ShardSessions[1:], session.logging, func(ctx context.Context, s *vtgatepb.Session_ShardSession, logging *executeLogger) error { + if DebugTwoPc { + // Test code to simulate a failure during RM prepare + if failNow, err := checkTestFailure(callerid.EffectiveCallerIDFromContext(ctx), "RMCommit_-40_FailNow", s.Target); failNow { + return err + } + } return txc.tabletGateway.CommitPrepared(ctx, s.Target, dtid) }) if err != nil { @@ -229,6 +264,42 @@ func (txc *TxConn) commit2PC(ctx context.Context, session *SafeSession) error { return txc.tabletGateway.ConcludeTransaction(ctx, mmShard.Target, dtid) } +func checkTestFailure(callerID *vtrpcpb.CallerID, expectCaller string, target *querypb.Target) (bool, error) { + if callerID == nil || callerID.GetPrincipal() != expectCaller { + return false, nil + } + switch callerID.Principal { + case "TRCreated_FailNow": + log.Errorf("Fail After TR created") + // no commit decision is made. Transaction should be a rolled back. + return true, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "Fail After TR created") + case "RMPrepare_-40_FailNow": + if target.Shard != "-40" { + return false, nil + } + log.Errorf("Fail During RM prepare") + // no commit decision is made. Transaction should be a rolled back. + return true, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "Fail During RM prepare") + case "RMPrepared_FailNow": + log.Errorf("Fail After RM prepared") + // no commit decision is made. Transaction should be a rolled back. + return true, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "Fail After RM prepared") + case "MMCommitted_FailNow": + log.Errorf("Fail After MM commit") + // commit decision is made. Transaction should be committed. + return true, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "Fail After MM commit") + case "RMCommit_-40_FailNow": + if target.Shard != "-40" { + return false, nil + } + log.Errorf("Fail During RM commit") + // commit decision is made. Transaction should be a committed. + return true, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "Fail During RM commit") + default: + return false, nil + } +} + // Rollback rolls back the current transaction. There are no retries on this operation. func (txc *TxConn) Rollback(ctx context.Context, session *SafeSession) error { if !session.InTransaction() { @@ -343,39 +414,49 @@ func (txc *TxConn) ReleaseAll(ctx context.Context, session *SafeSession) error { }) } -// Resolve resolves the specified 2PC transaction. -func (txc *TxConn) Resolve(ctx context.Context, dtid string) error { - mmShard, err := dtids.ShardSession(dtid) +// ResolveTransactions fetches all unresolved transactions and resolves them. +func (txc *TxConn) ResolveTransactions(ctx context.Context, target *querypb.Target) error { + transactions, err := txc.tabletGateway.UnresolvedTransactions(ctx, target) if err != nil { return err } - transaction, err := txc.tabletGateway.ReadTransaction(ctx, mmShard.Target, dtid) - if err != nil { - return err + failedResolution := 0 + for _, txRecord := range transactions { + log.Infof("Resolving transaction ID: %s", txRecord.Dtid) + err = txc.resolveTx(ctx, target, txRecord) + if err != nil { + failedResolution++ + log.Errorf("Failed to resolve transaction ID: %s with error: %v", txRecord.Dtid, err) + } } - if transaction == nil || transaction.Dtid == "" { - // It was already resolved. + if failedResolution == 0 { return nil } + return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "failed to resolve %d out of %d transactions", failedResolution, len(transactions)) +} + +// resolveTx resolves the specified distributed transaction. +func (txc *TxConn) resolveTx(ctx context.Context, target *querypb.Target, transaction *querypb.TransactionMetadata) error { + mmShard, err := dtids.ShardSession(transaction.Dtid) + if err != nil { + return err + } + switch transaction.State { case querypb.TransactionState_PREPARE: // If state is PREPARE, make a decision to rollback and // fallthrough to the rollback workflow. - qs, err := txc.queryService(ctx, mmShard.TabletAlias) - if err != nil { - return err - } - if err := qs.SetRollback(ctx, mmShard.Target, transaction.Dtid, mmShard.TransactionId); err != nil { + if err := txc.tabletGateway.SetRollback(ctx, target, transaction.Dtid, mmShard.TransactionId); err != nil { return err } fallthrough case querypb.TransactionState_ROLLBACK: - if err := txc.resumeRollback(ctx, mmShard.Target, transaction); err != nil { + if err := txc.resumeRollback(ctx, target, transaction); err != nil { return err } case querypb.TransactionState_COMMIT: - if err := txc.resumeCommit(ctx, mmShard.Target, transaction); err != nil { + if err := txc.resumeCommit(ctx, target, transaction); err != nil { return err } default: @@ -385,6 +466,25 @@ func (txc *TxConn) Resolve(ctx context.Context, dtid string) error { return nil } +// rollbackTx rollbacks the specified distributed transaction. +func (txc *TxConn) rollbackTx(ctx context.Context, dtid string, mmShard *vtgatepb.Session_ShardSession, participants []*vtgatepb.Session_ShardSession, logging *executeLogger) error { + qs, err := txc.queryService(ctx, mmShard.TabletAlias) + if err != nil { + return err + } + if err := qs.SetRollback(ctx, mmShard.Target, dtid, mmShard.TransactionId); err != nil { + return err + } + err = txc.runSessions(ctx, participants, logging, func(ctx context.Context, session *vtgatepb.Session_ShardSession, logger *executeLogger) error { + return txc.tabletGateway.RollbackPrepared(ctx, session.Target, dtid, session.TransactionId) + }) + if err != nil { + return err + } + return txc.tabletGateway.ConcludeTransaction(ctx, mmShard.Target, dtid) + +} + func (txc *TxConn) resumeRollback(ctx context.Context, target *querypb.Target, transaction *querypb.TransactionMetadata) error { err := txc.runTargets(transaction.Participants, func(t *querypb.Target) error { return txc.tabletGateway.RollbackPrepared(ctx, t, transaction.Dtid, 0) @@ -447,3 +547,11 @@ func (txc *TxConn) runTargets(targets []*querypb.Target, action func(*querypb.Ta wg.Wait() return allErrors.AggrError(vterrors.Aggregate) } + +func (txc *TxConn) ReadTransaction(ctx context.Context, transactionID string) (*querypb.TransactionMetadata, error) { + mmShard, err := dtids.ShardSession(transactionID) + if err != nil { + return nil, err + } + return txc.tabletGateway.ReadTransaction(ctx, mmShard.Target, transactionID) +} diff --git a/go/vt/vtgate/tx_conn_test.go b/go/vt/vtgate/tx_conn_test.go index 4d77ea16c92..74329153936 100644 --- a/go/vt/vtgate/tx_conn_test.go +++ b/go/vt/vtgate/tx_conn_test.go @@ -20,25 +20,24 @@ import ( "context" "fmt" "strconv" + "strings" "testing" "github.com/stretchr/testify/assert" - - "vitess.io/vitess/go/test/utils" - "github.com/stretchr/testify/require" + "vitess.io/vitess/go/event/syslogger" "vitess.io/vitess/go/mysql/sqlerror" + "vitess.io/vitess/go/test/utils" "vitess.io/vitess/go/vt/discovery" "vitess.io/vitess/go/vt/key" - "vitess.io/vitess/go/vt/srvtopo" - "vitess.io/vitess/go/vt/vterrors" - "vitess.io/vitess/go/vt/vttablet/sandboxconn" - querypb "vitess.io/vitess/go/vt/proto/query" topodatapb "vitess.io/vitess/go/vt/proto/topodata" vtgatepb "vitess.io/vitess/go/vt/proto/vtgate" vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" + "vitess.io/vitess/go/vt/srvtopo" + "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/vt/vttablet/sandboxconn" ) var queries = []*querypb.BoundQuery{{Sql: "query1"}} @@ -1024,9 +1023,15 @@ func TestTxConnCommit2PCPrepareFail(t *testing.T) { assert.Contains(t, err.Error(), want, "Commit") assert.EqualValues(t, 1, sbc0.CreateTransactionCount.Load(), "sbc0.CreateTransactionCount") assert.EqualValues(t, 1, sbc1.PrepareCount.Load(), "sbc1.PrepareCount") + // Prepared failed on RM, so no commit on MM or RMs. assert.EqualValues(t, 0, sbc0.StartCommitCount.Load(), "sbc0.StartCommitCount") assert.EqualValues(t, 0, sbc1.CommitPreparedCount.Load(), "sbc1.CommitPreparedCount") - assert.EqualValues(t, 0, sbc0.ConcludeTransactionCount.Load(), "sbc0.ConcludeTransactionCount") + // rollback original transaction on MM + assert.EqualValues(t, 1, sbc0.SetRollbackCount.Load(), "sbc0.SetRollbackCount") + // rollback prepare transaction on RM + assert.EqualValues(t, 1, sbc1.RollbackPreparedCount.Load(), "sbc1.RollbackPreparedCount") + // conclude the transaction. + assert.EqualValues(t, 1, sbc0.ConcludeTransactionCount.Load(), "sbc0.ConcludeTransactionCount") } func TestTxConnCommit2PCStartCommitFail(t *testing.T) { @@ -1179,14 +1184,21 @@ func TestTxConnReservedRollbackFailure(t *testing.T) { assert.EqualValues(t, 1, sbc1.ReleaseCount.Load(), "sbc1.ReleaseCount") } +func getMMTarget() *querypb.Target { + return &querypb.Target{ + Keyspace: "TestTxConn", + Shard: "0", + TabletType: topodatapb.TabletType_PRIMARY, + } +} + func TestTxConnResolveOnPrepare(t *testing.T) { ctx := utils.LeakCheckContext(t) sc, sbc0, sbc1, _, _, _ := newTestTxConnEnv(t, ctx, "TestTxConn") - dtid := "TestTxConn:0:1234" - sbc0.ReadTransactionResults = []*querypb.TransactionMetadata{{ - Dtid: dtid, + sbc0.UnresolvedTransactionsResult = []*querypb.TransactionMetadata{{ + Dtid: "TestTxConn:0:1234", State: querypb.TransactionState_PREPARE, Participants: []*querypb.Target{{ Keyspace: "TestTxConn", @@ -1194,8 +1206,9 @@ func TestTxConnResolveOnPrepare(t *testing.T) { TabletType: topodatapb.TabletType_PRIMARY, }}, }} - err := sc.txConn.Resolve(ctx, dtid) + err := sc.txConn.ResolveTransactions(ctx, getMMTarget()) require.NoError(t, err) + assert.EqualValues(t, 1, sbc0.UnresolvedTransactionsCount.Load(), "sbc0.UnresolvedTransactionsCount") assert.EqualValues(t, 1, sbc0.SetRollbackCount.Load(), "sbc0.SetRollbackCount") assert.EqualValues(t, 1, sbc1.RollbackPreparedCount.Load(), "sbc1.RollbackPreparedCount") assert.EqualValues(t, 0, sbc1.CommitPreparedCount.Load(), "sbc1.CommitPreparedCount") @@ -1207,9 +1220,8 @@ func TestTxConnResolveOnRollback(t *testing.T) { sc, sbc0, sbc1, _, _, _ := newTestTxConnEnv(t, ctx, "TestTxConn") - dtid := "TestTxConn:0:1234" - sbc0.ReadTransactionResults = []*querypb.TransactionMetadata{{ - Dtid: dtid, + sbc0.UnresolvedTransactionsResult = []*querypb.TransactionMetadata{{ + Dtid: "TestTxConn:0:1234", State: querypb.TransactionState_ROLLBACK, Participants: []*querypb.Target{{ Keyspace: "TestTxConn", @@ -1217,8 +1229,9 @@ func TestTxConnResolveOnRollback(t *testing.T) { TabletType: topodatapb.TabletType_PRIMARY, }}, }} - require.NoError(t, - sc.txConn.Resolve(ctx, dtid)) + err := sc.txConn.ResolveTransactions(ctx, getMMTarget()) + require.NoError(t, err) + assert.EqualValues(t, 1, sbc0.UnresolvedTransactionsCount.Load(), "sbc0.UnresolvedTransactionsCount") assert.EqualValues(t, 0, sbc0.SetRollbackCount.Load(), "sbc0.SetRollbackCount") assert.EqualValues(t, 1, sbc1.RollbackPreparedCount.Load(), "sbc1.RollbackPreparedCount") assert.EqualValues(t, 0, sbc1.CommitPreparedCount.Load(), "sbc1.CommitPreparedCount") @@ -1230,9 +1243,8 @@ func TestTxConnResolveOnCommit(t *testing.T) { sc, sbc0, sbc1, _, _, _ := newTestTxConnEnv(t, ctx, "TestTxConn") - dtid := "TestTxConn:0:1234" - sbc0.ReadTransactionResults = []*querypb.TransactionMetadata{{ - Dtid: dtid, + sbc0.UnresolvedTransactionsResult = []*querypb.TransactionMetadata{{ + Dtid: "TestTxConn:0:1234", State: querypb.TransactionState_COMMIT, Participants: []*querypb.Target{{ Keyspace: "TestTxConn", @@ -1240,35 +1252,45 @@ func TestTxConnResolveOnCommit(t *testing.T) { TabletType: topodatapb.TabletType_PRIMARY, }}, }} - require.NoError(t, - sc.txConn.Resolve(ctx, dtid)) + err := sc.txConn.ResolveTransactions(ctx, getMMTarget()) + require.NoError(t, err) + assert.EqualValues(t, 1, sbc0.UnresolvedTransactionsCount.Load(), "sbc0.UnresolvedTransactionsCount") assert.EqualValues(t, 0, sbc0.SetRollbackCount.Load(), "sbc0.SetRollbackCount") assert.EqualValues(t, 0, sbc1.RollbackPreparedCount.Load(), "sbc1.RollbackPreparedCount") assert.EqualValues(t, 1, sbc1.CommitPreparedCount.Load(), "sbc1.CommitPreparedCount") assert.EqualValues(t, 1, sbc0.ConcludeTransactionCount.Load(), "sbc0.ConcludeTransactionCount") } -func TestTxConnResolveInvalidDTID(t *testing.T) { +func TestTxConnUnresolvedTransactionsFail(t *testing.T) { ctx := utils.LeakCheckContext(t) - sc, _, _, _, _, _ := newTestTxConnEnv(t, ctx, "TestTxConn") + sc, sbc0, _, _, _, _ := newTestTxConnEnv(t, ctx, "TestTxConn") - err := sc.txConn.Resolve(ctx, "abcd") - want := "invalid parts in dtid: abcd" - require.EqualError(t, err, want, "Resolve") + sbc0.MustFailCodes[vtrpcpb.Code_INVALID_ARGUMENT] = 1 + err := sc.txConn.ResolveTransactions(ctx, getMMTarget()) + require.ErrorContains(t, err, "target: TestTxConn.0.primary: INVALID_ARGUMENT error") } -func TestTxConnResolveReadTransactionFail(t *testing.T) { +func TestTxConnResolveInvalidDTID(t *testing.T) { ctx := utils.LeakCheckContext(t) sc, sbc0, _, _, _, _ := newTestTxConnEnv(t, ctx, "TestTxConn") - dtid := "TestTxConn:0:1234" - sbc0.MustFailCodes[vtrpcpb.Code_INVALID_ARGUMENT] = 1 - err := sc.txConn.Resolve(ctx, dtid) - want := "INVALID_ARGUMENT error" - require.Error(t, err) - assert.Contains(t, err.Error(), want, "Resolve") + tl := syslogger.NewTestLogger() + defer tl.Close() + + sbc0.UnresolvedTransactionsResult = []*querypb.TransactionMetadata{{ + Dtid: "abcd", + State: querypb.TransactionState_COMMIT, + Participants: []*querypb.Target{{ + Keyspace: "TestTxConn", + Shard: "1", + TabletType: topodatapb.TabletType_PRIMARY, + }}, + }} + err := sc.txConn.ResolveTransactions(ctx, getMMTarget()) + require.ErrorContains(t, err, "failed to resolve 1 out of 1 transactions") + require.Contains(t, strings.Join(tl.GetAllLogs(), "|"), "invalid parts in dtid: abcd") } func TestTxConnResolveInternalError(t *testing.T) { @@ -1276,9 +1298,11 @@ func TestTxConnResolveInternalError(t *testing.T) { sc, sbc0, _, _, _, _ := newTestTxConnEnv(t, ctx, "TestTxConn") - dtid := "TestTxConn:0:1234" - sbc0.ReadTransactionResults = []*querypb.TransactionMetadata{{ - Dtid: dtid, + tl := syslogger.NewTestLogger() + defer tl.Close() + + sbc0.UnresolvedTransactionsResult = []*querypb.TransactionMetadata{{ + Dtid: "TestTxConn:0:1234", State: querypb.TransactionState_UNKNOWN, Participants: []*querypb.Target{{ Keyspace: "TestTxConn", @@ -1286,10 +1310,9 @@ func TestTxConnResolveInternalError(t *testing.T) { TabletType: topodatapb.TabletType_PRIMARY, }}, }} - err := sc.txConn.Resolve(ctx, dtid) - want := "invalid state: UNKNOWN" - require.Error(t, err) - assert.Contains(t, err.Error(), want, "Resolve") + err := sc.txConn.ResolveTransactions(ctx, getMMTarget()) + require.ErrorContains(t, err, "failed to resolve 1 out of 1 transactions") + require.Contains(t, strings.Join(tl.GetAllLogs(), "|"), "invalid state: UNKNOWN") } func TestTxConnResolveSetRollbackFail(t *testing.T) { @@ -1297,9 +1320,11 @@ func TestTxConnResolveSetRollbackFail(t *testing.T) { sc, sbc0, sbc1, _, _, _ := newTestTxConnEnv(t, ctx, "TestTxConn") - dtid := "TestTxConn:0:1234" - sbc0.ReadTransactionResults = []*querypb.TransactionMetadata{{ - Dtid: dtid, + tl := syslogger.NewTestLogger() + defer tl.Close() + + sbc0.UnresolvedTransactionsResult = []*querypb.TransactionMetadata{{ + Dtid: "TestTxConn:0:1234", State: querypb.TransactionState_PREPARE, Participants: []*querypb.Target{{ Keyspace: "TestTxConn", @@ -1308,10 +1333,11 @@ func TestTxConnResolveSetRollbackFail(t *testing.T) { }}, }} sbc0.MustFailSetRollback = 1 - err := sc.txConn.Resolve(ctx, dtid) - want := "error: err" - require.Error(t, err) - assert.Contains(t, err.Error(), want, "Resolve") + err := sc.txConn.ResolveTransactions(ctx, getMMTarget()) + require.ErrorContains(t, err, "failed to resolve 1 out of 1 transactions") + require.Contains(t, strings.Join(tl.GetAllLogs(), "|"), "error: err") + assert.EqualValues(t, 1, sbc0.UnresolvedTransactionsCount.Load(), "sbc0.UnresolvedTransactionsCount") + assert.EqualValues(t, 1, sbc0.UnresolvedTransactionsCount.Load(), "sbc0.UnresolvedTransactionsCount") assert.EqualValues(t, 1, sbc0.SetRollbackCount.Load(), "sbc0.SetRollbackCount") assert.EqualValues(t, 0, sbc1.RollbackPreparedCount.Load(), "sbc1.RollbackPreparedCount") assert.EqualValues(t, 0, sbc1.CommitPreparedCount.Load(), "sbc1.CommitPreparedCount") @@ -1323,9 +1349,11 @@ func TestTxConnResolveRollbackPreparedFail(t *testing.T) { sc, sbc0, sbc1, _, _, _ := newTestTxConnEnv(t, ctx, "TestTxConn") - dtid := "TestTxConn:0:1234" - sbc0.ReadTransactionResults = []*querypb.TransactionMetadata{{ - Dtid: dtid, + tl := syslogger.NewTestLogger() + defer tl.Close() + + sbc0.UnresolvedTransactionsResult = []*querypb.TransactionMetadata{{ + Dtid: "TestTxConn:0:1234", State: querypb.TransactionState_ROLLBACK, Participants: []*querypb.Target{{ Keyspace: "TestTxConn", @@ -1334,10 +1362,10 @@ func TestTxConnResolveRollbackPreparedFail(t *testing.T) { }}, }} sbc1.MustFailRollbackPrepared = 1 - err := sc.txConn.Resolve(ctx, dtid) - want := "error: err" - require.Error(t, err) - assert.Contains(t, err.Error(), want, "Resolve") + err := sc.txConn.ResolveTransactions(ctx, getMMTarget()) + require.ErrorContains(t, err, "failed to resolve 1 out of 1 transactions") + require.Contains(t, strings.Join(tl.GetAllLogs(), "|"), "error: err") + assert.EqualValues(t, 1, sbc0.UnresolvedTransactionsCount.Load(), "sbc0.UnresolvedTransactionsCount") assert.EqualValues(t, 0, sbc0.SetRollbackCount.Load(), "sbc0.SetRollbackCount") assert.EqualValues(t, 1, sbc1.RollbackPreparedCount.Load(), "sbc1.RollbackPreparedCount") assert.EqualValues(t, 0, sbc1.CommitPreparedCount.Load(), "sbc1.CommitPreparedCount") @@ -1349,9 +1377,11 @@ func TestTxConnResolveCommitPreparedFail(t *testing.T) { sc, sbc0, sbc1, _, _, _ := newTestTxConnEnv(t, ctx, "TestTxConn") - dtid := "TestTxConn:0:1234" - sbc0.ReadTransactionResults = []*querypb.TransactionMetadata{{ - Dtid: dtid, + tl := syslogger.NewTestLogger() + defer tl.Close() + + sbc0.UnresolvedTransactionsResult = []*querypb.TransactionMetadata{{ + Dtid: "TestTxConn:0:1234", State: querypb.TransactionState_COMMIT, Participants: []*querypb.Target{{ Keyspace: "TestTxConn", @@ -1360,11 +1390,10 @@ func TestTxConnResolveCommitPreparedFail(t *testing.T) { }}, }} sbc1.MustFailCommitPrepared = 1 - err := sc.txConn.Resolve(ctx, dtid) - want := "error: err" - require.Error(t, err) - assert.Contains(t, err.Error(), want, "Resolve") - assert.EqualValues(t, 0, sbc0.SetRollbackCount.Load(), "sbc0.SetRollbackCount") + err := sc.txConn.ResolveTransactions(ctx, getMMTarget()) + require.ErrorContains(t, err, "failed to resolve 1 out of 1 transactions") + require.Contains(t, strings.Join(tl.GetAllLogs(), "|"), "error: err") + assert.EqualValues(t, 1, sbc0.UnresolvedTransactionsCount.Load(), "sbc0.UnresolvedTransactionsCount") assert.EqualValues(t, 0, sbc1.RollbackPreparedCount.Load(), "sbc1.RollbackPreparedCount") assert.EqualValues(t, 1, sbc1.CommitPreparedCount.Load(), "sbc1.CommitPreparedCount") assert.EqualValues(t, 0, sbc0.ConcludeTransactionCount.Load(), "sbc0.ConcludeTransactionCount") @@ -1375,9 +1404,11 @@ func TestTxConnResolveConcludeTransactionFail(t *testing.T) { sc, sbc0, sbc1, _, _, _ := newTestTxConnEnv(t, ctx, "TestTxConn") - dtid := "TestTxConn:0:1234" - sbc0.ReadTransactionResults = []*querypb.TransactionMetadata{{ - Dtid: dtid, + tl := syslogger.NewTestLogger() + defer tl.Close() + + sbc0.UnresolvedTransactionsResult = []*querypb.TransactionMetadata{{ + Dtid: "TestTxConn:0:1234", State: querypb.TransactionState_COMMIT, Participants: []*querypb.Target{{ Keyspace: "TestTxConn", @@ -1386,10 +1417,10 @@ func TestTxConnResolveConcludeTransactionFail(t *testing.T) { }}, }} sbc0.MustFailConcludeTransaction = 1 - err := sc.txConn.Resolve(ctx, dtid) - want := "error: err" - require.Error(t, err) - assert.Contains(t, err.Error(), want, "Resolve") + err := sc.txConn.ResolveTransactions(ctx, getMMTarget()) + require.ErrorContains(t, err, "failed to resolve 1 out of 1 transactions") + require.Contains(t, strings.Join(tl.GetAllLogs(), "|"), "error: err") + assert.EqualValues(t, 1, sbc0.UnresolvedTransactionsCount.Load(), "sbc0.UnresolvedTransactionsCount") assert.EqualValues(t, 0, sbc0.SetRollbackCount.Load(), "sbc0.SetRollbackCount") assert.EqualValues(t, 0, sbc1.RollbackPreparedCount.Load(), "sbc1.RollbackPreparedCount") assert.EqualValues(t, 1, sbc1.CommitPreparedCount.Load(), "sbc1.CommitPreparedCount") diff --git a/go/vt/vtgate/txresolver/tx_resolver.go b/go/vt/vtgate/txresolver/tx_resolver.go new file mode 100644 index 00000000000..3c96c7bc836 --- /dev/null +++ b/go/vt/vtgate/txresolver/tx_resolver.go @@ -0,0 +1,104 @@ +/* +Copyright 2024 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 txresolver + +import ( + "context" + "sync" + + "vitess.io/vitess/go/vt/discovery" + "vitess.io/vitess/go/vt/log" + querypb "vitess.io/vitess/go/vt/proto/query" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" +) + +type TxResolver struct { + ch chan *discovery.TabletHealth + cancel context.CancelFunc + + txConn TxConnection + + mu sync.Mutex + resolve map[string]bool +} + +type TxConnection interface { + ResolveTransactions(ctx context.Context, target *querypb.Target) error +} + +func NewTxResolver(ch chan *discovery.TabletHealth, txConn TxConnection) *TxResolver { + return &TxResolver{ + ch: ch, + txConn: txConn, + resolve: make(map[string]bool), + } +} + +func (tr *TxResolver) Start() { + ctx, cancel := context.WithCancel(context.Background()) + tr.cancel = cancel + + go func() { + for { + select { + case <-ctx.Done(): + return + case th := <-tr.ch: + if th.Stats != nil && th.Target.TabletType == topodatapb.TabletType_PRIMARY && th.Stats.TxUnresolved { + go tr.resolveTransactions(ctx, th.Target) + } + } + } + }() +} + +func (tr *TxResolver) Stop() { + if tr.cancel != nil { + log.Info("Stopping transaction resolver") + tr.cancel() + } +} + +func (tr *TxResolver) resolveTransactions(ctx context.Context, target *querypb.Target) { + dest := target.Keyspace + ":" + target.Shard + if !tr.tryLockTarget(dest) { + return + } + log.Infof("resolving transactions for shard: %s", dest) + + defer func() { + tr.mu.Lock() + delete(tr.resolve, dest) + tr.mu.Unlock() + }() + err := tr.txConn.ResolveTransactions(ctx, target) + if err != nil { + log.Errorf("failed to resolve transactions for shard: %s, %v", dest, err) + return + } + log.Infof("successfully resolved all the transactions for shard: %s", dest) +} + +func (tr *TxResolver) tryLockTarget(dest string) bool { + tr.mu.Lock() + defer tr.mu.Unlock() + if tr.resolve[dest] { + return false + } + tr.resolve[dest] = true + return true +} diff --git a/go/vt/vtgate/vcursor_impl.go b/go/vt/vtgate/vcursor_impl.go index 9372012f77d..ae9c073e123 100644 --- a/go/vt/vtgate/vcursor_impl.go +++ b/go/vt/vtgate/vcursor_impl.go @@ -86,6 +86,7 @@ type iExecute interface { planPrepareStmt(ctx context.Context, vcursor *vcursorImpl, query string) (*engine.Plan, sqlparser.Statement, error) environment() *vtenv.Environment + ReadTransaction(ctx context.Context, transactionID string) (*querypb.TransactionMetadata, error) } // VSchemaOperator is an interface to Vschema Operations @@ -250,6 +251,10 @@ func (vc *vcursorImpl) IsShardRoutingEnabled() bool { return enableShardRouting } +func (vc *vcursorImpl) ReadTransaction(ctx context.Context, transactionID string) (*querypb.TransactionMetadata, error) { + return vc.executor.ReadTransaction(ctx, transactionID) +} + // FindTable finds the specified table. If the keyspace what specified in the input, it gets used as qualifier. // Otherwise, the keyspace from the request is used, if one was provided. func (vc *vcursorImpl) FindTable(name sqlparser.TableName) (*vindexes.Table, string, topodatapb.TabletType, key.Destination, error) { @@ -1225,7 +1230,16 @@ func (vc *vcursorImpl) ThrottleApp(ctx context.Context, throttledAppRule *topoda if throttlerConfig.ThrottledApps == nil { throttlerConfig.ThrottledApps = make(map[string]*topodatapb.ThrottledAppRule) } - throttlerConfig.ThrottledApps[req.ThrottledApp.Name] = req.ThrottledApp + if req.ThrottledApp != nil && req.ThrottledApp.Name != "" { + // TODO(shlomi) in v22: replace the following line with the commented out block + throttlerConfig.ThrottledApps[req.ThrottledApp.Name] = req.ThrottledApp + // timeNow := time.Now() + // if protoutil.TimeFromProto(req.ThrottledApp.ExpiresAt).After(timeNow) { + // throttlerConfig.ThrottledApps[req.ThrottledApp.Name] = req.ThrottledApp + // } else { + // delete(throttlerConfig.ThrottledApps, req.ThrottledApp.Name) + // } + } return throttlerConfig } diff --git a/go/vt/vtgate/vindexes/fuzz.go b/go/vt/vtgate/vindexes/fuzz.go index f1def0c3e1e..5a54aeb2bd8 100644 --- a/go/vt/vtgate/vindexes/fuzz.go +++ b/go/vt/vtgate/vindexes/fuzz.go @@ -67,6 +67,7 @@ var querypbTypes = []querypb.Type{querypb.Type_NULL_TYPE, querypb.Type_SET, querypb.Type_GEOMETRY, querypb.Type_JSON, + querypb.Type_VECTOR, querypb.Type_EXPRESSION} // All valid vindexes diff --git a/go/vt/vtgate/vindexes/vschema.go b/go/vt/vtgate/vindexes/vschema.go index 924a28b309d..eba3ac49969 100644 --- a/go/vt/vtgate/vindexes/vschema.go +++ b/go/vt/vtgate/vindexes/vschema.go @@ -1349,7 +1349,7 @@ func LoadFormal(filename string) (*vschemapb.SrvVSchema, error) { if err != nil { return nil, err } - err = json2.Unmarshal(data, formal) + err = json2.UnmarshalPB(data, formal) if err != nil { return nil, err } @@ -1367,7 +1367,7 @@ func LoadFormalKeyspace(filename string) (*vschemapb.Keyspace, error) { if err != nil { return nil, err } - err = json2.Unmarshal(data, formal) + err = json2.UnmarshalPB(data, formal) if err != nil { return nil, err } @@ -1378,12 +1378,10 @@ func LoadFormalKeyspace(filename string) (*vschemapb.Keyspace, error) { // the given SQL data type. func ChooseVindexForType(typ querypb.Type) (string, error) { switch { - case sqltypes.IsIntegral(typ): + case sqltypes.IsIntegral(typ) || sqltypes.IsBinary(typ): return "xxhash", nil case sqltypes.IsText(typ): - return "unicode_loose_md5", nil - case sqltypes.IsBinary(typ): - return "binary_md5", nil + return "unicode_loose_xxhash", nil } return "", vterrors.Errorf( vtrpcpb.Code_INVALID_ARGUMENT, diff --git a/go/vt/vtgate/vindexes/vschema_test.go b/go/vt/vtgate/vindexes/vschema_test.go index 40cba720a0c..7761b6ae8ab 100644 --- a/go/vt/vtgate/vindexes/vschema_test.go +++ b/go/vt/vtgate/vindexes/vschema_test.go @@ -960,22 +960,22 @@ func TestChooseVindexForType(t *testing.T) { out: "", }, { in: sqltypes.Text, - out: "unicode_loose_md5", + out: "unicode_loose_xxhash", }, { in: sqltypes.Blob, - out: "binary_md5", + out: "xxhash", }, { in: sqltypes.VarChar, - out: "unicode_loose_md5", + out: "unicode_loose_xxhash", }, { in: sqltypes.VarBinary, - out: "binary_md5", + out: "xxhash", }, { in: sqltypes.Char, - out: "unicode_loose_md5", + out: "unicode_loose_xxhash", }, { in: sqltypes.Binary, - out: "binary_md5", + out: "xxhash", }, { in: sqltypes.Bit, out: "", @@ -2735,7 +2735,7 @@ func TestVSchemaPBJSON(t *testing.T) { } ` var got vschemapb.Keyspace - if err := json2.Unmarshal([]byte(in), &got); err != nil { + if err := json2.UnmarshalPB([]byte(in), &got); err != nil { t.Error(err) } want := vschemapb.Keyspace{ diff --git a/go/vt/vtgate/vschema_manager.go b/go/vt/vtgate/vschema_manager.go index c73266af769..2b6761f4a8e 100644 --- a/go/vt/vtgate/vschema_manager.go +++ b/go/vt/vtgate/vschema_manager.go @@ -229,9 +229,9 @@ func (vm *VSchemaManager) updateTableInfo(vschema *vindexes.VSchema, ks *vindexe // Now that we have ensured that all the tables are created, we can start populating the foreign keys // in the tables. for tblName, tblInfo := range m { - rTbl, err := vschema.FindRoutedTable(ksName, tblName, topodatapb.TabletType_PRIMARY) - if err != nil { - log.Errorf("error finding routed table %s: %v", tblName, err) + rTbl := ks.Tables[tblName] + if rTbl == nil { + log.Errorf("unable to find table %s in %s", tblName, ksName) continue } for _, fkDef := range tblInfo.ForeignKeys { @@ -240,7 +240,7 @@ func (vm *VSchemaManager) updateTableInfo(vschema *vindexes.VSchema, ks *vindexe continue } parentTbl, err := vschema.FindRoutedTable(ksName, fkDef.ReferenceDefinition.ReferencedTable.Name.String(), topodatapb.TabletType_PRIMARY) - if err != nil { + if err != nil || parentTbl == nil { log.Errorf("error finding parent table %s: %v", fkDef.ReferenceDefinition.ReferencedTable.Name.String(), err) continue } diff --git a/go/vt/vtgate/vschema_manager_test.go b/go/vt/vtgate/vschema_manager_test.go index 32f83f0021a..8dfb889df0d 100644 --- a/go/vt/vtgate/vschema_manager_test.go +++ b/go/vt/vtgate/vschema_manager_test.go @@ -336,6 +336,49 @@ func TestVSchemaUpdate(t *testing.T) { } } +// TestKeyspaceRoutingRules tests that the vschema manager doens't panic in the presence of keyspace routing rules. +func TestKeyspaceRoutingRules(t *testing.T) { + cols1 := []vindexes.Column{{ + Name: sqlparser.NewIdentifierCI("id"), + Type: querypb.Type_INT64, + }} + // Create a vschema manager with a fake vschema that returns a table with a column and a primary key. + vm := &VSchemaManager{} + vm.schema = &fakeSchema{t: map[string]*vindexes.TableInfo{ + "t1": { + Columns: cols1, + Indexes: []*sqlparser.IndexDefinition{ + { + Info: &sqlparser.IndexInfo{Type: sqlparser.IndexTypePrimary}, + Columns: []*sqlparser.IndexColumn{ + { + Column: sqlparser.NewIdentifierCI("id"), + }, + }, + }, + }, + }, + }} + // Define a vschema that has a keyspace routing rule. + vs := &vindexes.VSchema{ + Keyspaces: map[string]*vindexes.KeyspaceSchema{ + "ks": { + Tables: map[string]*vindexes.Table{}, + Keyspace: &vindexes.Keyspace{Name: "ks", Sharded: true}, + }, + "ks2": { + Tables: map[string]*vindexes.Table{}, + Keyspace: &vindexes.Keyspace{Name: "ks2", Sharded: true}, + }, + }, + KeyspaceRoutingRules: map[string]string{ + "ks": "ks2", + }, + } + // Ensure that updating the vschema manager from the vschema doesn't cause a panic. + vm.updateFromSchema(vs) +} + func TestRebuildVSchema(t *testing.T) { cols1 := []vindexes.Column{{ Name: sqlparser.NewIdentifierCI("id"), diff --git a/go/vt/vtgate/vtgate.go b/go/vt/vtgate/vtgate.go index 9ea5da7a7e3..7d28c0e9697 100644 --- a/go/vt/vtgate/vtgate.go +++ b/go/vt/vtgate/vtgate.go @@ -30,8 +30,6 @@ import ( "github.com/spf13/pflag" - "vitess.io/vitess/go/vt/vtenv" - "vitess.io/vitess/go/acl" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/stats" @@ -51,9 +49,11 @@ import ( "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/srvtopo" "vitess.io/vitess/go/vt/topo/topoproto" + "vitess.io/vitess/go/vt/vtenv" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" vtschema "vitess.io/vitess/go/vt/vtgate/schema" + "vitess.io/vitess/go/vt/vtgate/txresolver" "vitess.io/vitess/go/vt/vtgate/vtgateservice" ) @@ -284,6 +284,8 @@ func Init( tc := NewTxConn(gw, getTxMode()) // ScatterConn depends on TxConn to perform forced rollbacks. sc := NewScatterConn("VttabletCall", tc, gw) + // TxResolver depends on TxConn to complete distributed transaction. + tr := txresolver.NewTxResolver(gw.hc.Subscribe(), tc) srvResolver := srvtopo.NewResolver(serv, gw, cell) resolver := NewResolver(srvResolver, serv, cell, sc) vsm := newVStreamManager(srvResolver, serv, cell) @@ -360,6 +362,7 @@ func Init( if st != nil && enableSchemaChangeSignal { st.Start() } + tr.Start() srv := initMySQLProtocol(vtgateInst) if srv != nil { servenv.OnTermSync(srv.shutdownMysqlProtocolAndDrain) @@ -370,6 +373,7 @@ func Init( if st != nil && enableSchemaChangeSignal { st.Stop() } + tr.Stop() }) vtgateInst.registerDebugHealthHandler() vtgateInst.registerDebugEnvHandler() @@ -552,11 +556,6 @@ func (vtg *VTGate) CloseSession(ctx context.Context, session *vtgatepb.Session) return vtg.executor.CloseSession(ctx, NewSafeSession(session)) } -// ResolveTransaction resolves the specified 2PC transaction. -func (vtg *VTGate) ResolveTransaction(ctx context.Context, dtid string) error { - return formatError(vtg.txConn.Resolve(ctx, dtid)) -} - // Prepare supports non-streaming prepare statement query with multi shards func (vtg *VTGate) Prepare(ctx context.Context, session *vtgatepb.Session, sql string, bindVariables map[string]*querypb.BindVariable) (newSession *vtgatepb.Session, fld []*querypb.Field, err error) { // In this context, we don't care if we can't fully parse destination diff --git a/go/vt/vtgate/vtgateconn/vtgateconn.go b/go/vt/vtgate/vtgateconn/vtgateconn.go index ae0da3fdf43..38899550c1d 100644 --- a/go/vt/vtgate/vtgateconn/vtgateconn.go +++ b/go/vt/vtgate/vtgateconn/vtgateconn.go @@ -87,11 +87,6 @@ func (conn *VTGateConn) SessionFromPb(sn *vtgatepb.Session) *VTGateSession { } } -// ResolveTransaction resolves the 2pc transaction. -func (conn *VTGateConn) ResolveTransaction(ctx context.Context, dtid string) error { - return conn.impl.ResolveTransaction(ctx, dtid) -} - // Close must be called for releasing resources. func (conn *VTGateConn) Close() { conn.impl.Close() @@ -178,9 +173,6 @@ type Impl interface { // CloseSession closes the session provided by rolling back any active transaction. CloseSession(ctx context.Context, session *vtgatepb.Session) error - // ResolveTransaction resolves the specified 2pc transaction. - ResolveTransaction(ctx context.Context, dtid string) error - // VStream streams binlogevents VStream(ctx context.Context, tabletType topodatapb.TabletType, vgtid *binlogdatapb.VGtid, filter *binlogdatapb.Filter, flags *vtgatepb.VStreamFlags) (VStreamReader, error) diff --git a/go/vt/vtgate/vtgateservice/interface.go b/go/vt/vtgate/vtgateservice/interface.go index bbfb2b2657e..c829f553d26 100644 --- a/go/vt/vtgate/vtgateservice/interface.go +++ b/go/vt/vtgate/vtgateservice/interface.go @@ -42,9 +42,6 @@ type VTGateService interface { // but does not affect the query statistics. CloseSession(ctx context.Context, session *vtgatepb.Session) error - // 2PC support - ResolveTransaction(ctx context.Context, dtid string) error - // Update Stream methods VStream(ctx context.Context, tabletType topodatapb.TabletType, vgtid *binlogdatapb.VGtid, filter *binlogdatapb.Filter, flags *vtgatepb.VStreamFlags, send func([]*binlogdatapb.VEvent) error) error diff --git a/go/vt/vttablet/endtoend/config_test.go b/go/vt/vttablet/endtoend/config_test.go index b1dc7f5dcb9..3902113f354 100644 --- a/go/vt/vttablet/endtoend/config_test.go +++ b/go/vt/vttablet/endtoend/config_test.go @@ -192,7 +192,7 @@ func TestConsolidatorReplicasOnly(t *testing.T) { } } -func TestQueryPlanCache(t *testing.T) { +func TestQueryEnginePlanCacheSize(t *testing.T) { var cachedPlanSize = int((&tabletserver.TabletPlan{}).CachedSize(true)) // sleep to avoid race between SchemaChanged event clearing out the plans cache which breaks this test @@ -211,19 +211,19 @@ func TestQueryPlanCache(t *testing.T) { assert.Equal(t, 1, framework.Server.QueryPlanCacheLen()) vend := framework.DebugVars() - assert.GreaterOrEqual(t, framework.FetchInt(vend, "QueryCacheSize"), cachedPlanSize) + assert.GreaterOrEqual(t, framework.FetchInt(vend, "QueryEnginePlanCacheSize"), cachedPlanSize) _, _ = client.Execute("select * from vitess_test where intval=:ival2", bindVars) require.Equal(t, 2, framework.Server.QueryPlanCacheLen()) vend = framework.DebugVars() - assert.GreaterOrEqual(t, framework.FetchInt(vend, "QueryCacheSize"), 2*cachedPlanSize) + assert.GreaterOrEqual(t, framework.FetchInt(vend, "QueryEnginePlanCacheSize"), 2*cachedPlanSize) _, _ = client.Execute("select * from vitess_test where intval=1", bindVars) require.Equal(t, 3, framework.Server.QueryPlanCacheLen()) vend = framework.DebugVars() - assert.GreaterOrEqual(t, framework.FetchInt(vend, "QueryCacheSize"), 3*cachedPlanSize) + assert.GreaterOrEqual(t, framework.FetchInt(vend, "QueryEnginePlanCacheSize"), 3*cachedPlanSize) } func TestMaxResultSize(t *testing.T) { diff --git a/go/vt/vttablet/endtoend/framework/client.go b/go/vt/vttablet/endtoend/framework/client.go index dc4b7f9f339..1cbff71dc25 100644 --- a/go/vt/vttablet/endtoend/framework/client.go +++ b/go/vt/vttablet/endtoend/framework/client.go @@ -178,6 +178,11 @@ func (client *QueryClient) ReadTransaction(dtid string) (*querypb.TransactionMet return client.server.ReadTransaction(client.ctx, client.target, dtid) } +// UnresolvedTransactions invokes the UnresolvedTransactions API of TabletServer. +func (client *QueryClient) UnresolvedTransactions() ([]*querypb.TransactionMetadata, error) { + return client.server.UnresolvedTransactions(client.ctx, client.target) +} + // SetServingType is for testing transitions. // It currently supports only primary->replica and back. func (client *QueryClient) SetServingType(tabletType topodatapb.TabletType) error { diff --git a/go/vt/vttablet/endtoend/framework/server.go b/go/vt/vttablet/endtoend/framework/server.go index 95c8114fd9f..2cd3ccc354c 100644 --- a/go/vt/vttablet/endtoend/framework/server.go +++ b/go/vt/vttablet/endtoend/framework/server.go @@ -35,8 +35,6 @@ import ( "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/vt/dbconfigs" - "vitess.io/vitess/go/vt/vtgate/fakerpcvtgateconn" - "vitess.io/vitess/go/vt/vtgate/vtgateconn" "vitess.io/vitess/go/vt/vttablet/tabletserver" "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" @@ -51,8 +49,6 @@ var ( Server *tabletserver.TabletServer // ServerAddress is the http URL for the server. ServerAddress string - // ResolveChan is the channel that sends dtids that are to be resolved. - ResolveChan = make(chan string, 1) // TopoServer is the topology for the server TopoServer *topo.Server ) @@ -61,15 +57,6 @@ var ( // all the global variables. This function should only be called // once at the beginning of the test. func StartCustomServer(ctx context.Context, connParams, connAppDebugParams mysql.ConnParams, dbName string, cfg *tabletenv.TabletConfig) error { - // Setup a fake vtgate server. - protocol := "resolveTest" - vtgateconn.SetVTGateProtocol(protocol) - vtgateconn.RegisterDialer(protocol, func(context.Context, string) (vtgateconn.Impl, error) { - return &txResolver{ - FakeVTGateConn: fakerpcvtgateconn.FakeVTGateConn{}, - }, nil - }) - dbcfgs := dbconfigs.NewTestDBConfigs(connParams, connAppDebugParams, dbName) Target = &querypb.Target{ @@ -118,7 +105,6 @@ func StartServer(ctx context.Context, connParams, connAppDebugParams mysql.ConnP config.StrictTableACL = true config.TwoPCEnable = true config.TwoPCAbandonAge = 1 - config.TwoPCCoordinatorAddress = "fake" config.HotRowProtection.Mode = tabletenv.Enable config.TrackSchemaVersions = true config.GracePeriods.Shutdown = 2 * time.Second @@ -138,16 +124,3 @@ func StartServer(ctx context.Context, connParams, connAppDebugParams mysql.ConnP func StopServer() { Server.StopService() } - -// txResolver transmits dtids to be resolved through ResolveChan. -type txResolver struct { - fakerpcvtgateconn.FakeVTGateConn -} - -func (conn *txResolver) ResolveTransaction(ctx context.Context, dtid string) error { - select { - case ResolveChan <- dtid: - default: - } - return nil -} diff --git a/go/vt/vttablet/endtoend/main_test.go b/go/vt/vttablet/endtoend/main_test.go index 939147cb139..1284f790b93 100644 --- a/go/vt/vttablet/endtoend/main_test.go +++ b/go/vt/vttablet/endtoend/main_test.go @@ -340,6 +340,13 @@ var tableACLConfig = `{ "readers": ["dev"], "writers": ["dev"], "admins": ["dev"] + }, + { + "name": "vitess_twopc", + "table_names_or_prefixes": ["dt_state"], + "readers": ["dev"], + "writers": ["dev"], + "admins": ["dev"] } ] }` diff --git a/go/vt/vttablet/endtoend/misc_test.go b/go/vt/vttablet/endtoend/misc_test.go index 768399572db..29bbba56873 100644 --- a/go/vt/vttablet/endtoend/misc_test.go +++ b/go/vt/vttablet/endtoend/misc_test.go @@ -198,7 +198,7 @@ func TestTrailingComment(t *testing.T) { } v2 := framework.Server.QueryPlanCacheLen() if v2 != v1+1 { - t.Errorf("QueryCacheLength(%s): %d, want %d", query, v2, v1+1) + t.Errorf("QueryEnginePlanCacheLength(%s): %d, want %d", query, v2, v1+1) } } } diff --git a/go/vt/vttablet/endtoend/reserve_test.go b/go/vt/vttablet/endtoend/reserve_test.go index d3fb685dd49..0712233c559 100644 --- a/go/vt/vttablet/endtoend/reserve_test.go +++ b/go/vt/vttablet/endtoend/reserve_test.go @@ -17,1178 +17,13 @@ limitations under the License. package endtoend import ( - "fmt" - "sync" "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "vitess.io/vitess/go/vt/vttablet/endtoend/framework" ) -func TestMultipleReserveHaveDifferentConnection(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client1 := framework.NewClient() - client2 := framework.NewClient() - - query := "select connection_id()" - - qrc1_1, err := client1.ReserveExecute(query, nil, nil) - require.NoError(t, err) - defer client1.Release() - qrc2_1, err := client2.ReserveExecute(query, nil, nil) - require.NoError(t, err) - defer client2.Release() - require.NotEqual(t, qrc1_1.Rows, qrc2_1.Rows) - - qrc1_2, err := client1.Execute(query, nil) - require.NoError(t, err) - qrc2_2, err := client2.Execute(query, nil) - require.NoError(t, err) - require.Equal(t, qrc1_1.Rows, qrc1_2.Rows) - require.Equal(t, qrc2_1.Rows, qrc2_2.Rows) -} - -func TestReserveBeginRelease(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - query := "select connection_id()" - - qr1, err := client.ReserveExecute(query, nil, nil) - require.NoError(t, err) - defer client.Release() - - qr2, err := client.BeginExecute(query, nil, nil) - require.NoError(t, err) - assert.Equal(t, qr1.Rows, qr2.Rows) - assert.Equal(t, client.ReservedID(), client.TransactionID()) - - require.NoError(t, client.Release()) -} - -func TestBeginReserveRelease(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - query := "select connection_id()" - - qr1, err := client.BeginExecute(query, nil, nil) - require.NoError(t, err) - defer client.Release() - - qr2, err := client.ReserveExecute(query, nil, nil) - require.NoError(t, err) - assert.Equal(t, qr1.Rows, qr2.Rows) - assert.Equal(t, client.ReservedID(), client.TransactionID()) - - require.NoError(t, client.Release()) -} - -func TestReserveBeginExecuteRelease(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - insQuery := "insert into vitess_test (intval, floatval, charval, binval) values (4, null, null, null)" - selQuery := "select intval from vitess_test where intval = 4" - _, err := client.ReserveBeginExecute(insQuery, nil, nil, nil) - require.NoError(t, err) - - qr, err := client.Execute(selQuery, nil) - require.NoError(t, err) - assert.Equal(t, `[[INT32(4)]]`, fmt.Sprintf("%v", qr.Rows)) - - err = client.Release() - require.NoError(t, err) - - qr, err = client.Execute(selQuery, nil) - require.NoError(t, err) - assert.Equal(t, `[]`, fmt.Sprintf("%v", qr.Rows)) -} - -func TestMultipleReserveBeginHaveDifferentConnection(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client1 := framework.NewClient() - client2 := framework.NewClient() - - query := "select connection_id()" - - qrc1_1, err := client1.ReserveBeginExecute(query, nil, nil, nil) - require.NoError(t, err) - defer client1.Release() - qrc2_1, err := client2.ReserveBeginExecute(query, nil, nil, nil) - require.NoError(t, err) - defer client2.Release() - require.NotEqual(t, qrc1_1.Rows, qrc2_1.Rows) - - qrc1_2, err := client1.Execute(query, nil) - require.NoError(t, err) - qrc2_2, err := client2.Execute(query, nil) - require.NoError(t, err) - require.Equal(t, qrc1_1.Rows, qrc1_2.Rows) - require.Equal(t, qrc2_1.Rows, qrc2_2.Rows) -} - -func TestCommitOnReserveBeginConn(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - query := "select connection_id()" - - qr1, err := client.ReserveBeginExecute(query, nil, nil, nil) - require.NoError(t, err) - defer client.Release() - - oldRID := client.ReservedID() - err = client.Commit() - require.NoError(t, err) - assert.NotEqual(t, client.ReservedID(), oldRID, "reservedID must change after commit") - assert.EqualValues(t, 0, client.TransactionID(), "transactionID should be 0 after commit") - - qr2, err := client.Execute(query, nil) - require.NoError(t, err) - assert.Equal(t, qr1.Rows, qr2.Rows) -} - -func TestRollbackOnReserveBeginConn(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - query := "select connection_id()" - - qr1, err := client.ReserveBeginExecute(query, nil, nil, nil) - require.NoError(t, err) - defer client.Release() - - oldRID := client.ReservedID() - err = client.Rollback() - require.NoError(t, err) - assert.NotEqual(t, client.ReservedID(), oldRID, "reservedID must change after rollback") - assert.EqualValues(t, 0, client.TransactionID(), "transactionID should be 0 after commit") - - qr2, err := client.Execute(query, nil) - require.NoError(t, err) - assert.Equal(t, qr1.Rows, qr2.Rows) -} - -func TestReserveBeginRollbackAndBeginCommitAgain(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - query := "select connection_id()" - - qr1, err := client.ReserveBeginExecute(query, nil, nil, nil) - require.NoError(t, err) - defer client.Release() - - oldRID := client.ReservedID() - err = client.Rollback() - require.NoError(t, err) - assert.EqualValues(t, 0, client.TransactionID(), "transactionID should be 0 after rollback") - assert.NotEqual(t, client.ReservedID(), oldRID, "reservedID must change after rollback") - - oldRID = client.ReservedID() - - qr2, err := client.BeginExecute(query, nil, nil) - require.NoError(t, err) - - err = client.Commit() - require.NoError(t, err) - assert.EqualValues(t, 0, client.TransactionID(), "transactionID should be 0 after commit") - assert.NotEqual(t, client.ReservedID(), oldRID, "reservedID must change after rollback") - - qr3, err := client.Execute(query, nil) - require.NoError(t, err) - assert.Equal(t, qr1.Rows, qr2.Rows) - assert.Equal(t, qr2.Rows, qr3.Rows) - - require.NoError(t, - client.Release()) -} - -func TestReserveBeginCommitFailToReuseTxID(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - query := "select connection_id()" - - _, err := client.ReserveBeginExecute(query, nil, nil, nil) - require.NoError(t, err) - defer client.Release() - - oldTxID := client.TransactionID() - - err = client.Commit() - require.NoError(t, err) - - client.SetTransactionID(oldTxID) - - _, err = client.Execute(query, nil) - require.Error(t, err) - require.NoError(t, - client.Release()) -} - -func TestReserveBeginRollbackFailToReuseTxID(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - query := "select connection_id()" - - _, err := client.ReserveBeginExecute(query, nil, nil, nil) - require.NoError(t, err) - defer client.Release() - - oldTxID := client.TransactionID() - - err = client.Rollback() - require.NoError(t, err) - - client.SetTransactionID(oldTxID) - - _, err = client.Execute(query, nil) - require.Error(t, err) - require.NoError(t, - client.Release()) -} - -func TestReserveBeginCommitFailToReuseOldReservedID(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - query := "select connection_id()" - - _, err := client.ReserveBeginExecute(query, nil, nil, nil) - require.NoError(t, err) - - oldRID := client.ReservedID() - - err = client.Commit() - require.NoError(t, err) - newRID := client.ReservedID() - - client.SetReservedID(oldRID) - - _, err = client.Execute(query, nil) - require.Error(t, err) - - client.SetReservedID(newRID) - require.NoError(t, - client.Release()) -} - -func TestReserveBeginRollbackFailToReuseOldReservedID(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - query := "select connection_id()" - - _, err := client.ReserveBeginExecute(query, nil, nil, nil) - require.NoError(t, err) - - oldRID := client.ReservedID() - - err = client.Rollback() - require.NoError(t, err) - newRID := client.ReservedID() - - client.SetReservedID(oldRID) - _, err = client.Execute(query, nil) - require.Error(t, err) - - client.SetReservedID(newRID) - require.NoError(t, - client.Release()) -} - -func TestReserveReleaseAndFailToUseReservedIDAgain(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - query := "select 42" - - _, err := client.ReserveExecute(query, nil, nil) - require.NoError(t, err) - - rID := client.ReservedID() - require.NoError(t, - client.Release()) - - client.SetReservedID(rID) - - _, err = client.Execute(query, nil) - require.Error(t, err) -} - -func TestReserveAndFailToRunTwiceConcurrently(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - query := "select 42" - - _, err := client.ReserveExecute(query, nil, nil) - require.NoError(t, err) - defer client.Release() - - // WaitGroup will make defer call to wait for go func to complete. - wg := &sync.WaitGroup{} - wg.Add(1) - go func() { - _, err = client.Execute("select sleep(1)", nil) - wg.Done() - }() - _, err2 := client.Execute("select sleep(1)", nil) - wg.Wait() - - if err == nil && err2 == nil { - assert.Fail(t, "at least one execution should fail") - } -} - -func TestBeginReserveCommitAndNewTransactionsOnSameReservedID(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - query := "select connection_id()" - - qrTx, err := client.BeginExecute(query, nil, nil) - require.NoError(t, err) - - qrRID, err := client.ReserveExecute(query, nil, nil) - require.NoError(t, err) - require.Equal(t, qrTx.Rows, qrRID.Rows) - - err = client.Commit() - require.NoError(t, err) - - qrTx, err = client.BeginExecute(query, nil, nil) - require.NoError(t, err) - require.Equal(t, qrTx.Rows, qrRID.Rows) - - err = client.Commit() - require.NoError(t, err) - - qrTx, err = client.BeginExecute(query, nil, nil) - require.NoError(t, err) - require.Equal(t, qrTx.Rows, qrRID.Rows) - - err = client.Rollback() - require.NoError(t, err) - - require.NoError(t, - client.Release()) -} - -func TestBeginReserveRollbackAndNewTransactionsOnSameReservedID(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - query := "select connection_id()" - - qrTx, err := client.BeginExecute(query, nil, nil) - require.NoError(t, err) - - qrRID, err := client.ReserveExecute(query, nil, nil) - require.NoError(t, err) - require.Equal(t, qrTx.Rows, qrRID.Rows) - - err = client.Rollback() - require.NoError(t, err) - - qrTx, err = client.BeginExecute(query, nil, nil) - require.NoError(t, err) - require.Equal(t, qrTx.Rows, qrRID.Rows) - - err = client.Commit() - require.NoError(t, err) - - qrTx, err = client.BeginExecute(query, nil, nil) - require.NoError(t, err) - require.Equal(t, qrTx.Rows, qrRID.Rows) - - err = client.Rollback() - require.NoError(t, err) - - require.NoError(t, - client.Release()) -} - -func TestBeginReserveReleaseAndFailToUseReservedIDAndTxIDAgain(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - query := "select 42" - - _, err := client.BeginExecute(query, nil, nil) - require.NoError(t, err) - - _, err = client.ReserveExecute(query, nil, nil) - require.NoError(t, err) - - rID := client.ReservedID() - txID := client.TransactionID() - - require.NoError(t, - client.Release()) - - client.SetReservedID(rID) - _, err = client.Execute(query, nil) - require.Error(t, err) - - client.SetReservedID(0) - client.SetTransactionID(txID) - _, err = client.Execute(query, nil) - require.Error(t, err) -} - -func TestReserveBeginReleaseAndFailToUseReservedIDAndTxIDAgain(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - query := "select 42" - - _, err := client.ReserveExecute(query, nil, nil) - require.NoError(t, err) - - _, err = client.BeginExecute(query, nil, nil) - require.NoError(t, err) - - rID := client.ReservedID() - txID := client.TransactionID() - - require.NoError(t, - client.Release()) - - client.SetReservedID(rID) - _, err = client.Execute(query, nil) - require.Error(t, err) - - client.SetReservedID(0) - client.SetTransactionID(txID) - _, err = client.Execute(query, nil) - require.Error(t, err) -} - -func TestReserveExecuteWithFailingQueryAndReserveConnectionRemainsOpen(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - _, err := client.ReserveExecute("select foo", nil, nil) - require.Error(t, err) - defer client.Release() - require.NotEqual(t, int64(0), client.ReservedID()) - - _, err = client.Execute("select 42", nil) - require.NoError(t, err) - require.NoError(t, client.Release()) -} - -func TestReserveAndExecuteWithFailingQueryAndReserveConnectionRemainsOpen(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - qr1, err := client.ReserveExecute("select connection_id()", nil, nil) - require.NoError(t, err) - defer client.Release() - - _, err = client.Execute("select foo", nil) - require.Error(t, err) - - qr2, err := client.Execute("select connection_id()", nil) - require.NoError(t, err) - require.Equal(t, qr1.Rows, qr2.Rows) - require.NoError(t, client.Release()) -} - -func TestReserveBeginExecuteWithFailingQueryAndReserveConnAndTxRemainsOpen(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - _, err := client.ReserveBeginExecute("select foo", nil, nil, nil) - require.Error(t, err) - - // Save the connection id to check in the end that everything got executed on same connection. - qr1, err := client.Execute("select connection_id()", nil) - require.NoError(t, err) - - _, err = client.Execute("insert into vitess_test (intval, floatval, charval, binval) values (4, null, null, null)", nil) - require.NoError(t, err) - - qr, err := client.Execute("select intval from vitess_test", nil) - require.NoError(t, err) - assert.Equal(t, "[[INT32(1)] [INT32(2)] [INT32(3)] [INT32(4)]]", fmt.Sprintf("%v", qr.Rows)) - - err = client.Rollback() - require.NoError(t, err) - - qr, err = client.Execute("select intval from vitess_test", nil) - require.NoError(t, err) - assert.Equal(t, "[[INT32(1)] [INT32(2)] [INT32(3)]]", fmt.Sprintf("%v", qr.Rows)) - - qr2, err := client.Execute("select connection_id()", nil) - require.NoError(t, err) - require.Equal(t, qr1.Rows, qr2.Rows) - - require.NoError(t, client.Release()) -} - -func TestReserveAndBeginExecuteWithFailingQueryAndReserveConnAndTxRemainsOpen(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - // Save the connection id to check in the end that everything got executed on same connection. - qr1, err := client.ReserveExecute("select connection_id()", nil, nil) - require.NoError(t, err) - - _, err = client.BeginExecute("select foo", nil, nil) - require.Error(t, err) - - _, err = client.Execute("insert into vitess_test (intval, floatval, charval, binval) values (4, null, null, null)", nil) - require.NoError(t, err) - - qr, err := client.Execute("select intval from vitess_test", nil) - require.NoError(t, err) - assert.Equal(t, "[[INT32(1)] [INT32(2)] [INT32(3)] [INT32(4)]]", fmt.Sprintf("%v", qr.Rows)) - - err = client.Rollback() - require.NoError(t, err) - - qr, err = client.Execute("select intval from vitess_test", nil) - require.NoError(t, err) - assert.Equal(t, "[[INT32(1)] [INT32(2)] [INT32(3)]]", fmt.Sprintf("%v", qr.Rows)) - - qr2, err := client.Execute("select connection_id()", nil) - require.NoError(t, err) - require.Equal(t, qr1.Rows, qr2.Rows) - - require.NoError(t, client.Release()) -} - -func TestReserveExecuteWithPreQueriesAndCheckConnectionState(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client1 := framework.NewClient() - client2 := framework.NewClient() - - selQuery := "select str_to_date('00/00/0000', '%m/%d/%Y')" - warnQuery := "show warnings" - preQueries1 := []string{ - "set sql_mode = ''", - } - preQueries2 := []string{ - "set sql_mode = 'NO_ZERO_DATE'", - } - - qr1, err := client1.ReserveExecute(selQuery, preQueries1, nil) - require.NoError(t, err) - defer client1.Release() - - qr2, err := client2.ReserveExecute(selQuery, preQueries2, nil) - require.NoError(t, err) - defer client2.Release() - - assert.NotEqual(t, qr1.Rows, qr2.Rows) - assert.Equal(t, `[[DATE("0000-00-00")]]`, fmt.Sprintf("%v", qr1.Rows)) - assert.Equal(t, `[[NULL]]`, fmt.Sprintf("%v", qr2.Rows)) - - qr1, err = client1.Execute(warnQuery, nil) - require.NoError(t, err) - - qr2, err = client2.Execute(warnQuery, nil) - require.NoError(t, err) - - assert.NotEqual(t, qr1.Rows, qr2.Rows) - assert.Equal(t, `[]`, fmt.Sprintf("%v", qr1.Rows)) - assert.Equal(t, `[[VARCHAR("Warning") UINT32(1411) VARCHAR("Incorrect datetime value: '00/00/0000' for function str_to_date")]]`, fmt.Sprintf("%v", qr2.Rows)) -} - -func TestReserveExecuteWithPreQueriesAndSavepoint(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - defer client.Release() - - insQuery := "insert into vitess_test (intval) values (5)" - selQuery := "select intval from vitess_test where intval = 5" - preQueries := []string{ - "set sql_mode = ''", - } - - postBeginQueries1 := []string{ - "savepoint a", - } - // savepoint there after begin. - _, err := client.ReserveBeginExecute(insQuery, preQueries, postBeginQueries1, nil) - require.NoError(t, err) - - qr, err := client.Execute(selQuery, nil) - require.NoError(t, err) - assert.Equal(t, `[[INT32(5)]]`, fmt.Sprintf("%v", qr.Rows)) - - _, err = client.Execute("rollback to a", nil) - require.NoError(t, err) - - qr, err = client.Execute(selQuery, nil) - require.NoError(t, err) - assert.Equal(t, `[]`, fmt.Sprintf("%v", qr.Rows)) - - err = client.Release() - require.NoError(t, err) - - postBeginQueries2 := []string{ - "savepoint a", - "release savepoint a", - "savepoint b", - } - // no savepoint after begin - _, err = client.ReserveBeginExecute(insQuery, preQueries, postBeginQueries2, nil) - require.NoError(t, err) - - qr, err = client.Execute(selQuery, nil) - require.NoError(t, err) - assert.Equal(t, `[[INT32(5)]]`, fmt.Sprintf("%v", qr.Rows)) - - // no savepoint a - _, err = client.Execute("rollback to a", nil) - require.Error(t, err) - - // no savepoint a. - _, err = client.Execute("release a", nil) - require.Error(t, err) - - // record still exists. - qr, err = client.Execute(selQuery, nil) - require.NoError(t, err) - assert.Equal(t, `[[INT32(5)]]`, fmt.Sprintf("%v", qr.Rows)) - - _, err = client.Execute("rollback to b", nil) - require.NoError(t, err) - - qr, err = client.Execute(selQuery, nil) - require.NoError(t, err) - assert.Equal(t, `[]`, fmt.Sprintf("%v", qr.Rows)) -} - -func TestReserveBeginExecuteWithPreQueriesAndCheckConnectionState(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - rcClient := framework.NewClient() - rucClient := framework.NewClient() - - insRcQuery := "insert into vitess_test (intval, floatval, charval, binval) values (4, null, null, null)" - insRucQuery := "insert into vitess_test (intval, floatval, charval, binval) values (5, null, null, null)" - selQuery := "select intval from vitess_test" - delQuery := "delete from vitess_test where intval = 5" - rcQuery := []string{ - "set session transaction isolation level read committed", - } - rucQuery := []string{ - "set session transaction isolation level read uncommitted", - } - - _, err := rcClient.ReserveBeginExecute(insRcQuery, rcQuery, nil, nil) - require.NoError(t, err) - defer rcClient.Release() - - _, err = rucClient.ReserveBeginExecute(insRucQuery, rucQuery, nil, nil) - require.NoError(t, err) - defer rucClient.Release() - - qr1, err := rcClient.Execute(selQuery, nil) - require.NoError(t, err) - - qr2, err := rucClient.Execute(selQuery, nil) - require.NoError(t, err) - - assert.NotEqual(t, qr1.Rows, qr2.Rows) - // As the transaction is read committed it is not able to see #5. - assert.Equal(t, `[[INT32(1)] [INT32(2)] [INT32(3)] [INT32(4)]]`, fmt.Sprintf("%v", qr1.Rows)) - // As the transaction is read uncommitted it is able to see #4. - assert.Equal(t, `[[INT32(1)] [INT32(2)] [INT32(3)] [INT32(4)] [INT32(5)]]`, fmt.Sprintf("%v", qr2.Rows)) - - err = rucClient.Commit() - require.NoError(t, err) - - qr1, err = rcClient.Execute(selQuery, nil) - require.NoError(t, err) - - qr2, err = rucClient.Execute(selQuery, nil) - require.NoError(t, err) - - // As the transaction on read uncommitted client got committed, transaction with read committed will be able to see #5. - assert.Equal(t, qr1.Rows, qr2.Rows) - assert.Equal(t, `[[INT32(1)] [INT32(2)] [INT32(3)] [INT32(4)] [INT32(5)]]`, fmt.Sprintf("%v", qr1.Rows)) - - err = rcClient.Rollback() - require.NoError(t, err) - - qr1, err = rcClient.Execute(selQuery, nil) - require.NoError(t, err) - - qr2, err = rucClient.Execute(selQuery, nil) - require.NoError(t, err) - - // As the transaction on read committed client got rolled back, table will forget #4. - assert.Equal(t, qr1.Rows, qr2.Rows) - assert.Equal(t, `[[INT32(1)] [INT32(2)] [INT32(3)] [INT32(5)]]`, fmt.Sprintf("%v", qr2.Rows)) - - // This is executed on reserved connection without transaction as the transaction was committed. - _, err = rucClient.Execute(delQuery, nil) - require.NoError(t, err) -} - -func TestReserveExecuteWithFailingPreQueriesAndCheckConnectionState(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - selQuery := "select 42" - preQueries := []string{ - "set @@no_sys_var = 42", - } - - _, err := client.ReserveExecute(selQuery, preQueries, nil) - require.Error(t, err) - - err = client.Release() - require.Error(t, err) -} - -func TestReserveBeginExecuteWithFailingPreQueriesAndCheckConnectionState(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - selQuery := "select 42" - preQueries := []string{ - "set @@no_sys_var = 42", - } - - _, err := client.ReserveBeginExecute(selQuery, preQueries, nil, nil) - require.Error(t, err) - - err = client.Commit() - require.Error(t, err) - - err = client.Release() - require.Error(t, err) -} - -func TestBeginReserveExecuteWithFailingPreQueriesAndCheckConnectionState(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - selQuery := "select 42" - preQueries := []string{ - "set @@no_sys_var = 42", - } - - _, err := client.BeginExecute(selQuery, nil, nil) - require.NoError(t, err) - - _, err = client.ReserveExecute(selQuery, preQueries, nil) - require.Error(t, err) - - err = client.Commit() - require.Error(t, err) - - err = client.Release() - require.Error(t, err) -} - -func TestReserveBeginExecuteWithCommitFailureAndCheckConnectionAndDBState(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - connQuery := "select connection_id()" - insQuery := "insert into vitess_test (intval, floatval, charval, binval) values (4, null, null, null)" - selQuery := "select intval from vitess_test where intval = 4" - - connQr, err := client.ReserveBeginExecute(connQuery, nil, nil, nil) - require.NoError(t, err) - - _, err = client.Execute(insQuery, nil) - require.NoError(t, err) - - killConnection(t, connQr.Rows[0][0].ToString()) - - err = client.Commit() - require.Error(t, err) - require.Zero(t, client.ReservedID()) - - qr, err := client.Execute(selQuery, nil) - require.NoError(t, err) - require.Empty(t, qr.Rows) - - qr, err = client.Execute(connQuery, nil) - require.NoError(t, err) - require.NotEqual(t, connQr.Rows, qr.Rows) - - require.Error(t, client.Release()) -} - -func TestReserveBeginExecuteWithRollbackFailureAndCheckConnectionAndDBState(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - connQuery := "select connection_id()" - insQuery := "insert into vitess_test (intval, floatval, charval, binval) values (4, null, null, null)" - selQuery := "select intval from vitess_test where intval = 4" - - connQr, err := client.ReserveBeginExecute(connQuery, nil, nil, nil) - require.NoError(t, err) - - _, err = client.Execute(insQuery, nil) - require.NoError(t, err) - - killConnection(t, connQr.Rows[0][0].ToString()) - - err = client.Rollback() - require.Error(t, err) - require.Zero(t, client.ReservedID()) - - qr, err := client.Execute(selQuery, nil) - require.NoError(t, err) - require.Empty(t, qr.Rows) - - qr, err = client.Execute(connQuery, nil) - require.NoError(t, err) - require.NotEqual(t, connQr.Rows, qr.Rows) - - require.Error(t, client.Release()) -} - -func TestReserveExecuteWithExecuteFailureAndCheckConnectionAndDBState(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - connQuery := "select connection_id()" - insQuery := "insert into vitess_test (intval, floatval, charval, binval) values (4, null, null, null)" - selQuery := "select intval from vitess_test where intval = 4" - - connQr, err := client.ReserveExecute(connQuery, nil, nil) - require.NoError(t, err) - - killConnection(t, connQr.Rows[0][0].ToString()) - - _, err = client.Execute(insQuery, nil) - require.Error(t, err) - // Expectation - require.Zero(t, client.ReservedID()) - // Reality - require.NotZero(t, client.ReservedID()) - - // Client still has transaction id and client id as non-zero. - _, err = client.Execute(selQuery, nil) - require.Error(t, err) - client.SetTransactionID(0) - - _, err = client.Execute(selQuery, nil) - require.Error(t, err) - client.SetReservedID(0) - - qr, err := client.Execute(selQuery, nil) - require.NoError(t, err) - require.Empty(t, qr.Rows) - - qr, err = client.Execute(connQuery, nil) - require.NoError(t, err) - require.NotEqual(t, connQr.Rows, qr.Rows) - - require.Error(t, client.Release()) -} - -func TestReserveExecuteDDLWithoutTx(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - defer client.Release() - - connQuery := "select connection_id()" - createQuery := "create table vitess_test_ddl(id bigint primary key)" - dropQuery := "drop table vitess_test_ddl" - descQuery := "describe vitess_test_ddl" - - qr1, err := client.ReserveExecute(connQuery, nil, nil) - require.NoError(t, err) - - _, err = client.Execute(createQuery, nil) - require.NoError(t, err) - require.Zero(t, client.TransactionID()) - defer client.Execute(dropQuery, nil) - - qr2, err := client.Execute(connQuery, nil) - require.NoError(t, err) - assert.Equal(t, qr1.Rows, qr2.Rows) - - qr3, err := client.Execute(descQuery, nil) - require.NoError(t, err) - require.NotZero(t, qr3.Rows) -} - -func TestReserveExecuteDDLWithTx(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - defer client.Release() - - connQuery := "select connection_id()" - createQuery := "create table vitess_test_ddl(id bigint primary key)" - dropQuery := "drop table vitess_test_ddl" - descQuery := "describe vitess_test_ddl" - - qr1, err := client.ReserveBeginExecute(connQuery, nil, nil, nil) - require.NoError(t, err) - - _, err = client.Execute(createQuery, nil) - require.NoError(t, err) - require.NotZero(t, client.TransactionID()) - defer client.Execute(dropQuery, nil) - - qr2, err := client.Execute(connQuery, nil) - require.NoError(t, err) - assert.Equal(t, qr1.Rows, qr2.Rows) - - qr3, err := client.Execute(descQuery, nil) - require.NoError(t, err) - require.NotZero(t, qr3.Rows) -} - -func killConnection(t *testing.T, connID string) { - client := framework.NewClient() - _, err := client.ReserveExecute("select 1", []string{fmt.Sprintf("kill %s", connID)}, nil) - require.NoError(t, err) - defer client.Release() -} - -func BenchmarkPreQueries(b *testing.B) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - tcases := []struct { - name string - settings []string - }{{ - name: "split_1", - settings: []string{ - "set @@sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'"}, - }, { - name: "split_2", - settings: []string{ - "set @@sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'", - "set @@sql_safe_updates = false"}, - }, { - name: "split_3", - settings: []string{ - "set @@sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'", - "set @@sql_safe_updates = false", - "set @@read_buffer_size = 9191181919"}, - }, { - name: "split_4", - settings: []string{ - "set @@sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'", - "set @@sql_safe_updates = false", "set @@read_buffer_size = 9191181919", - "set @@max_heap_table_size = 10204023"}, - }, { - name: "combined_2", - settings: []string{"set @@sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION', @@sql_safe_updates = false"}, - }, { - name: "combined_3", - settings: []string{"set @@sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION', @@sql_safe_updates = false, @@read_buffer_size = 9191181919"}, - }, { - name: "combined_4", - settings: []string{"set @@sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION', @@sql_safe_updates = false, @@read_buffer_size = 9191181919, @@max_heap_table_size = 10204023"}, - }} - query := "select connection_id()" - - for _, tcase := range tcases { - b.Run(tcase.name, func(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := client.ReserveExecute(query, tcase.settings, nil); err != nil { - b.Error(err) - } - if err := client.Release(); err != nil { - b.Error(err) - } - } - }) - } -} - -func TestFailInfiniteSessions(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - qr, err := client.Execute("select @@max_connections", nil) - require.NoError(t, err) - maxConn, err := qr.Rows[0][0].ToInt64() - require.NoError(t, err) - - // twice the number of sessions than the pool size. - numOfSessions := int(maxConn * 2) - - var clients []*framework.QueryClient - - // read session - var failed bool - for i := 0; i < numOfSessions; i++ { - client := framework.NewClient() - _, err := client.ReserveExecute("select 1", []string{"set sql_mode = ''"}, nil) - if err != nil { - failed = true - require.Contains(t, err.Error(), "immediate error from server errorCode=1040 errorMsg=Too many connections") - break - } - clients = append(clients, client) - } - require.True(t, failed, "should have failed to create more sessions than the max mysql connection") - - // Release all the sessions. - for _, client := range clients { - require.NoError(t, - client.Release()) - } - clients = nil - - // write session - failed = false - for i := 0; i < numOfSessions; i++ { - client := framework.NewClient() - _, err := client.ReserveBeginExecute("select 1", []string{"set sql_mode = ''"}, nil, nil) - if err != nil { - failed = true - require.Contains(t, err.Error(), "immediate error from server errorCode=1040 errorMsg=Too many connections") - break - } - require.NoError(t, - client.Commit()) - clients = append(clients, client) - } - require.True(t, failed, "should have failed to create more sessions than the max mysql connection") - - // Release all the sessions. - for _, client := range clients { - require.NoError(t, - client.Release()) - } -} - -func TestReserveQueryTimeout(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false - defer func() { - framework.Server.Config().EnableSettingsPool = true - }() - client := framework.NewClient() - - _, err := client.ReserveExecute("select sleep(19)", []string{"set sql_mode = ''"}, nil) - assert.NoError(t, err) - assert.NoError(t, - client.Release()) - - _, err = client.ReserveStreamExecute("select sleep(19)", []string{"set sql_mode = ''"}, nil) - assert.NoError(t, err) - assert.NoError(t, - client.Release()) -} - // TestReserveFlushTables checks that `flush table with read lock` works only with reserve api. func TestReserveFlushTables(t *testing.T) { client := framework.NewClient() diff --git a/go/vt/vttablet/endtoend/settings_test.go b/go/vt/vttablet/endtoend/settings_test.go index d0a3b4987dd..a459ad15844 100644 --- a/go/vt/vttablet/endtoend/settings_test.go +++ b/go/vt/vttablet/endtoend/settings_test.go @@ -355,21 +355,25 @@ func TestInfiniteSessions(t *testing.T) { } func TestSetQueriesMultipleWays(t *testing.T) { - framework.Server.Config().EnableSettingsPool = false client := framework.NewClient() defer client.Release() + client2 := framework.NewClient() + defer client2.Release() + + // This will not reserve the connection, instead use a connection from the pool and change settings. + // The connection will be stored with settings state in the pool _, err := client.ReserveExecute("select 1", []string{"set sql_safe_updates = 1"}, nil) require.NoError(t, err) - _, err = client.Execute("set sql_safe_updates = 1", nil) - require.NoError(t, err) + // As no connection is reserved, set statement will fail to execute. + _, err = client.Execute("set sql_safe_updates = 0", nil) + assert.ErrorContains(t, err, "Set not allowed without reserved connection") - framework.Server.Config().EnableSettingsPool = true - client2 := framework.NewClient() - _, err = client2.ReserveExecute("select 1", []string{"set sql_safe_updates = 1"}, nil) - require.NoError(t, err) + // This will reserve the connection as this is part of the query execution and not the pre-queries to Reserve API + _, err = client2.ReserveExecute("set sql_safe_updates = 1", nil, nil) + assert.NoError(t, err) - // this should not panic. - _, err = client.Execute("set sql_safe_updates = 1", nil) - require.NoError(t, err) + // This will not error out as it gets executed on the reserved connection, + _, err = client2.Execute("set sql_safe_updates = 0", nil) + assert.NoError(t, err) } diff --git a/go/vt/vttablet/endtoend/streamtimeout/healthstream_test.go b/go/vt/vttablet/endtoend/streamtimeout/healthstream_test.go deleted file mode 100644 index 9890efd427d..00000000000 --- a/go/vt/vttablet/endtoend/streamtimeout/healthstream_test.go +++ /dev/null @@ -1,99 +0,0 @@ -/* -Copyright 2023 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 streamtimeout - -import ( - "context" - "slices" - "testing" - "time" - - "github.com/stretchr/testify/require" - - "vitess.io/vitess/go/mysql" - querypb "vitess.io/vitess/go/vt/proto/query" - "vitess.io/vitess/go/vt/vttablet/endtoend/framework" -) - -// TestSchemaChangeTimedout ensures that the timeout functionality is working properly -// to prevent queries from hanging up and causing a mutex to be locked forever. -func TestSchemaChangeTimedout(t *testing.T) { - const TableName = "vitess_healthstream" - - client := framework.NewClient() - reloadEstimatedTime := 2 * time.Second - - err := cluster.SimulateMySQLHang() - require.NoError(t, err) - - defer cluster.StopSimulateMySQLHang() - - ch := make(chan []string, 100) - go func(ch chan []string) { - client.StreamHealth(func(response *querypb.StreamHealthResponse) error { - if response.RealtimeStats.TableSchemaChanged != nil { - ch <- response.RealtimeStats.TableSchemaChanged - } - return nil - }) - }(ch) - - // get a clean connection that skips toxyproxy to be able to change the schema in the underlying DB - cleanParams := cluster.MySQLCleanConnParams() - cleanConn, err := mysql.Connect(context.Background(), &cleanParams) - require.NoError(t, err) - defer cleanConn.Close() - - // change the schema to trigger the health_streamer to send a notification at a later time. - _, err = cleanConn.ExecuteFetch("create table "+TableName+"(id bigint primary key)", -1, false) - require.NoError(t, err) - - select { - case <-ch: // get the schema notification - t.Fatalf("received an schema change event from the HealthStreamer (is toxyproxy working?)") - case <-time.After(reloadEstimatedTime): - // Good, continue - } - - // We will wait for the health_streamer to attempt sending a notification. - // It's important to keep in mind that the total wait time after the simulation should be shorter than the reload timeout. - // This is because the query timeout triggers the *DBConn.Kill() method, which in turn holds the mutex lock on the health_streamer. - // Although not indefinitely, this can result in longer wait times. - // It's worth noting that the behavior of *DBConn.Kill() is outside the scope of this test. - reloadInterval := config.SignalSchemaChangeReloadInterval - time.Sleep(reloadInterval) - - // pause simulating the mysql stall to allow the health_streamer to resume. - err = cluster.PauseSimulateMySQLHang() - require.NoError(t, err) - - // wait for the health_streamer to complete retrying the notification. - reloadTimeout := config.SchemaChangeReloadTimeout - retryEstimatedTime := reloadTimeout + reloadInterval + reloadEstimatedTime - timeout := time.After(retryEstimatedTime) - for { - select { - case res := <-ch: // get the schema notification - if slices.Contains(res, TableName) { - return - } - case <-timeout: - t.Errorf("timed out even after the mysql hang was no longer simulated") - return - } - } -} diff --git a/go/vt/vttablet/endtoend/streamtimeout/main_test.go b/go/vt/vttablet/endtoend/streamtimeout/main_test.go deleted file mode 100644 index 0b2f37a987c..00000000000 --- a/go/vt/vttablet/endtoend/streamtimeout/main_test.go +++ /dev/null @@ -1,102 +0,0 @@ -/* -Copyright 2023 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. -*/ - -/* -All tests in this package come with toxiproxy in front of the MySQL server -*/ -package streamtimeout - -import ( - "context" - "flag" - "fmt" - "os" - "testing" - "time" - - "vitess.io/vitess/go/vt/vttablet/endtoend/framework" - "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" - "vitess.io/vitess/go/vt/vttest" - - vttestpb "vitess.io/vitess/go/vt/proto/vttest" -) - -var ( - cluster vttest.LocalCluster - config *tabletenv.TabletConfig -) - -func TestMain(m *testing.M) { - flag.Parse() // Do not remove this comment, import into google3 depends on it - tabletenv.Init() - - exitCode := func() int { - // Launch MySQL. - // We need a Keyspace in the topology, so the DbName is set. - // We need a Shard too, so the database 'vttest' is created. - cfg := vttest.Config{ - Topology: &vttestpb.VTTestTopology{ - Keyspaces: []*vttestpb.Keyspace{ - { - Name: "vttest", - Shards: []*vttestpb.Shard{ - { - Name: "0", - DbNameOverride: "vttest", - }, - }, - }, - }, - }, - OnlyMySQL: true, - Charset: "utf8mb4_general_ci", - } - - env, err := vttest.NewLocalTestEnv(0) - if err != nil { - fmt.Fprintf(os.Stderr, "%v", err) - return 1 - } - env.EnableToxiproxy = true - cluster = vttest.LocalCluster{ - Config: cfg, - Env: env, - } - if err := cluster.Setup(); err != nil { - fmt.Fprintf(os.Stderr, "could not launch mysql: %v\n", err) - return 1 - } - defer cluster.TearDown() - - connParams := cluster.MySQLConnParams() - connAppDebugParams := cluster.MySQLAppDebugConnParams() - config = tabletenv.NewDefaultConfig() - config.SchemaReloadInterval = (2 * time.Second) + (100 * time.Millisecond) - config.SchemaChangeReloadTimeout = 10 * time.Second - config.SignalWhenSchemaChange = true - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - err = framework.StartCustomServer(ctx, connParams, connAppDebugParams, cluster.DbName(), config) - if err != nil { - fmt.Fprintf(os.Stderr, "%v", err) - return 1 - } - defer framework.StopServer() - return m.Run() - }() - os.Exit(exitCode) -} diff --git a/go/vt/vttablet/endtoend/transaction_test.go b/go/vt/vttablet/endtoend/transaction_test.go index b15e73585ba..ad6ff558c40 100644 --- a/go/vt/vttablet/endtoend/transaction_test.go +++ b/go/vt/vttablet/endtoend/transaction_test.go @@ -540,7 +540,7 @@ func TestMMCommitFlow(t *testing.T) { info.TimeCreated = 0 wantInfo := &querypb.TransactionMetadata{ Dtid: "aa", - State: 2, + State: querypb.TransactionState_COMMIT, Participants: []*querypb.Target{{ Keyspace: "test1", Shard: "0", @@ -593,7 +593,7 @@ func TestMMRollbackFlow(t *testing.T) { info.TimeCreated = 0 wantInfo := &querypb.TransactionMetadata{ Dtid: "aa", - State: 3, + State: querypb.TransactionState_ROLLBACK, Participants: []*querypb.Target{{ Keyspace: "test1", Shard: "0", @@ -612,7 +612,43 @@ func TestMMRollbackFlow(t *testing.T) { require.NoError(t, err) } -func TestWatchdog(t *testing.T) { +type AsyncChecker struct { + t *testing.T + ch chan bool +} + +func newAsyncChecker(t *testing.T) *AsyncChecker { + return &AsyncChecker{ + t: t, + ch: make(chan bool), + } +} + +func (ac *AsyncChecker) check() { + ac.ch <- true +} + +func (ac *AsyncChecker) shouldNotify(timeout time.Duration, message string) { + select { + case <-ac.ch: + // notified, all is well + case <-time.After(timeout): + // timed out waiting for notification + ac.t.Error(message) + } +} +func (ac *AsyncChecker) shouldNotNotify(timeout time.Duration, message string) { + select { + case <-ac.ch: + // notified - not expected + ac.t.Error(message) + case <-time.After(timeout): + // timed out waiting for notification, which is expected + } +} + +// TestTransactionWatcherSignal test that unresolved transaction signal is received via health stream. +func TestTransactionWatcherSignal(t *testing.T) { client := framework.NewClient() query := "insert into vitess_test (intval, floatval, charval, binval) " + @@ -622,44 +658,38 @@ func TestWatchdog(t *testing.T) { _, err = client.Execute(query, nil) require.NoError(t, err) - start := time.Now() - err = client.CreateTransaction("aa", []*querypb.Target{{ - Keyspace: "test1", - Shard: "0", - }, { - Keyspace: "test2", - Shard: "1", - }}) + ch := newAsyncChecker(t) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + go func() { + err := client.StreamHealthWithContext(ctx, func(shr *querypb.StreamHealthResponse) error { + if shr.RealtimeStats.TxUnresolved { + ch.check() + } + return nil + }) + require.NoError(t, err) + }() + + err = client.CreateTransaction("aa", []*querypb.Target{ + {Keyspace: "test1", Shard: "0"}, + {Keyspace: "test2", Shard: "1"}}) require.NoError(t, err) - // The watchdog should kick in after 1 second. - dtid := <-framework.ResolveChan - if dtid != "aa" { - t.Errorf("dtid: %s, want aa", dtid) - } - diff := time.Since(start) - if diff < 1*time.Second { - t.Errorf("diff: %v, want greater than 1s", diff) - } + // wait for unresolved transaction signal + ch.shouldNotify(2*time.Second, "timed out waiting for transaction watcher signal") err = client.SetRollback("aa", 0) require.NoError(t, err) + + // still should receive unresolved transaction signal + ch.shouldNotify(2*time.Second, "timed out waiting for transaction watcher signal") + err = client.ConcludeTransaction("aa") require.NoError(t, err) - // Make sure the watchdog stops sending messages. - // Check twice. Sometimes, a race can still cause - // a stray message. - dtid = "" - for i := 0; i < 2; i++ { - select { - case dtid = <-framework.ResolveChan: - continue - case <-time.After(2 * time.Second): - return - } - } - t.Errorf("Unexpected message: %s", dtid) + // transaction watcher should stop sending singal now. + ch.shouldNotNotify(2*time.Second, "unexpected signal for resolved transaction") } func TestUnresolvedTracking(t *testing.T) { @@ -737,3 +767,95 @@ func TestManualTwopcz(t *testing.T) { fmt.Print("Sleeping for 30 seconds\n") time.Sleep(30 * time.Second) } + +// TestUnresolvedTransactions tests the UnresolvedTransactions API. +func TestUnresolvedTransactions(t *testing.T) { + client := framework.NewClient() + + participants := []*querypb.Target{ + {Keyspace: "ks1", Shard: "80-c0", TabletType: topodatapb.TabletType_PRIMARY}, + } + err := client.CreateTransaction("dtid01", participants) + require.NoError(t, err) + defer client.ConcludeTransaction("dtid01") + + // expected no transaction to show here, as 1 second not passed. + transactions, err := client.UnresolvedTransactions() + require.NoError(t, err) + require.Empty(t, transactions) + + // abandon age is 1 second. + time.Sleep(2 * time.Second) + + transactions, err = client.UnresolvedTransactions() + require.NoError(t, err) + want := []*querypb.TransactionMetadata{{ + Dtid: "dtid01", + State: querypb.TransactionState_PREPARE, + Participants: participants, + }} + utils.MustMatch(t, want, transactions) +} + +// TestUnresolvedTransactions tests the UnresolvedTransactions API. +func TestUnresolvedTransactionsOrdering(t *testing.T) { + client := framework.NewClient() + + participants1 := []*querypb.Target{ + {Keyspace: "ks1", Shard: "c0-", TabletType: topodatapb.TabletType_PRIMARY}, + {Keyspace: "ks1", Shard: "80-c0", TabletType: topodatapb.TabletType_PRIMARY}, + } + participants2 := []*querypb.Target{ + {Keyspace: "ks1", Shard: "-40", TabletType: topodatapb.TabletType_PRIMARY}, + {Keyspace: "ks1", Shard: "80-c0", TabletType: topodatapb.TabletType_PRIMARY}, + } + participants3 := []*querypb.Target{ + {Keyspace: "ks1", Shard: "c0-", TabletType: topodatapb.TabletType_PRIMARY}, + {Keyspace: "ks1", Shard: "-40", TabletType: topodatapb.TabletType_PRIMARY}, + } + // prepare state + err := client.CreateTransaction("dtid01", participants1) + require.NoError(t, err) + defer client.ConcludeTransaction("dtid01") + + // commit state + err = client.CreateTransaction("dtid02", participants2) + require.NoError(t, err) + defer client.ConcludeTransaction("dtid02") + _, err = client.Execute( + fmt.Sprintf("update _vt.dt_state set state = %d where dtid = 'dtid02'", querypb.TransactionState_COMMIT.Number()), nil) + require.NoError(t, err) + + // rollback state + err = client.CreateTransaction("dtid03", participants3) + require.NoError(t, err) + defer client.ConcludeTransaction("dtid03") + _, err = client.Execute( + fmt.Sprintf("update _vt.dt_state set state = %d where dtid = 'dtid03'", querypb.TransactionState_ROLLBACK.Number()), nil) + require.NoError(t, err) + + // expected no transaction to show here, as 1 second not passed. + transactions, err := client.UnresolvedTransactions() + require.NoError(t, err) + require.Empty(t, transactions) + + // abandon age is 1 second. + time.Sleep(2 * time.Second) + + transactions, err = client.UnresolvedTransactions() + require.NoError(t, err) + want := []*querypb.TransactionMetadata{{ + Dtid: "dtid02", + State: querypb.TransactionState_COMMIT, + Participants: participants2, + }, { + Dtid: "dtid03", + State: querypb.TransactionState_ROLLBACK, + Participants: participants3, + }, { + Dtid: "dtid01", + State: querypb.TransactionState_PREPARE, + Participants: participants1, + }} + utils.MustMatch(t, want, transactions) +} diff --git a/go/vt/vttablet/faketmclient/fake_client.go b/go/vt/vttablet/faketmclient/fake_client.go index f7ef32ce18f..3aeeff71e85 100644 --- a/go/vt/vttablet/faketmclient/fake_client.go +++ b/go/vt/vttablet/faketmclient/fake_client.go @@ -371,6 +371,10 @@ func (client *FakeTabletManagerClient) CheckThrottler(ctx context.Context, table return &tabletmanagerdatapb.CheckThrottlerResponse{}, nil } +func (client *FakeTabletManagerClient) GetThrottlerStatus(ctx context.Context, tablet *topodatapb.Tablet, request *tabletmanagerdatapb.GetThrottlerStatusRequest) (*tabletmanagerdatapb.GetThrottlerStatusResponse, error) { + return &tabletmanagerdatapb.GetThrottlerStatusResponse{}, nil +} + // // Management related methods // diff --git a/go/vt/vttablet/grpcqueryservice/server.go b/go/vt/vttablet/grpcqueryservice/server.go index 64a7697162d..c26d291aa50 100644 --- a/go/vt/vttablet/grpcqueryservice/server.go +++ b/go/vt/vttablet/grpcqueryservice/server.go @@ -233,6 +233,21 @@ func (q *query) ReadTransaction(ctx context.Context, request *querypb.ReadTransa return &querypb.ReadTransactionResponse{Metadata: result}, nil } +// UnresolvedTransactions is part of the queryservice.QueryServer interface +func (q *query) UnresolvedTransactions(ctx context.Context, request *querypb.UnresolvedTransactionsRequest) (response *querypb.UnresolvedTransactionsResponse, err error) { + defer q.server.HandlePanic(&err) + ctx = callerid.NewContext(callinfo.GRPCCallInfo(ctx), + request.EffectiveCallerId, + request.ImmediateCallerId, + ) + transactions, err := q.server.UnresolvedTransactions(ctx, request.Target) + if err != nil { + return nil, vterrors.ToGRPC(err) + } + + return &querypb.UnresolvedTransactionsResponse{Transactions: transactions}, nil +} + // BeginExecute is part of the queryservice.QueryServer interface func (q *query) BeginExecute(ctx context.Context, request *querypb.BeginExecuteRequest) (response *querypb.BeginExecuteResponse, err error) { defer q.server.HandlePanic(&err) diff --git a/go/vt/vttablet/grpctabletconn/conn.go b/go/vt/vttablet/grpctabletconn/conn.go index fe446fbec27..a76505383b7 100644 --- a/go/vt/vttablet/grpctabletconn/conn.go +++ b/go/vt/vttablet/grpctabletconn/conn.go @@ -438,6 +438,26 @@ func (conn *gRPCQueryClient) ReadTransaction(ctx context.Context, target *queryp return response.Metadata, nil } +// UnresolvedTransactions returns all unresolved distributed transactions. +func (conn *gRPCQueryClient) UnresolvedTransactions(ctx context.Context, target *querypb.Target) ([]*querypb.TransactionMetadata, error) { + conn.mu.RLock() + defer conn.mu.RUnlock() + if conn.cc == nil { + return nil, tabletconn.ConnClosed + } + + req := &querypb.UnresolvedTransactionsRequest{ + Target: target, + EffectiveCallerId: callerid.EffectiveCallerIDFromContext(ctx), + ImmediateCallerId: callerid.ImmediateCallerIDFromContext(ctx), + } + response, err := conn.c.UnresolvedTransactions(ctx, req) + if err != nil { + return nil, tabletconn.ErrorFromGRPC(err) + } + return response.Transactions, nil +} + // BeginExecute starts a transaction and runs an Execute. func (conn *gRPCQueryClient) BeginExecute(ctx context.Context, target *querypb.Target, preQueries []string, query string, bindVars map[string]*querypb.BindVariable, reservedID int64, options *querypb.ExecuteOptions) (state queryservice.TransactionState, result *sqltypes.Result, err error) { conn.mu.RLock() diff --git a/go/vt/vttablet/grpctmclient/client.go b/go/vt/vttablet/grpctmclient/client.go index 023622c6370..c3ff1b02767 100644 --- a/go/vt/vttablet/grpctmclient/client.go +++ b/go/vt/vttablet/grpctmclient/client.go @@ -1205,6 +1205,24 @@ func (client *Client) CheckThrottler(ctx context.Context, tablet *topodatapb.Tab return response, nil } +// GetThrottlerStatus is part of the tmclient.TabletManagerClient interface. +// It always tries to use a cached client via the dialer pool as this is +// called very frequently between tablets when the throttler is enabled in +// a keyspace and the overhead of creating a new gRPC connection/channel +// and dialing the other tablet every time is not practical. +func (client *Client) GetThrottlerStatus(ctx context.Context, tablet *topodatapb.Tablet, req *tabletmanagerdatapb.GetThrottlerStatusRequest) (*tabletmanagerdatapb.GetThrottlerStatusResponse, error) { + c, closer, err := client.dialer.dial(ctx, tablet) + if err != nil { + return nil, err + } + defer closer.Close() + response, err := c.GetThrottlerStatus(ctx, req) + if err != nil { + return nil, err + } + return response, nil +} + type restoreFromBackupStreamAdapter struct { stream tabletmanagerservicepb.TabletManager_RestoreFromBackupClient closer io.Closer diff --git a/go/vt/vttablet/grpctmclient/client_test.go b/go/vt/vttablet/grpctmclient/client_test.go index 1487303163d..2a5ae3ff6d0 100644 --- a/go/vt/vttablet/grpctmclient/client_test.go +++ b/go/vt/vttablet/grpctmclient/client_test.go @@ -76,10 +76,18 @@ func TestDialDedicatedPool(t *testing.T) { ctx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - req := &tabletmanagerdatapb.CheckThrottlerRequest{} + req := &tabletmanagerdatapb.CheckThrottlerRequest{MultiMetricsEnabled: true} _, err := client.CheckThrottler(ctx, tablet, req) assert.Error(t, err) }) + t.Run("GetThrottlerStatus", func(t *testing.T) { + ctx, cancel := context.WithTimeout(ctx, time.Second) + defer cancel() + + req := &tabletmanagerdatapb.GetThrottlerStatusRequest{} + _, err := client.GetThrottlerStatus(ctx, tablet, req) + assert.Error(t, err) + }) t.Run("empty map", func(t *testing.T) { rpcClient, ok := client.dialer.(*grpcClient) require.True(t, ok) @@ -133,7 +141,7 @@ func TestDialPool(t *testing.T) { ctx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - req := &tabletmanagerdatapb.CheckThrottlerRequest{} + req := &tabletmanagerdatapb.CheckThrottlerRequest{MultiMetricsEnabled: true} _, err := client.CheckThrottler(ctx, tablet, req) assert.Error(t, err) }) diff --git a/go/vt/vttablet/grpctmserver/server.go b/go/vt/vttablet/grpctmserver/server.go index 196f7a14882..42cfd441eeb 100644 --- a/go/vt/vttablet/grpctmserver/server.go +++ b/go/vt/vttablet/grpctmserver/server.go @@ -596,6 +596,13 @@ func (s *server) CheckThrottler(ctx context.Context, request *tabletmanagerdatap return response, err } +func (s *server) GetThrottlerStatus(ctx context.Context, request *tabletmanagerdatapb.GetThrottlerStatusRequest) (response *tabletmanagerdatapb.GetThrottlerStatusResponse, err error) { + defer s.tm.HandleRPCPanic(ctx, "GetThrottlerStatus", request, response, false /*verbose*/, &err) + ctx = callinfo.GRPCCallInfo(ctx) + response, err = s.tm.GetThrottlerStatus(ctx, request) + return response, err +} + // registration glue func init() { diff --git a/go/vt/vttablet/onlineddl/executor.go b/go/vt/vttablet/onlineddl/executor.go index 00998c453e1..1aa75907e88 100644 --- a/go/vt/vttablet/onlineddl/executor.go +++ b/go/vt/vttablet/onlineddl/executor.go @@ -3870,8 +3870,10 @@ func (e *Executor) reviewRunningMigrations(ctx context.Context) (countRunnning i _ = e.updateRowsCopied(ctx, uuid, s.rowsCopied) _ = e.updateMigrationProgressByRowsCopied(ctx, uuid, s.rowsCopied) _ = e.updateMigrationETASecondsByProgress(ctx, uuid) - _ = e.updateMigrationLastThrottled(ctx, uuid, time.Unix(s.timeThrottled, 0), s.componentThrottled) - + if s.timeThrottled != 0 { + // Avoid creating a 0000-00-00 00:00:00 timestamp + _ = e.updateMigrationLastThrottled(ctx, uuid, time.Unix(s.timeThrottled, 0), s.componentThrottled) + } if onlineDDL.StrategySetting().IsInOrderCompletion() { // We will fail an in-order migration if there's _prior_ migrations within the same migration-context // which have failed. @@ -4758,6 +4760,26 @@ func (e *Executor) CleanupMigration(ctx context.Context, uuid string) (result *s return rs, nil } +// CleanupMigration sets migration is ready for artifact cleanup. Artifacts are not immediately deleted: +// all we do is set retain_artifacts_seconds to a very small number (it's actually a negative) so that the +// next iteration of gcArtifacts() picks up the migration's artifacts and schedules them for deletion +func (e *Executor) CleanupAllMigrations(ctx context.Context) (result *sqltypes.Result, err error) { + if atomic.LoadInt64(&e.isOpen) == 0 { + return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, schema.ErrOnlineDDLDisabled.Error()) + } + log.Infof("CleanupMigration: request to cleanup all terminal migrations") + e.migrationMutex.Lock() + defer e.migrationMutex.Unlock() + + rs, err := e.execQuery(ctx, sqlUpdateReadyForCleanupAll) + if err != nil { + return nil, err + } + log.Infof("CleanupMigration: %v migrations marked as ready to clean up", rs.RowsAffected) + defer e.triggerNextCheckInterval() + return rs, nil +} + // ForceCutOverMigration markes the given migration for forced cut-over. This has two implications: // - No backoff for the given migration's cut-over (cut-over will be attempted at the next scheduler cycle, // irrespective of how many cut-over attempts have been made and when these attempts have been made). diff --git a/go/vt/vttablet/onlineddl/schema.go b/go/vt/vttablet/onlineddl/schema.go index 30f132bd0e3..7ff1cd220d6 100644 --- a/go/vt/vttablet/onlineddl/schema.go +++ b/go/vt/vttablet/onlineddl/schema.go @@ -169,6 +169,13 @@ const ( WHERE migration_uuid=%a ` + sqlUpdateReadyForCleanupAll = `UPDATE _vt.schema_migrations + SET retain_artifacts_seconds=-1 + WHERE + migration_status IN ('complete', 'cancelled', 'failed') + AND cleanup_timestamp IS NULL + AND retain_artifacts_seconds > 0 + ` sqlUpdateForceCutOver = `UPDATE _vt.schema_migrations SET force_cutover=1 WHERE diff --git a/go/vt/vttablet/queryservice/queryservice.go b/go/vt/vttablet/queryservice/queryservice.go index c4d72b0c927..10cf48fd8b1 100644 --- a/go/vt/vttablet/queryservice/queryservice.go +++ b/go/vt/vttablet/queryservice/queryservice.go @@ -76,6 +76,9 @@ type QueryService interface { // ReadTransaction returns the metadata for the specified dtid. ReadTransaction(ctx context.Context, target *querypb.Target, dtid string) (metadata *querypb.TransactionMetadata, err error) + // UnresolvedTransactions returns the list of unresolved distributed transactions. + UnresolvedTransactions(ctx context.Context, target *querypb.Target) ([]*querypb.TransactionMetadata, error) + // Execute for query execution Execute(ctx context.Context, target *querypb.Target, sql string, bindVariables map[string]*querypb.BindVariable, transactionID, reservedID int64, options *querypb.ExecuteOptions) (*sqltypes.Result, error) // StreamExecute for query execution with streaming diff --git a/go/vt/vttablet/queryservice/wrapped.go b/go/vt/vttablet/queryservice/wrapped.go index 910a1d8948e..d24bd051c4a 100644 --- a/go/vt/vttablet/queryservice/wrapped.go +++ b/go/vt/vttablet/queryservice/wrapped.go @@ -176,6 +176,15 @@ func (ws *wrappedService) ReadTransaction(ctx context.Context, target *querypb.T return metadata, err } +func (ws *wrappedService) UnresolvedTransactions(ctx context.Context, target *querypb.Target) (transactions []*querypb.TransactionMetadata, err error) { + err = ws.wrapper(ctx, target, ws.impl, "UnresolvedTransactions", false, func(ctx context.Context, target *querypb.Target, conn QueryService) (bool, error) { + var innerErr error + transactions, innerErr = conn.UnresolvedTransactions(ctx, target) + return canRetry(ctx, innerErr), innerErr + }) + return transactions, err +} + func (ws *wrappedService) Execute(ctx context.Context, target *querypb.Target, query string, bindVars map[string]*querypb.BindVariable, transactionID, reservedID int64, options *querypb.ExecuteOptions) (qr *sqltypes.Result, err error) { inDedicatedConn := transactionID != 0 || reservedID != 0 err = ws.wrapper(ctx, target, ws.impl, "Execute", inDedicatedConn, func(ctx context.Context, target *querypb.Target, conn QueryService) (bool, error) { diff --git a/go/vt/vttablet/sandboxconn/sandboxconn.go b/go/vt/vttablet/sandboxconn/sandboxconn.go index 618a87b1d81..3c7f4c8c445 100644 --- a/go/vt/vttablet/sandboxconn/sandboxconn.go +++ b/go/vt/vttablet/sandboxconn/sandboxconn.go @@ -26,17 +26,15 @@ import ( "time" "vitess.io/vitess/go/mysql/collations" - "vitess.io/vitess/go/vt/log" - "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/sqltypes" - "vitess.io/vitess/go/vt/vterrors" - "vitess.io/vitess/go/vt/vttablet/queryservice" - + "vitess.io/vitess/go/vt/log" binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" querypb "vitess.io/vitess/go/vt/proto/query" topodatapb "vitess.io/vitess/go/vt/proto/topodata" vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" + "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/vt/vttablet/queryservice" ) // SandboxConn satisfies the QueryService interface @@ -65,22 +63,23 @@ type SandboxConn struct { // These Count vars report how often the corresponding // functions were called. - ExecCount atomic.Int64 - BeginCount atomic.Int64 - CommitCount atomic.Int64 - RollbackCount atomic.Int64 - AsTransactionCount atomic.Int64 - PrepareCount atomic.Int64 - CommitPreparedCount atomic.Int64 - RollbackPreparedCount atomic.Int64 - CreateTransactionCount atomic.Int64 - StartCommitCount atomic.Int64 - SetRollbackCount atomic.Int64 - ConcludeTransactionCount atomic.Int64 - ReadTransactionCount atomic.Int64 - ReserveCount atomic.Int64 - ReleaseCount atomic.Int64 - GetSchemaCount atomic.Int64 + ExecCount atomic.Int64 + BeginCount atomic.Int64 + CommitCount atomic.Int64 + RollbackCount atomic.Int64 + AsTransactionCount atomic.Int64 + PrepareCount atomic.Int64 + CommitPreparedCount atomic.Int64 + RollbackPreparedCount atomic.Int64 + CreateTransactionCount atomic.Int64 + StartCommitCount atomic.Int64 + SetRollbackCount atomic.Int64 + ConcludeTransactionCount atomic.Int64 + ReadTransactionCount atomic.Int64 + UnresolvedTransactionsCount atomic.Int64 + ReserveCount atomic.Int64 + ReleaseCount atomic.Int64 + GetSchemaCount atomic.Int64 queriesRequireLocking bool queriesMu sync.Mutex @@ -102,6 +101,9 @@ type SandboxConn struct { // ReadTransactionResults is used for returning results for ReadTransaction. ReadTransactionResults []*querypb.TransactionMetadata + // UnresolvedTransactionsResult is used for returning results for UnresolvedTransactions. + UnresolvedTransactionsResult []*querypb.TransactionMetadata + MessageIDs []*querypb.Value // vstream expectations. @@ -427,6 +429,15 @@ func (sbc *SandboxConn) ReadTransaction(ctx context.Context, target *querypb.Tar return nil, nil } +// UnresolvedTransactions is part of the QueryService interface. +func (sbc *SandboxConn) UnresolvedTransactions(context.Context, *querypb.Target) ([]*querypb.TransactionMetadata, error) { + sbc.UnresolvedTransactionsCount.Add(1) + if err := sbc.getError(); err != nil { + return nil, err + } + return sbc.UnresolvedTransactionsResult, nil +} + // BeginExecute is part of the QueryService interface. func (sbc *SandboxConn) BeginExecute(ctx context.Context, target *querypb.Target, preQueries []string, query string, bindVars map[string]*querypb.BindVariable, reservedID int64, options *querypb.ExecuteOptions) (queryservice.TransactionState, *sqltypes.Result, error) { sbc.panicIfNeeded() diff --git a/go/vt/vttablet/tabletconntest/fakequeryservice.go b/go/vt/vttablet/tabletconntest/fakequeryservice.go index 2efd7d330ed..54deee1aed7 100644 --- a/go/vt/vttablet/tabletconntest/fakequeryservice.go +++ b/go/vt/vttablet/tabletconntest/fakequeryservice.go @@ -359,6 +359,18 @@ func (f *FakeQueryService) ReadTransaction(ctx context.Context, target *querypb. return Metadata, nil } +// UnresolvedTransactions is part of the queryservice.QueryService interface +func (f *FakeQueryService) UnresolvedTransactions(ctx context.Context, target *querypb.Target) ([]*querypb.TransactionMetadata, error) { + if f.HasError { + return nil, f.TabletError + } + if f.Panics { + panic(fmt.Errorf("test-triggered panic")) + } + f.checkTargetCallerID(ctx, "UnresolvedTransactions", target) + return []*querypb.TransactionMetadata{Metadata}, nil +} + // ExecuteQuery is a fake test query. const ExecuteQuery = "executeQuery" diff --git a/go/vt/vttablet/tabletconntest/tabletconntest.go b/go/vt/vttablet/tabletconntest/tabletconntest.go index f8dafb0636e..0f443d8d58d 100644 --- a/go/vt/vttablet/tabletconntest/tabletconntest.go +++ b/go/vt/vttablet/tabletconntest/tabletconntest.go @@ -399,6 +399,33 @@ func testReadTransactionPanics(t *testing.T, conn queryservice.QueryService, f * }) } +func testUnresolvedTransactions(t *testing.T, conn queryservice.QueryService, f *FakeQueryService) { + t.Log("testUnresolvedTransactions") + ctx := context.Background() + ctx = callerid.NewContext(ctx, TestCallerID, TestVTGateCallerID) + transactions, err := conn.UnresolvedTransactions(ctx, TestTarget) + require.NoError(t, err) + require.True(t, proto.Equal(transactions[0], Metadata)) +} + +func testUnresolvedTransactionsError(t *testing.T, conn queryservice.QueryService, f *FakeQueryService) { + t.Log("testUnresolvedTransactionsError") + f.HasError = true + testErrorHelper(t, f, "UnresolvedTransactions", func(ctx context.Context) error { + _, err := conn.UnresolvedTransactions(ctx, TestTarget) + return err + }) + f.HasError = false +} + +func testUnresolvedTransactionsPanics(t *testing.T, conn queryservice.QueryService, f *FakeQueryService) { + t.Log("testUnresolvedTransactionsPanics") + testPanicHelper(t, f, "UnresolvedTransactions", func(ctx context.Context) error { + _, err := conn.UnresolvedTransactions(ctx, TestTarget) + return err + }) +} + func testExecute(t *testing.T, conn queryservice.QueryService, f *FakeQueryService) { t.Log("testExecute") f.ExpectedTransactionID = ExecuteTransactionID @@ -936,6 +963,7 @@ func TestSuite(ctx context.Context, t *testing.T, protocol string, tablet *topod testSetRollback, testConcludeTransaction, testReadTransaction, + testUnresolvedTransactions, testExecute, testBeginExecute, testStreamExecute, @@ -956,6 +984,7 @@ func TestSuite(ctx context.Context, t *testing.T, protocol string, tablet *topod testSetRollbackError, testConcludeTransactionError, testReadTransactionError, + testUnresolvedTransactionsError, testExecuteError, testBeginExecuteErrorInBegin, testBeginExecuteErrorInExecute, @@ -979,6 +1008,7 @@ func TestSuite(ctx context.Context, t *testing.T, protocol string, tablet *topod testSetRollbackPanics, testConcludeTransactionPanics, testReadTransactionPanics, + testUnresolvedTransactionsPanics, testExecutePanics, testBeginExecutePanics, testStreamExecutePanics, diff --git a/go/vt/vttablet/tabletmanager/rpc_agent.go b/go/vt/vttablet/tabletmanager/rpc_agent.go index da70dd9adde..6dd21a21915 100644 --- a/go/vt/vttablet/tabletmanager/rpc_agent.go +++ b/go/vt/vttablet/tabletmanager/rpc_agent.go @@ -156,4 +156,5 @@ type RPCTM interface { // Throttler CheckThrottler(ctx context.Context, request *tabletmanagerdatapb.CheckThrottlerRequest) (*tabletmanagerdatapb.CheckThrottlerResponse, error) + GetThrottlerStatus(ctx context.Context, request *tabletmanagerdatapb.GetThrottlerStatusRequest) (*tabletmanagerdatapb.GetThrottlerStatusResponse, error) } diff --git a/go/vt/vttablet/tabletmanager/rpc_throttler.go b/go/vt/vttablet/tabletmanager/rpc_throttler.go index ab153b3ef43..8ec3bb592da 100644 --- a/go/vt/vttablet/tabletmanager/rpc_throttler.go +++ b/go/vt/vttablet/tabletmanager/rpc_throttler.go @@ -19,22 +19,34 @@ package tabletmanager import ( "context" + "vitess.io/vitess/go/protoutil" "vitess.io/vitess/go/stats" tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" "vitess.io/vitess/go/vt/proto/vtrpc" + "vitess.io/vitess/go/vt/topo/topoproto" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle" + "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/throttlerapp" ) +var ( + statsThrottlerCheckRequests = stats.NewCounter("ThrottlerCheckRequest", "CheckThrottler requests") + statsThrottlerStatusRequests = stats.NewCounter("GetThrottlerStatusRequest", "GetThrottlerStatus requests") +) + // CheckThrottler executes a throttler check func (tm *TabletManager) CheckThrottler(ctx context.Context, req *tabletmanagerdatapb.CheckThrottlerRequest) (*tabletmanagerdatapb.CheckThrottlerResponse, error) { - go stats.GetOrNewCounter("ThrottlerCheckRequest", "CheckThrottler requests").Add(1) + statsThrottlerCheckRequests.Add(1) if req.AppName == "" { req.AppName = throttlerapp.VitessName.String() } flags := &throttle.CheckFlags{ - SkipRequestHeartbeats: true, + Scope: base.Scope(req.Scope), + SkipRequestHeartbeats: req.SkipRequestHeartbeats, + OKIfNotExists: req.OkIfNotExists, + MultiMetricsEnabled: req.MultiMetricsEnabled, } checkResult := tm.QueryServiceControl.CheckThrottler(ctx, req.AppName, flags) if checkResult == nil { @@ -46,9 +58,89 @@ func (tm *TabletManager) CheckThrottler(ctx context.Context, req *tabletmanagerd Threshold: checkResult.Threshold, Message: checkResult.Message, RecentlyChecked: checkResult.RecentlyChecked, + Metrics: make(map[string]*tabletmanagerdatapb.CheckThrottlerResponse_Metric), + } + for name, metric := range checkResult.Metrics { + resp.Metrics[name] = &tabletmanagerdatapb.CheckThrottlerResponse_Metric{ + Name: name, + Scope: metric.Scope, + StatusCode: int32(metric.StatusCode), + Value: metric.Value, + Threshold: metric.Threshold, + Message: metric.Message, + } + } + if len(checkResult.Metrics) == 0 { + // For backwards compatibility, when the checked tablet is of lower version, it does not return a + // matrics map, but only the one metric. + resp.Metrics[base.DefaultMetricName.String()] = &tabletmanagerdatapb.CheckThrottlerResponse_Metric{ + StatusCode: int32(checkResult.StatusCode), + Value: checkResult.Value, + Threshold: checkResult.Threshold, + Message: checkResult.Message, + } } if checkResult.Error != nil { resp.Error = checkResult.Error.Error() } return resp, nil } + +// GetThrottlerStatus returns a detailed breakdown of the throttler status +func (tm *TabletManager) GetThrottlerStatus(ctx context.Context, req *tabletmanagerdatapb.GetThrottlerStatusRequest) (*tabletmanagerdatapb.GetThrottlerStatusResponse, error) { + statsThrottlerStatusRequests.Add(1) + status := tm.QueryServiceControl.GetThrottlerStatus(ctx) + if status == nil { + return nil, vterrors.Errorf(vtrpc.Code_INTERNAL, "nil status") + } + resp := &tabletmanagerdatapb.GetThrottlerStatusResponse{ + TabletAlias: topoproto.TabletAliasString(tm.Tablet().Alias), + Keyspace: status.Keyspace, + Shard: status.Shard, + IsLeader: status.IsLeader, + IsOpen: status.IsOpen, + IsEnabled: status.IsEnabled, + IsDormant: status.IsDormant, + RecentlyChecked: status.RecentlyChecked, + LagMetricQuery: status.Query, + CustomMetricQuery: status.CustomQuery, + DefaultThreshold: status.Threshold, + MetricNameUsedAsDefault: status.MetricNameUsedAsDefault, + AggregatedMetrics: make(map[string]*tabletmanagerdatapb.GetThrottlerStatusResponse_MetricResult), + MetricThresholds: status.MetricsThresholds, + MetricsHealth: make(map[string]*tabletmanagerdatapb.GetThrottlerStatusResponse_MetricHealth), + ThrottledApps: make(map[string]*topodatapb.ThrottledAppRule), + AppCheckedMetrics: status.AppCheckedMetrics, + RecentApps: make(map[string]*tabletmanagerdatapb.GetThrottlerStatusResponse_RecentApp), + } + for k, m := range status.AggregatedMetrics { + val, err := m.Get() + resp.AggregatedMetrics[k] = &tabletmanagerdatapb.GetThrottlerStatusResponse_MetricResult{ + Value: val, + } + if err != nil { + resp.AggregatedMetrics[k].Error = err.Error() + } + } + for k, m := range status.MetricsHealth { + resp.MetricsHealth[k] = &tabletmanagerdatapb.GetThrottlerStatusResponse_MetricHealth{ + LastHealthyAt: protoutil.TimeToProto(m.LastHealthyAt), + SecondsSinceLastHealthy: m.SecondsSinceLastHealthy, + } + } + for _, app := range status.ThrottledApps { + resp.ThrottledApps[app.AppName] = &topodatapb.ThrottledAppRule{ + Name: app.AppName, + Ratio: app.Ratio, + ExpiresAt: protoutil.TimeToProto(app.ExpireAt), + Exempt: app.Exempt, + } + } + for _, recentApp := range status.RecentApps { + resp.RecentApps[recentApp.AppName] = &tabletmanagerdatapb.GetThrottlerStatusResponse_RecentApp{ + CheckedAt: protoutil.TimeToProto(recentApp.CheckedAt), + StatusCode: int32(recentApp.StatusCode), + } + } + return resp, nil +} diff --git a/go/vt/vttablet/tabletmanager/rpc_vreplication_test.go b/go/vt/vttablet/tabletmanager/rpc_vreplication_test.go index f1211c87c8f..7ab959c1e17 100644 --- a/go/vt/vttablet/tabletmanager/rpc_vreplication_test.go +++ b/go/vt/vttablet/tabletmanager/rpc_vreplication_test.go @@ -71,7 +71,7 @@ const ( getMaxValForSequence = "select max(`id`) as maxval from `vt_%s`.`%s`" initSequenceTable = "insert into %a.%a (id, next_id, cache) values (0, %d, 1000) on duplicate key update next_id = if(next_id < %d, %d, next_id)" deleteWorkflow = "delete from _vt.vreplication where db_name = 'vt_%s' and workflow = '%s'" - updatePickedSourceTablet = `update _vt.vreplication set message='Picked source tablet: cell:\"%s\" uid:%d' where id=%d` + updatePickedSourceTablet = `update _vt.vreplication set message='Picked source tablet: cell:"%s" uid:%d' where id=%d` getRowsCopied = "SELECT rows_copied FROM _vt.vreplication WHERE id=%d" hasWorkflows = "select if(count(*) > 0, 1, 0) as has_workflows from _vt.vreplication where db_name = '%s'" 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 group by workflow, id order by workflow, id" @@ -135,7 +135,7 @@ func TestCreateVReplicationWorkflow(t *testing.T) { Cells: tenv.cells, AllTables: true, }, - query: fmt.Sprintf(`%s values ('%s', 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"t1\" filter:\"select * from t1\"}}', '', 0, 0, '%s', '', now(), 0, 'Stopped', '%s', 1, 0, 0, '{}')`, + query: fmt.Sprintf(`%s values ('%s', 'keyspace:"%s" shard:"%s" filter:{rules:{match:"t1" filter:"select * from t1"}}', '', 0, 0, '%s', '', now(), 0, 'Stopped', '%s', 1, 0, 0, '{}')`, insertVReplicationPrefix, wf, sourceKs, shard, tenv.cells[0], tenv.dbName), }, { @@ -170,7 +170,7 @@ func TestCreateVReplicationWorkflow(t *testing.T) { DeferSecondaryKeys: true, AutoStart: true, }, - query: fmt.Sprintf(`%s values ('%s', 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"t1\" filter:\"select * from t1\"}} on_ddl:EXEC stop_after_copy:true source_time_zone:\"EDT\" target_time_zone:\"UTC\"', '', 0, 0, '%s', '', now(), 0, 'Stopped', '%s', 1, 0, 1, '{}')`, + query: fmt.Sprintf(`%s values ('%s', 'keyspace:"%s" shard:"%s" filter:{rules:{match:"t1" filter:"select * from t1"}} on_ddl:EXEC stop_after_copy:true source_time_zone:"EDT" target_time_zone:"UTC"', '', 0, 0, '%s', '', now(), 0, 'Stopped', '%s', 1, 0, 1, '{}')`, insertVReplicationPrefix, wf, sourceKs, shard, tenv.cells[0], tenv.dbName), }, { @@ -210,7 +210,7 @@ func TestCreateVReplicationWorkflow(t *testing.T) { DeferSecondaryKeys: true, AutoStart: true, }, - query: fmt.Sprintf(`%s values ('%s', 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"t1\" filter:\"select * from t1\"} rules:{match:\"wut\" filter:\"select * from wut\"} rules:{match:\"zt\" filter:\"select * from zt\"}} on_ddl:EXEC stop_after_copy:true source_time_zone:\"EDT\" target_time_zone:\"UTC\"', '', 0, 0, '%s', '', now(), 0, 'Stopped', '%s', 1, 0, 1, '{}')`, + query: fmt.Sprintf(`%s values ('%s', 'keyspace:"%s" shard:"%s" filter:{rules:{match:"t1" filter:"select * from t1"} rules:{match:"wut" filter:"select * from wut"} rules:{match:"zt" filter:"select * from zt"}} on_ddl:EXEC stop_after_copy:true source_time_zone:"EDT" target_time_zone:"UTC"', '', 0, 0, '%s', '', now(), 0, 'Stopped', '%s', 1, 0, 1, '{}')`, insertVReplicationPrefix, wf, sourceKs, shard, tenv.cells[0], tenv.dbName), }, { @@ -250,7 +250,7 @@ func TestCreateVReplicationWorkflow(t *testing.T) { DeferSecondaryKeys: true, AutoStart: true, }, - query: fmt.Sprintf(`%s values ('%s', 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"t1\" filter:\"select * from t1\"} rules:{match:\"wut\" filter:\"select * from wut\"} rules:{match:\"zt\" filter:\"select * from zt\"}} on_ddl:EXEC stop_after_copy:true source_time_zone:\"EDT\" target_time_zone:\"UTC\"', '', 0, 0, '%s', '', now(), 0, 'Stopped', '%s', 1, 0, 1, '{}')`, + query: fmt.Sprintf(`%s values ('%s', 'keyspace:"%s" shard:"%s" filter:{rules:{match:"t1" filter:"select * from t1"} rules:{match:"wut" filter:"select * from wut"} rules:{match:"zt" filter:"select * from zt"}} on_ddl:EXEC stop_after_copy:true source_time_zone:"EDT" target_time_zone:"UTC"', '', 0, 0, '%s', '', now(), 0, 'Stopped', '%s', 1, 0, 1, '{}')`, insertVReplicationPrefix, wf, sourceKs, shard, tenv.cells[0], tenv.dbName), }, } @@ -394,7 +394,7 @@ func TestMoveTables(t *testing.T) { ftc.vrdbClient.AddInvariant(getCopyStateQuery, &sqltypes.Result{}) tenv.tmc.setVReplicationExecResults(ftc.tablet, getCopyState, &sqltypes.Result{}) ftc.vrdbClient.ExpectRequest(fmt.Sprintf(readAllWorkflows, tenv.dbName, ""), &sqltypes.Result{}, nil) - insert := fmt.Sprintf(`%s values ('%s', 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"t1\" filter:\"select * from t1 where in_keyrange(id, \'%s.hash\', \'%s\')\"}}', '', 0, 0, '%s', 'primary,replica,rdonly', now(), 0, 'Stopped', '%s', %d, 0, 0, '{}')`, + insert := fmt.Sprintf(`%s values ('%s', 'keyspace:"%s" shard:"%s" filter:{rules:{match:"t1" filter:"select * from t1 where in_keyrange(id, \'%s.hash\', \'%s\')"}}', '', 0, 0, '%s', 'primary,replica,rdonly', now(), 0, 'Stopped', '%s', %d, 0, 0, '{}')`, insertVReplicationPrefix, wf, sourceKs, sourceShard, targetKs, ftc.tablet.Shard, tenv.cells[0], tenv.dbName, vreplID) ftc.vrdbClient.ExpectRequest(insert, &sqltypes.Result{InsertID: 1}, nil) ftc.vrdbClient.ExpectRequest(getAutoIncrementStep, &sqltypes.Result{}, nil) @@ -428,7 +428,7 @@ func TestMoveTables(t *testing.T) { fmt.Sprintf("%d|%s|||Stopped|", vreplID, bls), ), nil) ftc.vrdbClient.ExpectRequest(idQuery, idRes, nil) - ftc.vrdbClient.ExpectRequest(fmt.Sprintf(updateWorkflow, binlogdatapb.VReplicationWorkflowState_Running.String(), strings.Replace(bls, `"`, `\"`, -1), "", "", vreplID), &sqltypes.Result{}, nil) + ftc.vrdbClient.ExpectRequest(fmt.Sprintf(updateWorkflow, binlogdatapb.VReplicationWorkflowState_Running.String(), bls, "", "", vreplID), &sqltypes.Result{}, nil) ftc.vrdbClient.ExpectRequest(fmt.Sprintf(getVReplicationRecord, vreplID), sqltypes.MakeTestResult( sqltypes.MakeTestFields( @@ -609,7 +609,7 @@ func TestUpdateVReplicationWorkflow(t *testing.T) { Cells: []string{"zone2"}, // TabletTypes is an empty value, so the current value should be cleared }, - query: fmt.Sprintf(`update _vt.vreplication set state = 'Running', source = 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"corder\" filter:\"select * from corder\"} rules:{match:\"customer\" filter:\"select * from customer\"}}', cell = '%s', tablet_types = '' where id in (%d)`, + query: fmt.Sprintf(`update _vt.vreplication set state = 'Running', source = 'keyspace:"%s" shard:"%s" filter:{rules:{match:"corder" filter:"select * from corder"} rules:{match:"customer" filter:"select * from customer"}}', cell = '%s', tablet_types = '' where id in (%d)`, keyspace, shard, "zone2", vreplID), }, { @@ -620,7 +620,7 @@ func TestUpdateVReplicationWorkflow(t *testing.T) { Cells: []string{"zone3"}, TabletTypes: []topodatapb.TabletType{topodatapb.TabletType(textutil.SimulatedNullInt)}, // So keep the current value of replica }, - query: fmt.Sprintf(`update _vt.vreplication set state = 'Running', source = 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"corder\" filter:\"select * from corder\"} rules:{match:\"customer\" filter:\"select * from customer\"}}', cell = '%s', tablet_types = '%s' where id in (%d)`, + query: fmt.Sprintf(`update _vt.vreplication set state = 'Running', source = 'keyspace:"%s" shard:"%s" filter:{rules:{match:"corder" filter:"select * from corder"} rules:{match:"customer" filter:"select * from customer"}}', cell = '%s', tablet_types = '%s' where id in (%d)`, keyspace, shard, "zone3", tabletTypes[0], vreplID), }, { @@ -631,7 +631,7 @@ func TestUpdateVReplicationWorkflow(t *testing.T) { TabletSelectionPreference: tabletmanagerdatapb.TabletSelectionPreference_INORDER, TabletTypes: []topodatapb.TabletType{topodatapb.TabletType_RDONLY, topodatapb.TabletType_REPLICA}, }, - query: fmt.Sprintf(`update _vt.vreplication set state = 'Running', source = 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"corder\" filter:\"select * from corder\"} rules:{match:\"customer\" filter:\"select * from customer\"}}', cell = '', tablet_types = '%s' where id in (%d)`, + query: fmt.Sprintf(`update _vt.vreplication set state = 'Running', source = 'keyspace:"%s" shard:"%s" filter:{rules:{match:"corder" filter:"select * from corder"} rules:{match:"customer" filter:"select * from customer"}}', cell = '', tablet_types = '%s' where id in (%d)`, keyspace, shard, "in_order:rdonly,replica", vreplID), }, { @@ -642,7 +642,7 @@ func TestUpdateVReplicationWorkflow(t *testing.T) { Cells: textutil.SimulatedNullStringSlice, // So keep the current value of zone1 TabletTypes: []topodatapb.TabletType{topodatapb.TabletType_RDONLY}, }, - query: fmt.Sprintf(`update _vt.vreplication set state = 'Running', source = 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"corder\" filter:\"select * from corder\"} rules:{match:\"customer\" filter:\"select * from customer\"}}', cell = '%s', tablet_types = '%s' where id in (%d)`, + query: fmt.Sprintf(`update _vt.vreplication set state = 'Running', source = 'keyspace:"%s" shard:"%s" filter:{rules:{match:"corder" filter:"select * from corder"} rules:{match:"customer" filter:"select * from customer"}}', cell = '%s', tablet_types = '%s' where id in (%d)`, keyspace, shard, cells[0], "rdonly", vreplID), }, { @@ -652,7 +652,7 @@ func TestUpdateVReplicationWorkflow(t *testing.T) { State: binlogdatapb.VReplicationWorkflowState(textutil.SimulatedNullInt), OnDdl: binlogdatapb.OnDDLAction_EXEC, }, - query: fmt.Sprintf(`update _vt.vreplication set state = 'Running', source = 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"corder\" filter:\"select * from corder\"} rules:{match:\"customer\" filter:\"select * from customer\"}} on_ddl:%s', cell = '', tablet_types = '' where id in (%d)`, + query: fmt.Sprintf(`update _vt.vreplication set state = 'Running', source = 'keyspace:"%s" shard:"%s" filter:{rules:{match:"corder" filter:"select * from corder"} rules:{match:"customer" filter:"select * from customer"}} on_ddl:%s', cell = '', tablet_types = '' where id in (%d)`, keyspace, shard, binlogdatapb.OnDDLAction_EXEC.String(), vreplID), }, { @@ -664,7 +664,7 @@ func TestUpdateVReplicationWorkflow(t *testing.T) { TabletTypes: []topodatapb.TabletType{topodatapb.TabletType_RDONLY, topodatapb.TabletType_REPLICA, topodatapb.TabletType_PRIMARY}, OnDdl: binlogdatapb.OnDDLAction_EXEC_IGNORE, }, - query: fmt.Sprintf(`update _vt.vreplication set state = 'Running', source = 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"corder\" filter:\"select * from corder\"} rules:{match:\"customer\" filter:\"select * from customer\"}} on_ddl:%s', cell = '%s', tablet_types = '%s' where id in (%d)`, + query: fmt.Sprintf(`update _vt.vreplication set state = 'Running', source = 'keyspace:"%s" shard:"%s" filter:{rules:{match:"corder" filter:"select * from corder"} rules:{match:"customer" filter:"select * from customer"}} on_ddl:%s', cell = '%s', tablet_types = '%s' where id in (%d)`, keyspace, shard, binlogdatapb.OnDDLAction_EXEC_IGNORE.String(), "zone1,zone2,zone3", "rdonly,replica,primary", vreplID), }, { @@ -676,7 +676,7 @@ func TestUpdateVReplicationWorkflow(t *testing.T) { TabletTypes: []topodatapb.TabletType{topodatapb.TabletType(textutil.SimulatedNullInt)}, OnDdl: binlogdatapb.OnDDLAction(textutil.SimulatedNullInt), }, - query: fmt.Sprintf(`update _vt.vreplication set state = '%s', source = 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"corder\" filter:\"select * from corder\"} rules:{match:\"customer\" filter:\"select * from customer\"}}', cell = '%s', tablet_types = '%s' where id in (%d)`, + query: fmt.Sprintf(`update _vt.vreplication set state = '%s', source = 'keyspace:"%s" shard:"%s" filter:{rules:{match:"corder" filter:"select * from corder"} rules:{match:"customer" filter:"select * from customer"}}', cell = '%s', tablet_types = '%s' where id in (%d)`, binlogdatapb.VReplicationWorkflowState_Stopped.String(), keyspace, shard, cells[0], tabletTypes[0], vreplID), }, { @@ -689,7 +689,7 @@ func TestUpdateVReplicationWorkflow(t *testing.T) { OnDdl: binlogdatapb.OnDDLAction(textutil.SimulatedNullInt), }, isCopying: true, - query: fmt.Sprintf(`update _vt.vreplication set state = 'Copying', source = 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"corder\" filter:\"select * from corder\"} rules:{match:\"customer\" filter:\"select * from customer\"}}', cell = '%s', tablet_types = '%s' where id in (%d)`, + query: fmt.Sprintf(`update _vt.vreplication set state = 'Copying', source = 'keyspace:"%s" shard:"%s" filter:{rules:{match:"corder" filter:"select * from corder"} rules:{match:"customer" filter:"select * from customer"}}', cell = '%s', tablet_types = '%s' where id in (%d)`, keyspace, shard, cells[0], tabletTypes[0], vreplID), }, } @@ -1033,7 +1033,7 @@ func TestSourceShardSelection(t *testing.T) { } tt.vrdbClient.ExpectRequest(fmt.Sprintf("use %s", sidecar.GetIdentifier()), &sqltypes.Result{}, nil) tt.vrdbClient.ExpectRequest( - fmt.Sprintf(`%s values ('%s', 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"t1\" filter:\"select * from t1 where in_keyrange(id, \'%s.hash\', \'%s\')\"}}', '', 0, 0, '%s', '', now(), 0, 'Stopped', '%s', 1, 0, 0, '{}')`, + fmt.Sprintf(`%s values ('%s', 'keyspace:"%s" shard:"%s" filter:{rules:{match:"t1" filter:"select * from t1 where in_keyrange(id, \'%s.hash\', \'%s\')"}}', '', 0, 0, '%s', '', now(), 0, 'Stopped', '%s', 1, 0, 0, '{}')`, insertVReplicationPrefix, wf, sourceKs, sourceShard, targetKs, tt.tablet.Shard, tenv.cells[0], tenv.dbName), &sqltypes.Result{InsertID: uint64(i + 1)}, err, @@ -1117,7 +1117,7 @@ func TestFailedMoveTablesCreateCleanup(t *testing.T) { targetTablet.vrdbClient.ExpectRequest( fmt.Sprintf("%s %s", insertVReplicationPrefix, - fmt.Sprintf(`values ('%s', 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"%s\" filter:\"select * from %s\"}} source_time_zone:\"%s\" target_time_zone:\"UTC\"', '', 0, 0, '%s', 'primary', now(), 0, 'Stopped', '%s', 1, 0, 0, '{}')`, + fmt.Sprintf(`values ('%s', 'keyspace:"%s" shard:"%s" filter:{rules:{match:"%s" filter:"select * from %s"}} source_time_zone:"%s" target_time_zone:"UTC"', '', 0, 0, '%s', 'primary', now(), 0, 'Stopped', '%s', 1, 0, 0, '{}')`, wf, sourceKs, shard, table, table, invalidTimeZone, strings.Join(tenv.cells, ","), tenv.dbName), ), &sqltypes.Result{ @@ -1793,7 +1793,7 @@ func TestMaterializerOneToOne(t *testing.T) { // the test with an error as at this point we've tested what // we wanted to test. insert := insertVReplicationPrefix + - fmt.Sprintf(` values ('%s', 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"t1\" filter:\"select * from t1\"} rules:{match:\"t2\" filter:\"select * from t3\"} rules:{match:\"t4\"}}', '', 0, 0, '%s', 'primary,rdonly', now(), 0, 'Stopped', '%s', 0, 0, 0, '{}')`, + fmt.Sprintf(` values ('%s', 'keyspace:"%s" shard:"%s" filter:{rules:{match:"t1" filter:"select * from t1"} rules:{match:"t2" filter:"select * from t3"} rules:{match:"t4"}}', '', 0, 0, '%s', 'primary,rdonly', now(), 0, 'Stopped', '%s', 0, 0, 0, '{}')`, wf, sourceKs, shard, tenv.cells[0], tenv.dbName) targetTablet.vrdbClient.ExpectRequest(insert, &sqltypes.Result{}, errShortCircuit) @@ -1858,7 +1858,7 @@ func TestMaterializerManyToOne(t *testing.T) { bls := fmt.Sprintf("keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"t1\" filter:\"select * from t1\"} rules:{match:\"t2\" filter:\"select * from t3\"}}", sourceKs, sourceShard) insert := insertVReplicationPrefix + - fmt.Sprintf(` values ('%s', 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"t1\" filter:\"select * from t1\"} rules:{match:\"t2\" filter:\"select * from t3\"}}', '', 0, 0, '%s', 'primary,rdonly', now(), 0, 'Stopped', '%s', 0, 0, 0, '{}')`, + fmt.Sprintf(` values ('%s', 'keyspace:"%s" shard:"%s" filter:{rules:{match:"t1" filter:"select * from t1"} rules:{match:"t2" filter:"select * from t3"}}', '', 0, 0, '%s', 'primary,rdonly', now(), 0, 'Stopped', '%s', 0, 0, 0, '{}')`, wf, sourceKs, sourceShard, tenv.cells[0], tenv.dbName) if vreplID == 1 { targetTablet.vrdbClient.ExpectRequest(insert, &sqltypes.Result{InsertID: uint64(vreplID)}, nil) @@ -1954,7 +1954,7 @@ func TestMaterializerOneToMany(t *testing.T) { bls := fmt.Sprintf("keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"t1\" filter:\"select * from t1 where in_keyrange(c1, '%s.xxhash', '%s')\"}}", sourceKs, sourceShard, targetKs, targetShard) insert := insertVReplicationPrefix + - fmt.Sprintf(` values ('%s', 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"t1\" filter:\"select * from t1 where in_keyrange(c1, \'%s.xxhash\', \'%s\')\"}}', '', 0, 0, '%s', 'primary,rdonly', now(), 0, 'Stopped', '%s', 0, 0, 0, '{}')`, + fmt.Sprintf(` values ('%s', 'keyspace:"%s" shard:"%s" filter:{rules:{match:"t1" filter:"select * from t1 where in_keyrange(c1, \'%s.xxhash\', \'%s\')"}}', '', 0, 0, '%s', 'primary,rdonly', now(), 0, 'Stopped', '%s', 0, 0, 0, '{}')`, wf, sourceKs, sourceShard, targetKs, targetShard, tenv.cells[0], tenv.dbName) if targetShard == "-80" { targetTablet.vrdbClient.ExpectRequest(insert, &sqltypes.Result{InsertID: uint64(vreplID)}, nil) @@ -2054,7 +2054,7 @@ func TestMaterializerManyToMany(t *testing.T) { bls := fmt.Sprintf("keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"t1\" filter:\"select * from t1 where in_keyrange(c1, '%s.xxhash', '%s')\"}}", sourceKs, sourceShard, targetKs, targetShard) insert := insertVReplicationPrefix + - fmt.Sprintf(` values ('%s', 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"t1\" filter:\"select * from t1 where in_keyrange(c1, \'%s.xxhash\', \'%s\')\"}}', '', 0, 0, '%s', 'primary,rdonly', now(), 0, 'Stopped', '%s', 0, 0, 0, '{}')`, + fmt.Sprintf(` values ('%s', 'keyspace:"%s" shard:"%s" filter:{rules:{match:"t1" filter:"select * from t1 where in_keyrange(c1, \'%s.xxhash\', \'%s\')"}}', '', 0, 0, '%s', 'primary,rdonly', now(), 0, 'Stopped', '%s', 0, 0, 0, '{}')`, wf, sourceKs, sourceShard, targetKs, targetShard, tenv.cells[0], tenv.dbName) if targetShard == "80-" && sourceShard == "40-" { // Last insert targetTablet.vrdbClient.ExpectRequest(insert, &sqltypes.Result{InsertID: uint64(vreplID)}, errShortCircuit) @@ -2155,7 +2155,7 @@ func TestMaterializerMulticolumnVindex(t *testing.T) { bls := fmt.Sprintf("keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"t1\" filter:\"select * from t1 where in_keyrange(c1, c2, '%s.region', '%s')\"}}", sourceKs, sourceShard, targetKs, targetShard) insert := insertVReplicationPrefix + - fmt.Sprintf(` values ('%s', 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"t1\" filter:\"select * from t1 where in_keyrange(c1, c2, \'%s.region\', \'%s\')\"}}', '', 0, 0, '%s', 'primary,rdonly', now(), 0, 'Stopped', '%s', 0, 0, 0, '{}')`, + fmt.Sprintf(` values ('%s', 'keyspace:"%s" shard:"%s" filter:{rules:{match:"t1" filter:"select * from t1 where in_keyrange(c1, c2, \'%s.region\', \'%s\')"}}', '', 0, 0, '%s', 'primary,rdonly', now(), 0, 'Stopped', '%s', 0, 0, 0, '{}')`, wf, sourceKs, sourceShard, targetKs, targetShard, tenv.cells[0], tenv.dbName) if targetShard == "-80" { targetTablet.vrdbClient.ExpectRequest(insert, &sqltypes.Result{InsertID: uint64(vreplID)}, nil) @@ -2239,7 +2239,7 @@ func TestMaterializerDeploySchema(t *testing.T) { // the test with an error as at this point we've tested what // we wanted to test. insert := insertVReplicationPrefix + - fmt.Sprintf(` values ('%s', 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"t1\" filter:\"select * from t1\"} rules:{match:\"t2\" filter:\"select * from t3\"}}', '', 0, 0, '%s', 'primary,rdonly', now(), 0, 'Stopped', '%s', 0, 0, 0, '{}')`, + fmt.Sprintf(` values ('%s', 'keyspace:"%s" shard:"%s" filter:{rules:{match:"t1" filter:"select * from t1"} rules:{match:"t2" filter:"select * from t3"}}', '', 0, 0, '%s', 'primary,rdonly', now(), 0, 'Stopped', '%s', 0, 0, 0, '{}')`, wf, sourceKs, shard, tenv.cells[0], tenv.dbName) targetTablet.vrdbClient.ExpectRequest(insert, &sqltypes.Result{}, errShortCircuit) @@ -2309,7 +2309,7 @@ func TestMaterializerCopySchema(t *testing.T) { // the test with an error as at this point we've tested what // we wanted to test. insert := insertVReplicationPrefix + - fmt.Sprintf(` values ('%s', 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"t1\" filter:\"select * from t1\"} rules:{match:\"t2\" filter:\"select * from t3\"}}', '', 0, 0, '%s', 'primary,rdonly', now(), 0, 'Stopped', '%s', 0, 0, 0, '{}')`, + fmt.Sprintf(` values ('%s', 'keyspace:"%s" shard:"%s" filter:{rules:{match:"t1" filter:"select * from t1"} rules:{match:"t2" filter:"select * from t3"}}', '', 0, 0, '%s', 'primary,rdonly', now(), 0, 'Stopped', '%s', 0, 0, 0, '{}')`, wf, sourceKs, shard, tenv.cells[0], tenv.dbName) targetTablet.vrdbClient.ExpectRequest(insert, &sqltypes.Result{}, errShortCircuit) @@ -2395,7 +2395,7 @@ func TestMaterializerExplicitColumns(t *testing.T) { bls := fmt.Sprintf("keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"t1\" filter:\"select c1, c1 + c2, c2 from t1 where in_keyrange(c1, c2, '%s.region', '%s')\"}}", sourceKs, sourceShard, targetKs, targetShard) insert := insertVReplicationPrefix + - fmt.Sprintf(` values ('%s', 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"t1\" filter:\"select c1, c1 + c2, c2 from t1 where in_keyrange(c1, c2, \'%s.region\', \'%s\')\"}}', '', 0, 0, '%s', 'primary,rdonly', now(), 0, 'Stopped', '%s', 0, 0, 0, '{}')`, + fmt.Sprintf(` values ('%s', 'keyspace:"%s" shard:"%s" filter:{rules:{match:"t1" filter:"select c1, c1 + c2, c2 from t1 where in_keyrange(c1, c2, \'%s.region\', \'%s\')"}}', '', 0, 0, '%s', 'primary,rdonly', now(), 0, 'Stopped', '%s', 0, 0, 0, '{}')`, wf, sourceKs, sourceShard, targetKs, targetShard, tenv.cells[0], tenv.dbName) if targetShard == "-80" { targetTablet.vrdbClient.ExpectRequest(insert, &sqltypes.Result{InsertID: uint64(vreplID)}, nil) @@ -2495,7 +2495,7 @@ func TestMaterializerRenamedColumns(t *testing.T) { bls := fmt.Sprintf("keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"t1\" filter:\"select c3 as c1, c1 + c2, c4 as c2 from t1 where in_keyrange(c3, c4, '%s.region', '%s')\"}}", sourceKs, sourceShard, targetKs, targetShard) insert := insertVReplicationPrefix + - fmt.Sprintf(` values ('%s', 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"t1\" filter:\"select c3 as c1, c1 + c2, c4 as c2 from t1 where in_keyrange(c3, c4, \'%s.region\', \'%s\')\"}}', '', 0, 0, '%s', 'primary,rdonly', now(), 0, 'Stopped', '%s', 0, 0, 0, '{}')`, + fmt.Sprintf(` values ('%s', 'keyspace:"%s" shard:"%s" filter:{rules:{match:"t1" filter:"select c3 as c1, c1 + c2, c4 as c2 from t1 where in_keyrange(c3, c4, \'%s.region\', \'%s\')"}}', '', 0, 0, '%s', 'primary,rdonly', now(), 0, 'Stopped', '%s', 0, 0, 0, '{}')`, wf, sourceKs, sourceShard, targetKs, targetShard, tenv.cells[0], tenv.dbName) if targetShard == "-80" { targetTablet.vrdbClient.ExpectRequest(insert, &sqltypes.Result{InsertID: uint64(vreplID)}, nil) @@ -2570,7 +2570,7 @@ func TestMaterializerStopAfterCopy(t *testing.T) { // the test with an error as at this point we've tested what // we wanted to test. insert := insertVReplicationPrefix + - fmt.Sprintf(` values ('%s', 'keyspace:\"%s\" shard:\"%s\" filter:{rules:{match:\"t1\" filter:\"select * from t1\"} rules:{match:\"t2\" filter:\"select * from t3\"}} stop_after_copy:true', '', 0, 0, '%s', 'primary,rdonly', now(), 0, 'Stopped', '%s', 0, 0, 0, '{}')`, + fmt.Sprintf(` values ('%s', 'keyspace:"%s" shard:"%s" filter:{rules:{match:"t1" filter:"select * from t1"} rules:{match:"t2" filter:"select * from t3"}} stop_after_copy:true', '', 0, 0, '%s', 'primary,rdonly', now(), 0, 'Stopped', '%s', 0, 0, 0, '{}')`, wf, sourceKs, shard, tenv.cells[0], tenv.dbName) targetTablet.vrdbClient.ExpectRequest(insert, &sqltypes.Result{}, errShortCircuit) diff --git a/go/vt/vttablet/tabletmanager/vdiff/action_test.go b/go/vt/vttablet/tabletmanager/vdiff/action_test.go index 4676238cf69..6949b411f13 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/action_test.go +++ b/go/vt/vttablet/tabletmanager/vdiff/action_test.go @@ -86,7 +86,7 @@ func TestPerformVDiffAction(t *testing.T) { query: fmt.Sprintf("select id as id from _vt.vdiff where vdiff_uuid = %s", encodeString(uuid)), }, { - 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)), + 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)), }, }, postFunc: func() error { @@ -120,7 +120,7 @@ func TestPerformVDiffAction(t *testing.T) { query: fmt.Sprintf("select id as id from _vt.vdiff where vdiff_uuid = %s", encodeString(uuid)), }, { - 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)), + 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)), }, }, postFunc: func() error { diff --git a/go/vt/vttablet/tabletmanager/vdiff/engine_test.go b/go/vt/vttablet/tabletmanager/vdiff/engine_test.go index e6c9a84d9e2..ef3c673cc8f 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/engine_test.go +++ b/go/vt/vttablet/tabletmanager/vdiff/engine_test.go @@ -187,8 +187,8 @@ func TestVDiff(t *testing.T) { ), `fields:{name:"c1" type:INT64 table:"t1" org_table:"t1" database:"vt_customer" org_name:"c1" column_length:20 charset:63 flags:53251} rows:{lengths:1 values:"1"}|0|{}`, ), nil) - vdenv.dbClient.ExpectRequest(`update _vt.vdiff_table set rows_compared = 0, report = '{\"TableName\":\"t1\",\"ProcessedRows\":0,\"MatchingRows\":0,\"MismatchedRows\":0,\"ExtraRowsSource\":0,\"ExtraRowsTarget\":0}' where vdiff_id = 1 and table_name = 't1'`, singleRowAffected, nil) - vdenv.dbClient.ExpectRequest(`update _vt.vdiff_table set state = 'completed', rows_compared = 0, report = '{\"TableName\":\"t1\",\"ProcessedRows\":0,\"MatchingRows\":0,\"MismatchedRows\":0,\"ExtraRowsSource\":0,\"ExtraRowsTarget\":0}' where vdiff_id = 1 and table_name = 't1'`, singleRowAffected, nil) + vdenv.dbClient.ExpectRequest(`update _vt.vdiff_table set rows_compared = 0, report = '{"TableName":"t1","ProcessedRows":0,"MatchingRows":0,"MismatchedRows":0,"ExtraRowsSource":0,"ExtraRowsTarget":0}' where vdiff_id = 1 and table_name = 't1'`, singleRowAffected, nil) + vdenv.dbClient.ExpectRequest(`update _vt.vdiff_table set state = 'completed', rows_compared = 0, report = '{"TableName":"t1","ProcessedRows":0,"MatchingRows":0,"MismatchedRows":0,"ExtraRowsSource":0,"ExtraRowsTarget":0}' 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("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) diff --git a/go/vt/vttablet/tabletmanager/vdiff/framework_test.go b/go/vt/vttablet/tabletmanager/vdiff/framework_test.go index 43aa76894d4..8df060e4170 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/framework_test.go +++ b/go/vt/vttablet/tabletmanager/vdiff/framework_test.go @@ -30,6 +30,7 @@ import ( "github.com/stretchr/testify/require" "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/mysql/capabilities" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/binlog/binlogplayer" "vitess.io/vitess/go/vt/grpcclient" @@ -422,6 +423,10 @@ func (dbc *realDBClient) ExecuteFetchMulti(query string, maxrows int) ([]*sqltyp return results, nil } +func (dbc *realDBClient) SupportsCapability(capability capabilities.FlavorCapability) (bool, error) { + return dbc.conn.SupportsCapability(capability) +} + //---------------------------------------------- // fakeTMClient @@ -510,6 +515,10 @@ func (tmc *fakeTMClient) CheckThrottler(ctx context.Context, tablet *topodatapb. return &tabletmanagerdatapb.CheckThrottlerResponse{}, nil } +func (tmc *fakeTMClient) GetThrottlerStatus(ctx context.Context, tablet *topodatapb.Tablet, request *tabletmanagerdatapb.GetThrottlerStatusRequest) (*tabletmanagerdatapb.GetThrottlerStatusResponse, error) { + return &tabletmanagerdatapb.GetThrottlerStatusResponse{}, nil +} + // ---------------------------------------------- // testVDiffEnv diff --git a/go/vt/vttablet/tabletmanager/vdiff/table_differ.go b/go/vt/vttablet/tabletmanager/vdiff/table_differ.go index a98a3ce90f9..f91a82b9d2c 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/table_differ.go +++ b/go/vt/vttablet/tabletmanager/vdiff/table_differ.go @@ -115,10 +115,11 @@ func (td *tableDiffer) initialize(ctx context.Context) error { defer dbClient.Close() targetKeyspace := td.wd.ct.vde.thisTablet.Keyspace - log.Infof("Locking target keyspace %s", targetKeyspace) - ctx, unlock, lockErr := td.wd.ct.ts.LockKeyspace(ctx, targetKeyspace, "vdiff") + lockName := fmt.Sprintf("%s/%s", targetKeyspace, td.wd.ct.workflow) + log.Infof("Locking workflow %s", lockName) + ctx, unlock, lockErr := td.wd.ct.ts.LockName(ctx, lockName, "vdiff") if lockErr != nil { - log.Errorf("LockKeyspace failed: %v", lockErr) + log.Errorf("Locking workfkow %s failed: %v", lockName, lockErr) return lockErr } @@ -126,7 +127,7 @@ func (td *tableDiffer) initialize(ctx context.Context) error { defer func() { unlock(&err) if err != nil { - log.Errorf("UnlockKeyspace %s failed: %v", targetKeyspace, err) + log.Errorf("Unlocking workflow %s failed: %v", lockName, err) } }() diff --git a/go/vt/vttablet/tabletmanager/vdiff/table_plan.go b/go/vt/vttablet/tabletmanager/vdiff/table_plan.go index 548f902e9ac..becce6f90e6 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/table_plan.go +++ b/go/vt/vttablet/tabletmanager/vdiff/table_plan.go @@ -174,8 +174,14 @@ func (td *tableDiffer) buildTablePlan(dbClient binlogplayer.DBClient, dbName str return nil, err } - // Remove in_keyrange. It's not understood by mysql. - sourceSelect.Where = sel.Where // removeKeyrange(sel.Where) + // Copy all workflow filters for the source query. + sourceSelect.Where = sel.Where + + // Copy all non-in_keyrange workflow filters to the target query. + // This is important for things like multi-tenant migrations where + // an additional tenant_id filter is applied in the workflow. + targetSelect.Where = copyNonKeyRangeExpressions(sel.Where) + // The source should also perform the group by. sourceSelect.GroupBy = sel.GroupBy sourceSelect.OrderBy = tp.orderBy diff --git a/go/vt/vttablet/tabletmanager/vdiff/utils.go b/go/vt/vttablet/tabletmanager/vdiff/utils.go index 07e070976a9..aeaa28972e0 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/utils.go +++ b/go/vt/vttablet/tabletmanager/vdiff/utils.go @@ -21,6 +21,7 @@ import ( "fmt" "strings" + "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vtgate/evalengine" "vitess.io/vitess/go/vt/binlog/binlogplayer" @@ -89,3 +90,23 @@ func stringListContains(lst []string, item string) bool { } return contains } + +// copyNonKeyRangeExpressions copies all expressions from the input WHERE clause +// to the output WHERE clause except for any in_keyrange() expressions. +func copyNonKeyRangeExpressions(where *sqlparser.Where) *sqlparser.Where { + if where == nil { + return nil + } + exprs := sqlparser.SplitAndExpression(nil, where.Expr) + newWhere := &sqlparser.Where{} + for _, expr := range exprs { + switch expr := expr.(type) { + case *sqlparser.FuncExpr: + if expr.Name.EqualString("in_keyrange") { + continue + } + } + newWhere.Expr = sqlparser.AndExpressions(newWhere.Expr, expr) + } + return newWhere +} diff --git a/go/vt/vttablet/tabletmanager/vdiff/workflow_differ_test.go b/go/vt/vttablet/tabletmanager/vdiff/workflow_differ_test.go index a460b87a4f6..d4f9ddb001d 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/workflow_differ_test.go +++ b/go/vt/vttablet/tabletmanager/vdiff/workflow_differ_test.go @@ -364,7 +364,6 @@ func TestBuildPlanSuccess(t *testing.T) { }, }, { // in_keyrange on RHS of AND. - // This is currently not a valid construct, but will be supported in the future. input: &binlogdatapb.Rule{ Match: "t1", Filter: "select * from t1 where c2 = 2 and in_keyrange('-80')", @@ -374,7 +373,7 @@ func TestBuildPlanSuccess(t *testing.T) { dbName: vdiffDBName, table: testSchema.TableDefinitions[tableDefMap["t1"]], sourceQuery: "select c1, c2 from t1 where c2 = 2 and in_keyrange('-80') order by c1 asc", - targetQuery: "select c1, c2 from t1 order by c1 asc", + targetQuery: "select c1, c2 from t1 where c2 = 2 order by c1 asc", compareCols: []compareColInfo{{0, collations.MySQL8().LookupByName(sqltypes.NULL.String()), true, "c1"}, {1, collations.MySQL8().LookupByName(sqltypes.NULL.String()), false, "c2"}}, comparePKs: []compareColInfo{{0, collations.MySQL8().LookupByName(sqltypes.NULL.String()), true, "c1"}}, pkCols: []int{0}, @@ -386,7 +385,6 @@ func TestBuildPlanSuccess(t *testing.T) { }, }, { // in_keyrange on LHS of AND. - // This is currently not a valid construct, but will be supported in the future. input: &binlogdatapb.Rule{ Match: "t1", Filter: "select * from t1 where in_keyrange('-80') and c2 = 2", @@ -396,7 +394,7 @@ func TestBuildPlanSuccess(t *testing.T) { dbName: vdiffDBName, table: testSchema.TableDefinitions[tableDefMap["t1"]], sourceQuery: "select c1, c2 from t1 where in_keyrange('-80') and c2 = 2 order by c1 asc", - targetQuery: "select c1, c2 from t1 order by c1 asc", + targetQuery: "select c1, c2 from t1 where c2 = 2 order by c1 asc", compareCols: []compareColInfo{{0, collations.MySQL8().LookupByName(sqltypes.NULL.String()), true, "c1"}, {1, collations.MySQL8().LookupByName(sqltypes.NULL.String()), false, "c2"}}, comparePKs: []compareColInfo{{0, collations.MySQL8().LookupByName(sqltypes.NULL.String()), true, "c1"}}, pkCols: []int{0}, @@ -408,7 +406,6 @@ func TestBuildPlanSuccess(t *testing.T) { }, }, { // in_keyrange on cascaded AND expression. - // This is currently not a valid construct, but will be supported in the future. input: &binlogdatapb.Rule{ Match: "t1", Filter: "select * from t1 where c2 = 2 and c1 = 1 and in_keyrange('-80')", @@ -418,7 +415,7 @@ func TestBuildPlanSuccess(t *testing.T) { dbName: vdiffDBName, table: testSchema.TableDefinitions[tableDefMap["t1"]], sourceQuery: "select c1, c2 from t1 where c2 = 2 and c1 = 1 and in_keyrange('-80') order by c1 asc", - targetQuery: "select c1, c2 from t1 order by c1 asc", + targetQuery: "select c1, c2 from t1 where c2 = 2 and c1 = 1 order by c1 asc", compareCols: []compareColInfo{{0, collations.MySQL8().LookupByName(sqltypes.NULL.String()), true, "c1"}, {1, collations.MySQL8().LookupByName(sqltypes.NULL.String()), false, "c2"}}, comparePKs: []compareColInfo{{0, collations.MySQL8().LookupByName(sqltypes.NULL.String()), true, "c1"}}, pkCols: []int{0}, @@ -430,7 +427,6 @@ func TestBuildPlanSuccess(t *testing.T) { }, }, { // in_keyrange parenthesized. - // This is currently not a valid construct, but will be supported in the future. input: &binlogdatapb.Rule{ Match: "t1", Filter: "select * from t1 where (c2 = 2 and in_keyrange('-80'))", @@ -440,7 +436,7 @@ func TestBuildPlanSuccess(t *testing.T) { dbName: vdiffDBName, table: testSchema.TableDefinitions[tableDefMap["t1"]], sourceQuery: "select c1, c2 from t1 where c2 = 2 and in_keyrange('-80') order by c1 asc", - targetQuery: "select c1, c2 from t1 order by c1 asc", + targetQuery: "select c1, c2 from t1 where c2 = 2 order by c1 asc", compareCols: []compareColInfo{{0, collations.MySQL8().LookupByName(sqltypes.NULL.String()), true, "c1"}, {1, collations.MySQL8().LookupByName(sqltypes.NULL.String()), false, "c2"}}, comparePKs: []compareColInfo{{0, collations.MySQL8().LookupByName(sqltypes.NULL.String()), true, "c1"}}, pkCols: []int{0}, diff --git a/go/vt/vttablet/tabletmanager/vreplication/engine.go b/go/vt/vttablet/tabletmanager/vreplication/engine.go index 54902928e02..d407bfe403b 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/engine.go +++ b/go/vt/vttablet/tabletmanager/vreplication/engine.go @@ -40,6 +40,7 @@ import ( "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle" + "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/throttlerapp" binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" @@ -139,7 +140,7 @@ func NewEngine(env *vtenv.Environment, config *tabletenv.TabletConfig, ts *topo. mysqld: mysqld, journaler: make(map[string]*journalEvent), ec: newExternalConnector(env, config.ExternalConnections), - throttlerClient: throttle.NewBackgroundClient(lagThrottler, throttlerapp.VReplicationName, throttle.ThrottleCheckPrimaryWrite), + throttlerClient: throttle.NewBackgroundClient(lagThrottler, throttlerapp.VReplicationName, base.UndefinedScope), } return vre diff --git a/go/vt/vttablet/tabletmanager/vreplication/framework_test.go b/go/vt/vttablet/tabletmanager/vreplication/framework_test.go index d4253de27e7..ef80dd49757 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/framework_test.go +++ b/go/vt/vttablet/tabletmanager/vreplication/framework_test.go @@ -34,6 +34,7 @@ import ( _flag "vitess.io/vitess/go/internal/flag" "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/mysql/capabilities" "vitess.io/vitess/go/mysql/replication" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/test/utils" @@ -509,6 +510,10 @@ func (dbc *realDBClient) ExecuteFetchMulti(query string, maxrows int) ([]*sqltyp return results, nil } +func (dbc *realDBClient) SupportsCapability(capability capabilities.FlavorCapability) (bool, error) { + return dbc.conn.SupportsCapability(capability) +} + func expectDeleteQueries(t *testing.T) { t.Helper() if doNotLogDBQueries { diff --git a/go/vt/vttablet/tabletmanager/vreplication/insert_generator_test.go b/go/vt/vttablet/tabletmanager/vreplication/insert_generator_test.go index 2b07308c4c2..92100429963 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/insert_generator_test.go +++ b/go/vt/vttablet/tabletmanager/vreplication/insert_generator_test.go @@ -29,10 +29,10 @@ func TestInsertGenerator(t *testing.T) { ig.now = 111 ig.AddRow("b", &binlogdatapb.BinlogSource{Keyspace: "c"}, "d", "e", "f", binlogdatapb.VReplicationWorkflowType_Materialize, binlogdatapb.VReplicationWorkflowSubType_None, false) want := `insert into _vt.vreplication(workflow, source, pos, max_tps, max_replication_lag, cell, tablet_types, time_updated, transaction_timestamp, state, db_name, workflow_type, workflow_sub_type, defer_secondary_keys, options) values ` + - `('b', 'keyspace:\"c\"', 'd', 9223372036854775807, 9223372036854775807, 'e', 'f', 111, 0, 'Stopped', 'a', 0, 0, false, '{}')` + `('b', 'keyspace:"c"', 'd', 9223372036854775807, 9223372036854775807, 'e', 'f', 111, 0, 'Stopped', 'a', 0, 0, false, '{}')` assert.Equal(t, ig.String(), want) ig.AddRow("g", &binlogdatapb.BinlogSource{Keyspace: "h"}, "i", "j", "k", binlogdatapb.VReplicationWorkflowType_Reshard, binlogdatapb.VReplicationWorkflowSubType_Partial, true) - want += `, ('g', 'keyspace:\"h\"', 'i', 9223372036854775807, 9223372036854775807, 'j', 'k', 111, 0, 'Stopped', 'a', 4, 1, true, '{}')` + want += `, ('g', 'keyspace:"h"', 'i', 9223372036854775807, 9223372036854775807, 'j', 'k', 111, 0, 'Stopped', 'a', 4, 1, true, '{}')` assert.Equal(t, ig.String(), want) } diff --git a/go/vt/vttablet/tabletmanager/vreplication/journal_test.go b/go/vt/vttablet/tabletmanager/vreplication/journal_test.go index 18dbe1e7fd8..862f22ab564 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/journal_test.go +++ b/go/vt/vttablet/tabletmanager/vreplication/journal_test.go @@ -70,7 +70,7 @@ func TestJournalOneToOne(t *testing.T) { expectDBClientQueries(t, qh.Expect( "begin", - `/insert into _vt.vreplication.*workflow, source, pos.*values.*'test', 'keyspace:\\"other_keyspace\\" shard:\\"0\\.*'MySQL56/7b04699f-f5e9-11e9-bf88-9cb6d089e1c3:1-10'`, + `/insert into _vt.vreplication.*workflow, source, pos.*values.*'test', 'keyspace:"other_keyspace" shard:"0.*'MySQL56/7b04699f-f5e9-11e9-bf88-9cb6d089e1c3:1-10'`, fmt.Sprintf("delete from _vt.vreplication where id=%d", firstID), "commit", "/update _vt.vreplication set message='Picked source tablet.*", @@ -133,8 +133,8 @@ func TestJournalOneToMany(t *testing.T) { expectDBClientQueries(t, qh.Expect( "begin", - `/insert into _vt.vreplication.*workflow, source, pos.*values.*'test', 'keyspace:\\"other_keyspace\\" shard:\\"-80\\.*'MySQL56/7b04699f-f5e9-11e9-bf88-9cb6d089e1c3:1-5'`, - `/insert into _vt.vreplication.*workflow, source, pos.*values.*'test', 'keyspace:\\"other_keyspace\\" shard:\\"80-\\.*'MySQL56/7b04699f-f5e9-11e9-bf88-9cb6d089e1c3:5-10'`, + `/insert into _vt.vreplication.*workflow, source, pos.*values.*'test', 'keyspace:"other_keyspace" shard:"-80.*'MySQL56/7b04699f-f5e9-11e9-bf88-9cb6d089e1c3:1-5'`, + `/insert into _vt.vreplication.*workflow, source, pos.*values.*'test', 'keyspace:"other_keyspace" shard:"80-.*'MySQL56/7b04699f-f5e9-11e9-bf88-9cb6d089e1c3:5-10'`, fmt.Sprintf("delete from _vt.vreplication where id=%d", firstID), "commit", "/update _vt.vreplication set message='Picked source tablet.*", @@ -194,7 +194,7 @@ func TestJournalTablePresent(t *testing.T) { expectDBClientQueries(t, qh.Expect( "begin", - `/insert into _vt.vreplication.*workflow, source, pos.*values.*'test', 'keyspace:\\"other_keyspace\\" shard:\\"0\\.*'MySQL56/7b04699f-f5e9-11e9-bf88-9cb6d089e1c3:1-10'`, + `/insert into _vt.vreplication.*workflow, source, pos.*values.*'test', 'keyspace:"other_keyspace" shard:"0.*'MySQL56/7b04699f-f5e9-11e9-bf88-9cb6d089e1c3:1-10'`, fmt.Sprintf("delete from _vt.vreplication where id=%d", firstID), "commit", "/update _vt.vreplication set message='Picked source tablet.*", diff --git a/go/vt/vttablet/tabletmanager/vreplication/utils.go b/go/vt/vttablet/tabletmanager/vreplication/utils.go index 2b80bfb62a2..537041907a7 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/utils.go +++ b/go/vt/vttablet/tabletmanager/vreplication/utils.go @@ -222,6 +222,7 @@ func isUnrecoverableError(err error) bool { sqlerror.ERWrongParametersToProcedure, sqlerror.ERWrongUsage, sqlerror.ERWrongValue, + sqlerror.ERVectorConversion, sqlerror.ERWrongValueCountOnRow: log.Errorf("Got unrecoverable error: %v", sqlErr) return true diff --git a/go/vt/vttablet/tabletmanager/vreplication/vcopier_test.go b/go/vt/vttablet/tabletmanager/vreplication/vcopier_test.go index 9cbb51e76c6..fda9012c1b5 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/vcopier_test.go +++ b/go/vt/vttablet/tabletmanager/vreplication/vcopier_test.go @@ -176,10 +176,10 @@ func testPlayerCopyCharPK(t *testing.T) { "/insert into _vt.copy_state", "/update _vt.vreplication set state='Copying'", "insert into dst(idc,val) values ('a\\0',1)", - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"idc\\" type:BINARY charset:63 flags:20611} rows:{lengths:2 values:\\"a\\\\x00\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"idc" type:BINARY charset:63 flags:20611} rows:{lengths:2 values:"a\\\\x00"}'.*`, `update dst set val=3 where idc='a\0' and ('a\0') <= ('a\0')`, "insert into dst(idc,val) values ('c\\0',2)", - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"idc\\" type:BINARY charset:63 flags:20611} rows:{lengths:2 values:\\"c\\\\x00\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"idc" type:BINARY charset:63 flags:20611} rows:{lengths:2 values:"c\\\\x00"}'.*`, "/delete cs, pca from _vt.copy_state as cs left join _vt.post_copy_action as pca on cs.vrepl_id=pca.vrepl_id and cs.table_name=pca.table_name.*dst", "/update _vt.vreplication set state='Running", ), recvTimeout) @@ -283,7 +283,7 @@ func testPlayerCopyVarcharPKCaseInsensitive(t *testing.T) { "/update _vt.vreplication set state='Copying'", // Copy mode. "insert into dst(idc,val) values ('a',1)", - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"idc\\" type:VARCHAR charset:33 flags:20483} rows:{lengths:1 values:\\"a\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"idc" type:VARCHAR charset:33 flags:20483} rows:{lengths:1 values:"a"}'.*`, // Copy-catchup mode. `/insert into dst\(idc,val\) select 'B', 3 from dual where \( .* 'B' COLLATE .* \) <= \( .* 'a' COLLATE .* \)`, ).Then(func(expect qh.ExpectationSequencer) qh.ExpectationSequencer { @@ -293,11 +293,11 @@ func testPlayerCopyVarcharPKCaseInsensitive(t *testing.T) { //upd1 := expect. upd1 := expect.Then(qh.Eventually( "insert into dst(idc,val) values ('B',3)", - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"idc\\" type:VARCHAR charset:33 flags:20483} rows:{lengths:1 values:\\"B\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"idc" type:VARCHAR charset:33 flags:20483} rows:{lengths:1 values:"B"}'.*`, )) upd2 := expect.Then(qh.Eventually( "insert into dst(idc,val) values ('c',2)", - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"idc\\" type:VARCHAR charset:33 flags:20483} rows:{lengths:1 values:\\"c\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"idc" type:VARCHAR charset:33 flags:20483} rows:{lengths:1 values:"c"}'.*`, )) upd1.Then(upd2.Eventually()) return upd2 @@ -406,12 +406,12 @@ func testPlayerCopyVarcharCompositePKCaseSensitiveCollation(t *testing.T) { "/update _vt.vreplication set state='Copying'", // Copy mode. "insert into dst(id,idc,idc2,val) values (1,'a','a',1)", - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"id\\" type:INT32 charset:63 flags:53251} fields:{name:\\"idc\\" type:VARBINARY charset:63 flags:20611} fields:{name:\\"idc2\\" type:VARBINARY charset:63 flags:20611} rows:{lengths:1 lengths:1 lengths:1 values:\\"1aa\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"id" type:INT32 charset:63 flags:53251} fields:{name:"idc" type:VARBINARY charset:63 flags:20611} fields:{name:"idc2" type:VARBINARY charset:63 flags:20611} rows:{lengths:1 lengths:1 lengths:1 values:"1aa"}'.*`, // Copy-catchup mode. `insert into dst(id,idc,idc2,val) select 1, 'B', 'B', 3 from dual where (1,'B','B') <= (1,'a','a')`, // Copy mode. "insert into dst(id,idc,idc2,val) values (1,'c','c',2)", - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"id\\" type:INT32 charset:63 flags:53251} fields:{name:\\"idc\\" type:VARBINARY charset:63 flags:20611} fields:{name:\\"idc2\\" type:VARBINARY charset:63 flags:20611} rows:{lengths:1 lengths:1 lengths:1 values:\\"1cc\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"id" type:INT32 charset:63 flags:53251} fields:{name:"idc" type:VARBINARY charset:63 flags:20611} fields:{name:"idc2" type:VARBINARY charset:63 flags:20611} rows:{lengths:1 lengths:1 lengths:1 values:"1cc"}'.*`, // Wrap-up. "/delete cs, pca from _vt.copy_state as cs left join _vt.post_copy_action as pca on cs.vrepl_id=pca.vrepl_id and cs.table_name=pca.table_name.*dst", "/update _vt.vreplication set state='Running'", @@ -495,7 +495,7 @@ func testPlayerCopyTablesWithFK(t *testing.T) { // Inserts may happen out-of-order. Update happen in-order. "begin", "insert into dst1(id,id2) values (1,1), (2,2)", - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"id\\" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:\\"2\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"id" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:"2"}'.*`, "commit", )).Then(qh.Immediately( "set @@session.foreign_key_checks=0", @@ -516,7 +516,7 @@ func testPlayerCopyTablesWithFK(t *testing.T) { // copy dst2 "begin", "insert into dst2(id,id2) values (1,21), (2,22)", - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"id\\" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:\\"2\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"id" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:"2"}'.*`, "commit", )).Then(qh.Immediately( "set @@session.foreign_key_checks=0", @@ -610,7 +610,7 @@ func testPlayerCopyTables(t *testing.T) { expectDBClientQueries(t, qh.Expect( // Filters should be lexicographically ordered by name. - regexp.QuoteMeta("/insert into _vt.vreplication (workflow, source, pos, max_tps, max_replication_lag, time_updated, transaction_timestamp, state, db_name, workflow_type, workflow_sub_type, options) values ('test', 'keyspace:\\\"vttest\\\" shard:\\\"0\\\" filter:{rules:{match:\\\"ast1\\\" filter:\\\"select * from ast1\\\"} rules:{match:\\\"dst1\\\" filter:\\\"select id, val, val as val2, d, j from src1\\\"} rules:{match:\\\"/yes\\\"}}'"), + regexp.QuoteMeta("/insert into _vt.vreplication (workflow, source, pos, max_tps, max_replication_lag, time_updated, transaction_timestamp, state, db_name, workflow_type, workflow_sub_type, options) values ('test', 'keyspace:\"vttest\" shard:\"0\" filter:{rules:{match:\"ast1\" filter:\"select * from ast1\"} rules:{match:\"dst1\" filter:\"select id, val, val as val2, d, j from src1\"} rules:{match:\"/yes\"}}'"), "/update _vt.vreplication set message='Picked source tablet.*", // Create the list of tables to copy and transition to Copying state. "begin", @@ -629,7 +629,7 @@ func testPlayerCopyTables(t *testing.T) { "commit", "begin", "insert into dst1(id,val,val2,d,j) values (1,'aaa','aaa',0,JSON_ARRAY(123456789012345678901234567890, _utf8mb4'abcd')), (2,'bbb','bbb',1,JSON_OBJECT(_utf8mb4'foo', _utf8mb4'bar')), (3,'ccc','ccc',2,CAST(_utf8mb4'null' as JSON)), (4,'ddd','ddd',3,JSON_OBJECT(_utf8mb4'name', _utf8mb4'matt', _utf8mb4'size', null)), (5,'eee','eee',4,null)", - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"id\\" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:\\"5\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"id" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:"5"}'.*`, "commit", // copy of dst1 is done: delete from copy_state. "/delete cs, pca from _vt.copy_state as cs left join _vt.post_copy_action as pca on cs.vrepl_id=pca.vrepl_id and cs.table_name=pca.table_name.*dst1", @@ -765,7 +765,7 @@ func testPlayerCopyBigTable(t *testing.T) { // The first fast-forward has no starting point. So, it just saves the current position. "/update _vt.vreplication set state='Copying'", "insert into dst(id,val) values (1,'aaa')", - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"id\\" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:\\"1\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"id" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:"1"}'.*`, // The next catchup executes the new row insert, but will be a no-op. "insert into dst(id,val) select 3, 'ccc' from dual where (3) <= (1)", // fastForward has nothing to add. Just saves position. @@ -775,12 +775,12 @@ func testPlayerCopyBigTable(t *testing.T) { ).Then(func(expect qh.ExpectationSequencer) qh.ExpectationSequencer { ins1 := expect.Then(qh.Eventually("insert into dst(id,val) values (2,'bbb')")) upd1 := ins1.Then(qh.Eventually( - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"id\\" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:\\"2\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"id" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:"2"}'.*`, )) // Third row copied without going back to catchup state. ins3 := expect.Then(qh.Eventually("insert into dst(id,val) values (3,'ccc')")) upd3 := ins3.Then(qh.Eventually( - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"id\\" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:\\"3\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"id" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:"3"}'.*`, )) upd1.Then(upd3.Eventually()) return upd3 @@ -894,7 +894,7 @@ func testPlayerCopyWildcardRule(t *testing.T) { "/update _vt.vreplication set state='Copying'", // The first fast-forward has no starting point. So, it just saves the current position. "insert into src(id,val) values (1,'aaa')", - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"id\\" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:\\"1\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"id" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:"1"}'.*`, // The next catchup executes the new row insert, but will be a no-op. "insert into src(id,val) select 3, 'ccc' from dual where (3) <= (1)", // fastForward has nothing to add. Just saves position. @@ -904,12 +904,12 @@ func testPlayerCopyWildcardRule(t *testing.T) { ).Then(func(expect qh.ExpectationSequencer) qh.ExpectationSequencer { ins1 := expect.Then(qh.Eventually("insert into src(id,val) values (2,'bbb')")) upd1 := ins1.Then(qh.Eventually( - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"id\\" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:\\"2\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"id" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:"2"}'.*`, )) // Third row copied without going back to catchup state. ins3 := expect.Then(qh.Eventually("insert into src(id,val) values (3,'ccc')")) upd3 := ins3.Then(qh.Eventually( - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"id\\" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:\\"3\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"id" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:"3"}'.*`, )) upd1.Then(upd3.Eventually()) return upd3 @@ -1068,13 +1068,13 @@ func testPlayerCopyTableContinuation(t *testing.T) { ).Then(qh.Immediately( "insert into dst1(id,val) values (7,'insert out'), (8,'no change'), (10,'updated'), (12,'move out')", )).Then(qh.Eventually( - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"id1\\" type:INT32 charset:63 flags:53251} fields:{name:\\"id2\\" type:INT32 charset:63 flags:53251} rows:{lengths:2 lengths:1 values:\\"126\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"id1" type:INT32 charset:63 flags:53251} fields:{name:"id2" type:INT32 charset:63 flags:53251} rows:{lengths:2 lengths:1 values:"126"}'.*`, )).Then(qh.Immediately( "/delete cs, pca from _vt.copy_state as cs left join _vt.post_copy_action as pca on cs.vrepl_id=pca.vrepl_id and cs.table_name=pca.table_name.*dst1", "insert into not_copied(id,val) values (1,'bbb')", )).Then(qh.Eventually( // Copy again. There should be no events for catchup. - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\\"id\\\" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:\\\"1\\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"id" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:"1"}'.*`, )).Then(qh.Immediately( "/delete cs, pca from _vt.copy_state as cs left join _vt.post_copy_action as pca on cs.vrepl_id=pca.vrepl_id and cs.table_name=pca.table_name.*not_copied", "/update _vt.vreplication set state='Running'", @@ -1390,7 +1390,7 @@ func testPlayerCopyTablesStopAfterCopy(t *testing.T) { ).Then(qh.Eventually( "begin", "insert into dst1(id,val) values (1,'aaa'), (2,'bbb')", - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"id\\" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:\\"2\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"id" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:"2"}'.*`, "commit", )).Then(qh.Immediately( // copy of dst1 is done: delete from copy_state. @@ -1478,7 +1478,7 @@ func testPlayerCopyTablesGIPK(t *testing.T) { ).Then(qh.Eventually( "begin", "insert into dst1(my_row_id,val) values (1,'aaa'), (2,'bbb')", - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"my_row_id\\" type:UINT64 charset:63 flags:49699} rows:{lengths:1 values:\\"2\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"my_row_id" type:UINT64 charset:63 flags:49699} rows:{lengths:1 values:"2"}'.*`, "commit", )).Then(qh.Immediately( // copy of dst1 is done: delete from copy_state. @@ -1489,7 +1489,7 @@ func testPlayerCopyTablesGIPK(t *testing.T) { "commit", "begin", "insert into dst2(my_row_id,val) values (1,'aaa'), (2,'bbb')", - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"my_row_id\\" type:UINT64 charset:63 flags:49699} rows:{lengths:1 values:\\"2\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"my_row_id" type:UINT64 charset:63 flags:49699} rows:{lengths:1 values:"2"}'.*`, "commit", )).Then(qh.Immediately( // copy of dst2 is done: delete from copy_state. @@ -1578,7 +1578,7 @@ func testPlayerCopyTableCancel(t *testing.T) { ).Then(qh.Eventually( "begin", "insert into dst1(id,val) values (1,'aaa'), (2,'bbb')", - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"id\\" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:\\"2\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"id" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:"2"}'.*`, "commit", )).Then(qh.Immediately( // copy of dst1 is done: delete from copy_state. @@ -1651,11 +1651,11 @@ func testPlayerCopyTablesWithGeneratedColumn(t *testing.T) { "/update _vt.vreplication set state", // The first fast-forward has no starting point. So, it just saves the current position. "insert into dst1(id,val,val3,id2) values (1,'aaa','aaa1',10), (2,'bbb','bbb2',20)", - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"id\\" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:\\"2\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"id" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:"2"}'.*`, // copy of dst1 is done: delete from copy_state. "/delete cs, pca from _vt.copy_state as cs left join _vt.post_copy_action as pca on cs.vrepl_id=pca.vrepl_id and cs.table_name=pca.table_name.*dst1", "insert into dst2(val3,val,id2) values ('aaa1','aaa',10), ('bbb2','bbb',20)", - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"id\\" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:\\"2\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"id" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:"2"}'.*`, // copy of dst2 is done: delete from copy_state. "/delete cs, pca from _vt.copy_state as cs left join _vt.post_copy_action as pca on cs.vrepl_id=pca.vrepl_id and cs.table_name=pca.table_name.*dst2", "/update _vt.vreplication set state", @@ -1732,7 +1732,7 @@ func testCopyTablesWithInvalidDates(t *testing.T) { ).Then(qh.Eventually( "begin", "insert into dst1(id,dt) values (1,'2020-01-12'), (2,'0000-00-00')", - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"id\\" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:\\"2\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"id" type:INT32 charset:63 flags:53251} rows:{lengths:1 values:"2"}'.*`, "commit", )).Then(qh.Immediately( // copy of dst1 is done: delete from copy_state. @@ -1822,7 +1822,7 @@ func testCopyInvisibleColumns(t *testing.T) { "/update _vt.vreplication set state='Copying'", // The first fast-forward has no starting point. So, it just saves the current position. "insert into dst1(id,id2,inv1,inv2) values (1,10,100,1000), (2,20,200,2000)", - `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:\\"id\\" type:INT32 charset:63 flags:53251} fields:{name:\\"inv1\\" type:INT32 charset:63 flags:53251} rows:{lengths:1 lengths:3 values:\\"2200\\"}'.*`, + `/insert into _vt.copy_state \(lastpk, vrepl_id, table_name\) values \('fields:{name:"id" type:INT32 charset:63 flags:53251} fields:{name:"inv1" type:INT32 charset:63 flags:53251} rows:{lengths:1 lengths:3 values:"2200"}'.*`, // copy of dst1 is done: delete from copy_state. "/delete cs, pca from _vt.copy_state as cs left join _vt.post_copy_action as pca on cs.vrepl_id=pca.vrepl_id and cs.table_name=pca.table_name.*dst1", "/update _vt.vreplication set state='Running'", diff --git a/go/vt/vttablet/tabletmanager/vreplication/vreplicator.go b/go/vt/vttablet/tabletmanager/vreplication/vreplicator.go index 8a01cf7c8ed..abeda52b047 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/vreplicator.go +++ b/go/vt/vttablet/tabletmanager/vreplication/vreplicator.go @@ -26,6 +26,7 @@ import ( "strings" "time" + "vitess.io/vitess/go/mysql/capabilities" "vitess.io/vitess/go/mysql/replication" "vitess.io/vitess/go/mysql/sqlerror" "vitess.io/vitess/go/sqltypes" @@ -105,6 +106,7 @@ type vreplicator struct { originalFKCheckSetting int64 originalSQLMode string + originalFKRestrict int64 WorkflowType int32 WorkflowSubType int32 @@ -239,6 +241,10 @@ func (vr *vreplicator) replicate(ctx context.Context) error { } //defensive guard, should be a no-op since it should happen after copy is done defer vr.resetFKCheckAfterCopy(vr.dbClient) + if err := vr.getSettingFKRestrict(); err != nil { + return err + } + defer vr.resetFKRestrictAfterCopy(vr.dbClient) vr.throttleUpdatesRateLimiter = timer.NewRateLimiter(time.Second) defer vr.throttleUpdatesRateLimiter.Stop() @@ -272,6 +278,10 @@ func (vr *vreplicator) replicate(ctx context.Context) error { log.Warningf("Unable to clear FK check %v", err) return err } + if err := vr.clearFKRestrict(vr.dbClient); err != nil { + log.Warningf("Unable to clear FK restrict %v", err) + return err + } if vr.WorkflowSubType == int32(binlogdatapb.VReplicationWorkflowSubType_AtomicCopy) { if err := newVCopier(vr).copyAll(ctx, settings); err != nil { log.Infof("Error atomically copying all tables: %v", err) @@ -301,6 +311,10 @@ func (vr *vreplicator) replicate(ctx context.Context) error { log.Warningf("Unable to reset FK check %v", err) return err } + if err := vr.resetFKRestrictAfterCopy(vr.dbClient); err != nil { + log.Warningf("Unable to reset FK restrict %v", err) + return err + } if vr.source.StopAfterCopy { return vr.setState(binlogdatapb.VReplicationWorkflowState_Stopped, "Stopped after copy.") } @@ -512,11 +526,45 @@ func (vr *vreplicator) getSettingFKCheck() error { return nil } +func (vr *vreplicator) needFKRestrict() bool { + ok, err := vr.dbClient.SupportsCapability(capabilities.RestrictFKOnNonStandardKey) + if err != nil { + return false + } + return ok +} + +func (vr *vreplicator) getSettingFKRestrict() error { + if !vr.needFKRestrict() { + return nil + } + qr, err := vr.dbClient.Execute("select @@session.restrict_fk_on_non_standard_key") + if err != nil { + return err + } + if len(qr.Rows) != 1 || len(qr.Fields) != 1 { + return fmt.Errorf("unable to select @@session.restrict_fk_on_non_standard_key") + } + vr.originalFKRestrict, err = qr.Rows[0][0].ToCastInt64() + if err != nil { + return err + } + return nil +} + func (vr *vreplicator) resetFKCheckAfterCopy(dbClient *vdbClient) error { _, err := dbClient.Execute(fmt.Sprintf("set @@session.foreign_key_checks=%d", vr.originalFKCheckSetting)) return err } +func (vr *vreplicator) resetFKRestrictAfterCopy(dbClient *vdbClient) error { + if !vr.needFKRestrict() { + return nil + } + _, err := dbClient.Execute(fmt.Sprintf("set @@session.restrict_fk_on_non_standard_key=%d", vr.originalFKRestrict)) + return err +} + func (vr *vreplicator) setSQLMode(ctx context.Context, dbClient *vdbClient) (func(), error) { resetFunc := func() {} // First save the original SQL mode if we have not already done so @@ -616,6 +664,14 @@ func (vr *vreplicator) clearFKCheck(dbClient *vdbClient) error { return err } +func (vr *vreplicator) clearFKRestrict(dbClient *vdbClient) error { + if !vr.needFKRestrict() { + return nil + } + _, err := dbClient.Execute("set @@session.restrict_fk_on_non_standard_key=0") + return err +} + func recalculatePKColsInfoByColumnNames(uniqueKeyColumnNames []string, colInfos []*ColumnInfo) (pkColInfos []*ColumnInfo) { pkColInfos = colInfos[:] columnOrderMap := map[string]int64{} @@ -1056,6 +1112,9 @@ func (vr *vreplicator) newClientConnection(ctx context.Context) (*vdbClient, err if err := vr.clearFKCheck(dbClient); err != nil { return nil, vterrors.Wrap(err, "failed to clear foreign key check") } + if err := vr.clearFKRestrict(dbClient); err != nil { + return nil, vterrors.Wrap(err, "failed to clear foreign key restriction") + } return dbClient, nil } diff --git a/go/vt/vttablet/tabletmanager/vreplication/vreplicator_test.go b/go/vt/vttablet/tabletmanager/vreplication/vreplicator_test.go index e4f55cc2384..f6eb3ac5958 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/vreplicator_test.go +++ b/go/vt/vttablet/tabletmanager/vreplication/vreplicator_test.go @@ -481,7 +481,15 @@ func TestDeferSecondaryKeys(t *testing.T) { } // Create the table. - _, err := dbClient.ExecuteFetch(tcase.initialDDL, 1) + if vr.needFKRestrict() { + _, err := dbClient.ExecuteFetch("set @@session.restrict_fk_on_non_standard_key=0", 1) + require.NoError(t, err) + defer func() { + _, err = dbClient.ExecuteFetch("set @@session.restrict_fk_on_non_standard_key=1", 1) + require.NoError(t, err) + }() + } + _, err = dbClient.ExecuteFetch(tcase.initialDDL, 1) require.NoError(t, err) defer func() { _, err = dbClient.ExecuteFetch(fmt.Sprintf("drop table %s.%s", dbName, tcase.tableName), 1) diff --git a/go/vt/vttablet/tabletserver/controller.go b/go/vt/vttablet/tabletserver/controller.go index 4d7e35862de..0336d9a73cc 100644 --- a/go/vt/vttablet/tabletserver/controller.go +++ b/go/vt/vttablet/tabletserver/controller.go @@ -92,6 +92,7 @@ type Controller interface { // CheckThrottler CheckThrottler(ctx context.Context, appName string, flags *throttle.CheckFlags) *throttle.CheckResult + GetThrottlerStatus(ctx context.Context) *throttle.ThrottlerStatus } // Ensure TabletServer satisfies Controller interface. diff --git a/go/vt/vttablet/tabletserver/debugenv.go b/go/vt/vttablet/tabletserver/debugenv.go index 924d5acbebb..54cf09db7d6 100644 --- a/go/vt/vttablet/tabletserver/debugenv.go +++ b/go/vt/vttablet/tabletserver/debugenv.go @@ -152,7 +152,8 @@ func debugEnvHandler(tsv *TabletServer, w http.ResponseWriter, r *http.Request) vars = addVar(vars, "PoolSize", tsv.PoolSize) vars = addVar(vars, "StreamPoolSize", tsv.StreamPoolSize) vars = addVar(vars, "TxPoolSize", tsv.TxPoolSize) - vars = addVar(vars, "QueryCacheCapacity", tsv.QueryPlanCacheCap) + vars = addVar(vars, "QueryCacheCapacity", tsv.QueryPlanCacheCap) // QueryCacheCapacity is deprecated in v21, it is replaced by QueryEnginePlanCacheCapacity + vars = addVar(vars, "QueryEnginePlanCacheCapacity", tsv.QueryPlanCacheCap) vars = addVar(vars, "MaxResultSize", tsv.MaxResultSize) vars = addVar(vars, "WarnResultSize", tsv.WarnResultSize) vars = addVar(vars, "RowStreamerMaxInnoDBTrxHistLen", func() int64 { return tsv.Config().RowStreamer.MaxInnoDBTrxHistLen }) diff --git a/go/vt/vttablet/tabletserver/tx_executor.go b/go/vt/vttablet/tabletserver/dt_executor.go similarity index 55% rename from go/vt/vttablet/tabletserver/tx_executor.go rename to go/vt/vttablet/tabletserver/dt_executor.go index 93d18a200f9..edf4438b8b2 100644 --- a/go/vt/vttablet/tabletserver/tx_executor.go +++ b/go/vt/vttablet/tabletserver/dt_executor.go @@ -20,38 +20,43 @@ import ( "context" "time" - "vitess.io/vitess/go/vt/vttablet/tabletserver/tx" - "vitess.io/vitess/go/trace" "vitess.io/vitess/go/vt/log" - querypb "vitess.io/vitess/go/vt/proto/query" vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" + "vitess.io/vitess/go/vt/vttablet/tabletserver/tx" ) -// TxExecutor is used for executing a transactional request. -// TODO: merge this with tx_engine -type TxExecutor struct { - // TODO(sougou): Parameterize this. +// DTExecutor is used for executing a distributed transactional request. +type DTExecutor struct { ctx context.Context logStats *tabletenv.LogStats te *TxEngine } +// NewDTExecutor creates a new distributed transaction executor. +func NewDTExecutor(ctx context.Context, te *TxEngine, logStats *tabletenv.LogStats) *DTExecutor { + return &DTExecutor{ + ctx: ctx, + te: te, + logStats: logStats, + } +} + // Prepare performs a prepare on a connection including the redo log work. // If there is any failure, an error is returned. No cleanup is performed. // A subsequent call to RollbackPrepared, which is required by the 2PC // protocol, will perform all the cleanup. -func (txe *TxExecutor) Prepare(transactionID int64, dtid string) error { - if !txe.te.twopcEnabled { +func (dte *DTExecutor) Prepare(transactionID int64, dtid string) error { + if !dte.te.twopcEnabled { return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "2pc is not enabled") } - defer txe.te.env.Stats().QueryTimings.Record("PREPARE", time.Now()) - txe.logStats.TransactionID = transactionID + defer dte.te.env.Stats().QueryTimings.Record("PREPARE", time.Now()) + dte.logStats.TransactionID = transactionID - conn, err := txe.te.txPool.GetAndLock(transactionID, "for prepare") + conn, err := dte.te.txPool.GetAndLock(transactionID, "for prepare") if err != nil { return err } @@ -62,14 +67,20 @@ func (txe *TxExecutor) Prepare(transactionID int64, dtid string) error { return nil } - err = txe.te.preparedPool.Put(conn, dtid) + // If the connection is tainted, we cannot prepare it. As there could be temporary tables involved. + if conn.IsTainted() { + conn.Release(tx.TxRollback) + return vterrors.VT12001("cannot prepare the transaction on a reserved connection") + } + + err = dte.te.preparedPool.Put(conn, dtid) if err != nil { - txe.te.txPool.RollbackAndRelease(txe.ctx, conn) + dte.te.txPool.RollbackAndRelease(dte.ctx, conn) return vterrors.Errorf(vtrpcpb.Code_RESOURCE_EXHAUSTED, "prepare failed for transaction %d: %v", transactionID, err) } - return txe.inTransaction(func(localConn *StatefulConnection) error { - return txe.te.twoPC.SaveRedo(txe.ctx, localConn, dtid, conn.TxProperties().Queries) + return dte.inTransaction(func(localConn *StatefulConnection) error { + return dte.te.twoPC.SaveRedo(dte.ctx, localConn, dtid, conn.TxProperties().Queries) }) } @@ -77,12 +88,12 @@ func (txe *TxExecutor) Prepare(transactionID int64, dtid string) error { // CommitPrepared commits a prepared transaction. If the operation // fails, an error counter is incremented and the transaction is // marked as failed in the redo log. -func (txe *TxExecutor) CommitPrepared(dtid string) error { - if !txe.te.twopcEnabled { +func (dte *DTExecutor) CommitPrepared(dtid string) error { + if !dte.te.twopcEnabled { return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "2pc is not enabled") } - defer txe.te.env.Stats().QueryTimings.Record("COMMIT_PREPARED", time.Now()) - conn, err := txe.te.preparedPool.FetchForCommit(dtid) + defer dte.te.env.Stats().QueryTimings.Record("COMMIT_PREPARED", time.Now()) + conn, err := dte.te.preparedPool.FetchForCommit(dtid) if err != nil { return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "cannot commit dtid %s, state: %v", dtid, err) } @@ -91,19 +102,19 @@ func (txe *TxExecutor) CommitPrepared(dtid string) error { } // We have to use a context that will never give up, // even if the original context expires. - ctx := trace.CopySpan(context.Background(), txe.ctx) - defer txe.te.txPool.RollbackAndRelease(ctx, conn) - err = txe.te.twoPC.DeleteRedo(ctx, conn, dtid) + ctx := trace.CopySpan(context.Background(), dte.ctx) + defer dte.te.txPool.RollbackAndRelease(ctx, conn) + err = dte.te.twoPC.DeleteRedo(ctx, conn, dtid) if err != nil { - txe.markFailed(ctx, dtid) + dte.markFailed(ctx, dtid) return err } - _, err = txe.te.txPool.Commit(ctx, conn) + _, err = dte.te.txPool.Commit(ctx, conn) if err != nil { - txe.markFailed(ctx, dtid) + dte.markFailed(ctx, dtid) return err } - txe.te.preparedPool.Forget(dtid) + dte.te.preparedPool.Forget(dtid) return nil } @@ -113,23 +124,23 @@ func (txe *TxExecutor) CommitPrepared(dtid string) error { // state of the transaction in the redo log as failed. If the // state change does not succeed, it just logs the event. // The function uses the passed in context that has no timeout -// instead of TxExecutor's context. -func (txe *TxExecutor) markFailed(ctx context.Context, dtid string) { - txe.te.env.Stats().InternalErrors.Add("TwopcCommit", 1) - txe.te.preparedPool.SetFailed(dtid) - conn, _, _, err := txe.te.txPool.Begin(ctx, &querypb.ExecuteOptions{}, false, 0, nil, nil) +// instead of DTExecutor's context. +func (dte *DTExecutor) markFailed(ctx context.Context, dtid string) { + dte.te.env.Stats().InternalErrors.Add("TwopcCommit", 1) + dte.te.preparedPool.SetFailed(dtid) + conn, _, _, err := dte.te.txPool.Begin(ctx, &querypb.ExecuteOptions{}, false, 0, nil, nil) if err != nil { log.Errorf("markFailed: Begin failed for dtid %s: %v", dtid, err) return } - defer txe.te.txPool.RollbackAndRelease(ctx, conn) + defer dte.te.txPool.RollbackAndRelease(ctx, conn) - if err = txe.te.twoPC.UpdateRedo(ctx, conn, dtid, RedoStateFailed); err != nil { + if err = dte.te.twoPC.UpdateRedo(ctx, conn, dtid, RedoStateFailed); err != nil { log.Errorf("markFailed: UpdateRedo failed for dtid %s: %v", dtid, err) return } - if _, err = txe.te.txPool.Commit(ctx, conn); err != nil { + if _, err = dte.te.txPool.Commit(ctx, conn); err != nil { log.Errorf("markFailed: Commit failed for dtid %s: %v", dtid, err) } } @@ -152,128 +163,135 @@ func (txe *TxExecutor) markFailed(ctx context.Context, dtid string) { // If so, it must be set to 0, and the function will not attempt that // step. If the original transaction is still alive, the transaction // killer will be the one to eventually roll it back. -func (txe *TxExecutor) RollbackPrepared(dtid string, originalID int64) error { - if !txe.te.twopcEnabled { +func (dte *DTExecutor) RollbackPrepared(dtid string, originalID int64) error { + if !dte.te.twopcEnabled { return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "2pc is not enabled") } - defer txe.te.env.Stats().QueryTimings.Record("ROLLBACK_PREPARED", time.Now()) + defer dte.te.env.Stats().QueryTimings.Record("ROLLBACK_PREPARED", time.Now()) defer func() { - if preparedConn := txe.te.preparedPool.FetchForRollback(dtid); preparedConn != nil { - txe.te.txPool.RollbackAndRelease(txe.ctx, preparedConn) + if preparedConn := dte.te.preparedPool.FetchForRollback(dtid); preparedConn != nil { + dte.te.txPool.RollbackAndRelease(dte.ctx, preparedConn) } if originalID != 0 { - txe.te.Rollback(txe.ctx, originalID) + dte.te.Rollback(dte.ctx, originalID) } }() - return txe.inTransaction(func(conn *StatefulConnection) error { - return txe.te.twoPC.DeleteRedo(txe.ctx, conn, dtid) + return dte.inTransaction(func(conn *StatefulConnection) error { + return dte.te.twoPC.DeleteRedo(dte.ctx, conn, dtid) }) } // CreateTransaction creates the metadata for a 2PC transaction. -func (txe *TxExecutor) CreateTransaction(dtid string, participants []*querypb.Target) error { - if !txe.te.twopcEnabled { +func (dte *DTExecutor) CreateTransaction(dtid string, participants []*querypb.Target) error { + if !dte.te.twopcEnabled { return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "2pc is not enabled") } - defer txe.te.env.Stats().QueryTimings.Record("CREATE_TRANSACTION", time.Now()) - return txe.inTransaction(func(conn *StatefulConnection) error { - return txe.te.twoPC.CreateTransaction(txe.ctx, conn, dtid, participants) + defer dte.te.env.Stats().QueryTimings.Record("CREATE_TRANSACTION", time.Now()) + return dte.inTransaction(func(conn *StatefulConnection) error { + return dte.te.twoPC.CreateTransaction(dte.ctx, conn, dtid, participants) }) } // StartCommit atomically commits the transaction along with the // decision to commit the associated 2pc transaction. -func (txe *TxExecutor) StartCommit(transactionID int64, dtid string) error { - if !txe.te.twopcEnabled { +func (dte *DTExecutor) StartCommit(transactionID int64, dtid string) error { + if !dte.te.twopcEnabled { return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "2pc is not enabled") } - defer txe.te.env.Stats().QueryTimings.Record("START_COMMIT", time.Now()) - txe.logStats.TransactionID = transactionID + defer dte.te.env.Stats().QueryTimings.Record("START_COMMIT", time.Now()) + dte.logStats.TransactionID = transactionID - conn, err := txe.te.txPool.GetAndLock(transactionID, "for 2pc commit") + conn, err := dte.te.txPool.GetAndLock(transactionID, "for 2pc commit") if err != nil { return err } - defer txe.te.txPool.RollbackAndRelease(txe.ctx, conn) + defer dte.te.txPool.RollbackAndRelease(dte.ctx, conn) - err = txe.te.twoPC.Transition(txe.ctx, conn, dtid, querypb.TransactionState_COMMIT) + err = dte.te.twoPC.Transition(dte.ctx, conn, dtid, querypb.TransactionState_COMMIT) if err != nil { return err } - _, err = txe.te.txPool.Commit(txe.ctx, conn) + _, err = dte.te.txPool.Commit(dte.ctx, conn) return err } // SetRollback transitions the 2pc transaction to the Rollback state. // If a transaction id is provided, that transaction is also rolled back. -func (txe *TxExecutor) SetRollback(dtid string, transactionID int64) error { - if !txe.te.twopcEnabled { +func (dte *DTExecutor) SetRollback(dtid string, transactionID int64) error { + if !dte.te.twopcEnabled { return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "2pc is not enabled") } - defer txe.te.env.Stats().QueryTimings.Record("SET_ROLLBACK", time.Now()) - txe.logStats.TransactionID = transactionID + defer dte.te.env.Stats().QueryTimings.Record("SET_ROLLBACK", time.Now()) + dte.logStats.TransactionID = transactionID if transactionID != 0 { - txe.te.Rollback(txe.ctx, transactionID) + // If the transaction is still open, it will be rolled back. + // Otherwise, it would have been rolled back by other means, like a timeout or vttablet/mysql restart. + dte.te.Rollback(dte.ctx, transactionID) } - return txe.inTransaction(func(conn *StatefulConnection) error { - return txe.te.twoPC.Transition(txe.ctx, conn, dtid, querypb.TransactionState_ROLLBACK) + return dte.inTransaction(func(conn *StatefulConnection) error { + return dte.te.twoPC.Transition(dte.ctx, conn, dtid, querypb.TransactionState_ROLLBACK) }) } // ConcludeTransaction deletes the 2pc transaction metadata // essentially resolving it. -func (txe *TxExecutor) ConcludeTransaction(dtid string) error { - if !txe.te.twopcEnabled { +func (dte *DTExecutor) ConcludeTransaction(dtid string) error { + if !dte.te.twopcEnabled { return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "2pc is not enabled") } - defer txe.te.env.Stats().QueryTimings.Record("RESOLVE", time.Now()) + defer dte.te.env.Stats().QueryTimings.Record("RESOLVE", time.Now()) - return txe.inTransaction(func(conn *StatefulConnection) error { - return txe.te.twoPC.DeleteTransaction(txe.ctx, conn, dtid) + return dte.inTransaction(func(conn *StatefulConnection) error { + return dte.te.twoPC.DeleteTransaction(dte.ctx, conn, dtid) }) } // ReadTransaction returns the metadata for the specified dtid. -func (txe *TxExecutor) ReadTransaction(dtid string) (*querypb.TransactionMetadata, error) { - if !txe.te.twopcEnabled { +func (dte *DTExecutor) ReadTransaction(dtid string) (*querypb.TransactionMetadata, error) { + if !dte.te.twopcEnabled { return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "2pc is not enabled") } - return txe.te.twoPC.ReadTransaction(txe.ctx, dtid) + return dte.te.twoPC.ReadTransaction(dte.ctx, dtid) } // ReadTwopcInflight returns info about all in-flight 2pc transactions. -func (txe *TxExecutor) ReadTwopcInflight() (distributed []*tx.DistributedTx, prepared, failed []*tx.PreparedTx, err error) { - if !txe.te.twopcEnabled { +func (dte *DTExecutor) ReadTwopcInflight() (distributed []*tx.DistributedTx, prepared, failed []*tx.PreparedTx, err error) { + if !dte.te.twopcEnabled { return nil, nil, nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "2pc is not enabled") } - prepared, failed, err = txe.te.twoPC.ReadAllRedo(txe.ctx) + prepared, failed, err = dte.te.twoPC.ReadAllRedo(dte.ctx) if err != nil { return nil, nil, nil, vterrors.Errorf(vtrpcpb.Code_UNKNOWN, "Could not read redo: %v", err) } - distributed, err = txe.te.twoPC.ReadAllTransactions(txe.ctx) + distributed, err = dte.te.twoPC.ReadAllTransactions(dte.ctx) if err != nil { return nil, nil, nil, vterrors.Errorf(vtrpcpb.Code_UNKNOWN, "Could not read redo: %v", err) } return distributed, prepared, failed, nil } -func (txe *TxExecutor) inTransaction(f func(*StatefulConnection) error) error { - conn, _, _, err := txe.te.txPool.Begin(txe.ctx, &querypb.ExecuteOptions{}, false, 0, nil, nil) +func (dte *DTExecutor) inTransaction(f func(*StatefulConnection) error) error { + conn, _, _, err := dte.te.txPool.Begin(dte.ctx, &querypb.ExecuteOptions{}, false, 0, nil, nil) if err != nil { return err } - defer txe.te.txPool.RollbackAndRelease(txe.ctx, conn) + defer dte.te.txPool.RollbackAndRelease(dte.ctx, conn) err = f(conn) if err != nil { return err } - _, err = txe.te.txPool.Commit(txe.ctx, conn) + _, err = dte.te.txPool.Commit(dte.ctx, conn) if err != nil { return err } return nil } + +// UnresolvedTransactions returns the list of unresolved distributed transactions. +func (dte *DTExecutor) UnresolvedTransactions() ([]*querypb.TransactionMetadata, error) { + return dte.te.twoPC.UnresolvedTransactions(dte.ctx, time.Now().Add(-dte.te.abandonAge)) +} diff --git a/go/vt/vttablet/tabletserver/tx_executor_test.go b/go/vt/vttablet/tabletserver/dt_executor_test.go similarity index 90% rename from go/vt/vttablet/tabletserver/tx_executor_test.go rename to go/vt/vttablet/tabletserver/dt_executor_test.go index c3949240147..448dd63bf5a 100644 --- a/go/vt/vttablet/tabletserver/tx_executor_test.go +++ b/go/vt/vttablet/tabletserver/dt_executor_test.go @@ -31,8 +31,6 @@ import ( "vitess.io/vitess/go/mysql/fakesqldb" "vitess.io/vitess/go/sqltypes" - "vitess.io/vitess/go/vt/vtgate/fakerpcvtgateconn" - "vitess.io/vitess/go/vt/vtgate/vtgateconn" "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" querypb "vitess.io/vitess/go/vt/proto/query" @@ -71,6 +69,22 @@ func TestTxExecutorPrepare(t *testing.T) { require.NoError(t, err) } +// TestTxExecutorPrepareResevedConn tests the case where a reserved connection is used for prepare. +func TestDTExecutorPrepareResevedConn(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + txe, tsv, db := newTestTxExecutor(t, ctx) + defer db.Close() + defer tsv.StopService() + txid := newTxForPrep(ctx, tsv) + + // Reserve a connection + txe.te.Reserve(ctx, nil, txid, nil) + + err := txe.Prepare(txid, "aa") + require.ErrorContains(t, err, "VT12001: unsupported: cannot prepare the transaction on a reserved connection") +} + func TestTxExecutorPrepareNotInTx(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -433,51 +447,41 @@ func TestExecutorReadAllTransactions(t *testing.T) { } } -// These vars and types are used only for TestExecutorResolveTransaction -var dtidCh = make(chan string) - -type FakeVTGateConn struct { - fakerpcvtgateconn.FakeVTGateConn -} - -func (conn *FakeVTGateConn) ResolveTransaction(ctx context.Context, dtid string) error { - dtidCh <- dtid - return nil -} - -func TestExecutorResolveTransaction(t *testing.T) { +// TestTransactionNotifier tests that the transaction notifier is called +// when a transaction watcher receives unresolved transaction count more than zero. +func TestTransactionNotifier(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - protocol := "resolveTest" - oldValue := vtgateconn.GetVTGateProtocol() - vtgateconn.SetVTGateProtocol(protocol) - defer func() { - vtgateconn.SetVTGateProtocol(oldValue) - }() - vtgateconn.RegisterDialer(protocol, func(context.Context, string) (vtgateconn.Impl, error) { - return &FakeVTGateConn{ - FakeVTGateConn: fakerpcvtgateconn.FakeVTGateConn{}, - }, nil - }) + _, tsv, db := newShortAgeExecutor(t, ctx) defer db.Close() defer tsv.StopService() - want := "aa" db.AddQueryPattern( - "select dtid, time_created from _vt\\.dt_state where time_created.*", - &sqltypes.Result{ - Fields: []*querypb.Field{ - {Type: sqltypes.VarChar}, - {Type: sqltypes.Int64}, - }, - Rows: [][]sqltypes.Value{{ - sqltypes.NewVarBinary(want), - sqltypes.NewVarBinary("1"), - }}, - }) - got := <-dtidCh - if got != want { - t.Errorf("ResolveTransaction: %s, want %s", got, want) + "select count\\(\\*\\) from _vt\\.redo_state where time_created.*", + sqltypes.MakeTestResult(sqltypes.MakeTestFields("count(*)", "int64"), "0")) + + // zero unresolved transactions + db.AddQueryPattern( + "select count\\(\\*\\) from _vt\\.dt_state where time_created.*", + sqltypes.MakeTestResult(sqltypes.MakeTestFields("count(*)", "int64"), "0")) + notifyCh := make(chan any) + tsv.te.dxNotify = func() { + notifyCh <- nil + } + select { + case <-notifyCh: + t.Error("unresolved transaction notifier call unexpected") + case <-time.After(1 * time.Second): + } + + // non zero unresolved transactions + db.AddQueryPattern( + "select count\\(\\*\\) from _vt\\.dt_state where time_created.*", + sqltypes.MakeTestResult(sqltypes.MakeTestFields("count(*)", "int64"), "1")) + select { + case <-notifyCh: + case <-time.After(1 * time.Second): + t.Error("unresolved transaction notifier expected but not received") } } @@ -533,7 +537,7 @@ func TestNoTwopc(t *testing.T) { } } -func newTestTxExecutor(t *testing.T, ctx context.Context) (txe *TxExecutor, tsv *TabletServer, db *fakesqldb.DB) { +func newTestTxExecutor(t *testing.T, ctx context.Context) (txe *DTExecutor, tsv *TabletServer, db *fakesqldb.DB) { db = setUpQueryExecutorTest(t) logStats := tabletenv.NewLogStats(ctx, "TestTxExecutor") tsv = newTestTabletServer(ctx, smallTxPool, db) @@ -542,7 +546,7 @@ func newTestTxExecutor(t *testing.T, ctx context.Context) (txe *TxExecutor, tsv db.AddQuery("delete from _vt.redo_state where dtid = 'aa'", &sqltypes.Result{}) db.AddQuery("delete from _vt.redo_statement where dtid = 'aa'", &sqltypes.Result{}) db.AddQuery("update test_table set `name` = 2 where pk = 1 limit 10001", &sqltypes.Result{}) - return &TxExecutor{ + return &DTExecutor{ ctx: ctx, logStats: logStats, te: tsv.te, @@ -550,7 +554,7 @@ func newTestTxExecutor(t *testing.T, ctx context.Context) (txe *TxExecutor, tsv } // newShortAgeExecutor is same as newTestTxExecutor, but shorter transaction abandon age. -func newShortAgeExecutor(t *testing.T, ctx context.Context) (txe *TxExecutor, tsv *TabletServer, db *fakesqldb.DB) { +func newShortAgeExecutor(t *testing.T, ctx context.Context) (txe *DTExecutor, tsv *TabletServer, db *fakesqldb.DB) { db = setUpQueryExecutorTest(t) logStats := tabletenv.NewLogStats(ctx, "TestTxExecutor") tsv = newTestTabletServer(ctx, smallTxPool|shortTwopcAge, db) @@ -559,7 +563,7 @@ func newShortAgeExecutor(t *testing.T, ctx context.Context) (txe *TxExecutor, ts db.AddQuery("delete from _vt.redo_state where dtid = 'aa'", &sqltypes.Result{}) db.AddQuery("delete from _vt.redo_statement where dtid = 'aa'", &sqltypes.Result{}) db.AddQuery("update test_table set `name` = 2 where pk = 1 limit 10001", &sqltypes.Result{}) - return &TxExecutor{ + return &DTExecutor{ ctx: ctx, logStats: logStats, te: tsv.te, @@ -567,11 +571,11 @@ func newShortAgeExecutor(t *testing.T, ctx context.Context) (txe *TxExecutor, ts } // newNoTwopcExecutor is same as newTestTxExecutor, but 2pc disabled. -func newNoTwopcExecutor(t *testing.T, ctx context.Context) (txe *TxExecutor, tsv *TabletServer, db *fakesqldb.DB) { +func newNoTwopcExecutor(t *testing.T, ctx context.Context) (txe *DTExecutor, tsv *TabletServer, db *fakesqldb.DB) { db = setUpQueryExecutorTest(t) logStats := tabletenv.NewLogStats(ctx, "TestTxExecutor") tsv = newTestTabletServer(ctx, noTwopc, db) - return &TxExecutor{ + return &DTExecutor{ ctx: ctx, logStats: logStats, te: tsv.te, diff --git a/go/vt/vttablet/tabletserver/gc/tablegc.go b/go/vt/vttablet/tabletserver/gc/tablegc.go index fced176b027..f1d64aebea3 100644 --- a/go/vt/vttablet/tabletserver/gc/tablegc.go +++ b/go/vt/vttablet/tabletserver/gc/tablegc.go @@ -39,6 +39,7 @@ import ( "vitess.io/vitess/go/vt/vttablet/tabletserver/connpool" "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle" + "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/throttlerapp" ) @@ -138,7 +139,7 @@ type Status struct { // NewTableGC creates a table collector func NewTableGC(env tabletenv.Env, ts *topo.Server, lagThrottler *throttle.Throttler) *TableGC { collector := &TableGC{ - throttlerClient: throttle.NewBackgroundClient(lagThrottler, throttlerapp.TableGCName, throttle.ThrottleCheckPrimaryWrite), + throttlerClient: throttle.NewBackgroundClient(lagThrottler, throttlerapp.TableGCName, base.UndefinedScope), isOpen: 0, env: env, diff --git a/go/vt/vttablet/tabletserver/health_streamer.go b/go/vt/vttablet/tabletserver/health_streamer.go index c13d11df69e..cfc5ea5e974 100644 --- a/go/vt/vttablet/tabletserver/health_streamer.go +++ b/go/vt/vttablet/tabletserver/health_streamer.go @@ -29,7 +29,6 @@ import ( vtschema "vitess.io/vitess/go/vt/schema" "vitess.io/vitess/go/vt/vttablet/tabletserver/schema" - "vitess.io/vitess/go/vt/dbconfigs" "vitess.io/vitess/go/vt/servenv" "vitess.io/vitess/go/history" @@ -39,7 +38,6 @@ import ( vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vttablet/tabletmanager/vreplication" - "vitess.io/vitess/go/vt/vttablet/tabletserver/connpool" "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" ) @@ -79,23 +77,12 @@ type healthStreamer struct { se *schema.Engine history *history.History - dbConfig dbconfigs.Connector - conns *connpool.Pool signalWhenSchemaChange bool - reloadTimeout time.Duration viewsEnabled bool } func newHealthStreamer(env tabletenv.Env, alias *topodatapb.TabletAlias, engine *schema.Engine) *healthStreamer { - var pool *connpool.Pool - if env.Config().SignalWhenSchemaChange { - // We need one connection for the reloader. - pool = connpool.NewPool(env, "", tabletenv.ConnPoolConfig{ - Size: 1, - IdleTimeout: env.Config().OltpReadPool.IdleTimeout, - }) - } hs := &healthStreamer{ stats: env.Stats(), degradedThreshold: env.Config().Healthcheck.DegradedThreshold, @@ -110,9 +97,7 @@ func newHealthStreamer(env tabletenv.Env, alias *topodatapb.TabletAlias, engine }, history: history.New(5), - conns: pool, signalWhenSchemaChange: env.Config().SignalWhenSchemaChange, - reloadTimeout: env.Config().SchemaChangeReloadTimeout, viewsEnabled: env.Config().EnableViews, se: engine, } @@ -120,9 +105,8 @@ func newHealthStreamer(env tabletenv.Env, alias *topodatapb.TabletAlias, engine return hs } -func (hs *healthStreamer) InitDBConfig(target *querypb.Target, cp dbconfigs.Connector) { +func (hs *healthStreamer) InitDBConfig(target *querypb.Target) { hs.state.Target = target.CloneVT() - hs.dbConfig = cp } func (hs *healthStreamer) Open() { @@ -133,10 +117,6 @@ func (hs *healthStreamer) Open() { return } hs.ctx, hs.cancel = context.WithCancel(context.Background()) - if hs.conns != nil { - // if we don't have a live conns object, it means we are not configured to signal when the schema changes - hs.conns.Open(hs.dbConfig, hs.dbConfig, hs.dbConfig) - } } func (hs *healthStreamer) Close() { @@ -148,10 +128,6 @@ func (hs *healthStreamer) Close() { hs.cancel() hs.cancel = nil } - if hs.conns != nil { - hs.conns.Close() - hs.conns = nil - } } func (hs *healthStreamer) Stream(ctx context.Context, callback func(*querypb.StreamHealthResponse) error) error { @@ -338,16 +314,6 @@ func (hs *healthStreamer) reload(created, altered, dropped []*schema.Table, udfs return nil } - // add a timeout to prevent unbounded waits - ctx, cancel := context.WithTimeout(hs.ctx, hs.reloadTimeout) - defer cancel() - - conn, err := hs.conns.Get(ctx, nil) - if err != nil { - return err - } - defer conn.Recycle() - // We create lists to store the tables that have schema changes. var tables []string var views []string @@ -380,3 +346,18 @@ func (hs *healthStreamer) reload(created, altered, dropped []*schema.Table, udfs hs.state.RealtimeStats.UdfsChanged = false return nil } + +// sendUnresolvedTransactionSignal sends broadcast message about unresolved transactions. +func (hs *healthStreamer) sendUnresolvedTransactionSignal() { + hs.mu.Lock() + defer hs.mu.Unlock() + // send signal only when primary is serving. + if !hs.isServingPrimary { + return + } + + hs.state.RealtimeStats.TxUnresolved = true + shr := hs.state.CloneVT() + hs.broadCastToClients(shr) + hs.state.RealtimeStats.TxUnresolved = false +} diff --git a/go/vt/vttablet/tabletserver/health_streamer_test.go b/go/vt/vttablet/tabletserver/health_streamer_test.go index a97f64c77c6..95517880339 100644 --- a/go/vt/vttablet/tabletserver/health_streamer_test.go +++ b/go/vt/vttablet/tabletserver/health_streamer_test.go @@ -32,7 +32,6 @@ import ( "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/mysql/fakesqldb" "vitess.io/vitess/go/sqltypes" - "vitess.io/vitess/go/vt/dbconfigs" querypb "vitess.io/vitess/go/vt/proto/query" topodatapb "vitess.io/vitess/go/vt/proto/topodata" "vitess.io/vitess/go/vt/vtenv" @@ -41,9 +40,7 @@ import ( ) func TestHealthStreamerClosed(t *testing.T) { - db := fakesqldb.New(t) - defer db.Close() - cfg := newConfig(db) + cfg := newConfig(nil) env := tabletenv.NewEnv(vtenv.NewTestEnv(), cfg, "ReplTrackerTest") alias := &topodatapb.TabletAlias{ Cell: "cell", @@ -59,18 +56,16 @@ func TestHealthStreamerClosed(t *testing.T) { func newConfig(db *fakesqldb.DB) *tabletenv.TabletConfig { cfg := tabletenv.NewDefaultConfig() - cfg.DB = newDBConfigs(db) + if db != nil { + cfg.DB = newDBConfigs(db) + } return cfg } // TestNotServingPrimaryNoWrite makes sure that the health-streamer doesn't write anything to the database when // the state is not serving primary. func TestNotServingPrimaryNoWrite(t *testing.T) { - db := fakesqldb.New(t) - defer db.Close() - cfg := newConfig(db) - cfg.SignalWhenSchemaChange = true - + cfg := newConfig(nil) env := tabletenv.NewEnv(vtenv.NewTestEnv(), cfg, "TestNotServingPrimary") alias := &topodatapb.TabletAlias{ Cell: "cell", @@ -79,11 +74,8 @@ func TestNotServingPrimaryNoWrite(t *testing.T) { // Create a new health streamer and set it to a serving primary state hs := newHealthStreamer(env, alias, &schema.Engine{}) hs.isServingPrimary = true - hs.InitDBConfig(&querypb.Target{TabletType: topodatapb.TabletType_PRIMARY}, cfg.DB.DbaWithDB()) hs.Open() defer hs.Close() - target := &querypb.Target{} - hs.InitDBConfig(target, dbconfigs.New(db.ConnParams())) // Let's say the tablet goes to a non-serving primary state. hs.MakePrimary(false) @@ -93,13 +85,10 @@ func TestNotServingPrimaryNoWrite(t *testing.T) { t1 := schema.NewTable("t1", schema.NoType) err := hs.reload([]*schema.Table{t1}, nil, nil, false) require.NoError(t, err) - require.NoError(t, db.LastError()) } func TestHealthStreamerBroadcast(t *testing.T) { - db := fakesqldb.New(t) - defer db.Close() - cfg := newConfig(db) + cfg := newConfig(nil) cfg.SignalWhenSchemaChange = false env := tabletenv.NewEnv(vtenv.NewTestEnv(), cfg, "ReplTrackerTest") @@ -109,11 +98,8 @@ func TestHealthStreamerBroadcast(t *testing.T) { } blpFunc = testBlpFunc hs := newHealthStreamer(env, alias, &schema.Engine{}) - hs.InitDBConfig(&querypb.Target{TabletType: topodatapb.TabletType_PRIMARY}, cfg.DB.DbaWithDB()) hs.Open() defer hs.Close() - target := &querypb.Target{} - hs.InitDBConfig(target, dbconfigs.New(db.ConnParams())) ch, cancel := testStream(hs) defer cancel() @@ -226,9 +212,6 @@ func TestReloadSchema(t *testing.T) { se := schema.NewEngine(env) hs := newHealthStreamer(env, alias, se) - target := &querypb.Target{TabletType: topodatapb.TabletType_PRIMARY} - configs := cfg.DB - db.AddQueryPattern("SELECT UNIX_TIMESTAMP()"+".*", sqltypes.MakeTestResult( sqltypes.MakeTestFields( "UNIX_TIMESTAMP(now())", @@ -282,8 +265,7 @@ func TestReloadSchema(t *testing.T) { "users|id", )) - hs.InitDBConfig(target, configs.DbaWithDB()) - se.InitDBConfig(configs.DbaWithDB()) + se.InitDBConfig(cfg.DB.DbaWithDB()) hs.Open() defer hs.Close() err := se.Open() @@ -350,7 +332,6 @@ func TestReloadView(t *testing.T) { db := fakesqldb.New(t) defer db.Close() cfg := newConfig(db) - cfg.SignalWhenSchemaChange = true cfg.SchemaReloadInterval = 100 * time.Millisecond cfg.EnableViews = true @@ -359,9 +340,6 @@ func TestReloadView(t *testing.T) { se := schema.NewEngine(env) hs := newHealthStreamer(env, alias, se) - target := &querypb.Target{TabletType: topodatapb.TabletType_PRIMARY} - configs := cfg.DB - db.AddQueryPattern("SELECT UNIX_TIMESTAMP()"+".*", sqltypes.MakeTestResult( sqltypes.MakeTestFields( "UNIX_TIMESTAMP(now())", @@ -411,8 +389,7 @@ func TestReloadView(t *testing.T) { // adding query pattern for udfs db.AddQueryPattern("SELECT name.*", &sqltypes.Result{}) - hs.InitDBConfig(target, configs.DbaWithDB()) - se.InitDBConfig(configs.DbaWithDB()) + se.InitDBConfig(cfg.DB.DbaWithDB()) hs.Open() defer hs.Close() err := se.Open() diff --git a/go/vt/vttablet/tabletserver/query_engine.go b/go/vt/vttablet/tabletserver/query_engine.go index 46b08b5d83d..d0542165878 100644 --- a/go/vt/vttablet/tabletserver/query_engine.go +++ b/go/vt/vttablet/tabletserver/query_engine.go @@ -188,7 +188,8 @@ type QueryEngine struct { // stats // Note: queryErrorCountsWithCode is similar to queryErrorCounts except it contains error code as an additional dimension queryCounts, queryCountsWithTabletType, queryTimes, queryErrorCounts, queryErrorCountsWithCode, queryRowsAffected, queryRowsReturned, queryTextCharsProcessed *stats.CountersWithMultiLabels - queryCacheHits, queryCacheMisses *stats.CounterFunc + queryEnginePlanCacheHits, queryEnginePlanCacheMisses *stats.CounterFunc + queryCacheHitsDeprecated, queryCacheMissesDeprecated *stats.CounterFunc // stats flags enablePerWorkloadTableMetrics bool @@ -269,22 +270,51 @@ func NewQueryEngine(env tabletenv.Env, se *schema.Engine) *QueryEngine { env.Exporter().NewGaugeFunc("StreamBufferSize", "Query engine stream buffer size", qe.streamBufferSize.Load) env.Exporter().NewCounterFunc("TableACLExemptCount", "Query engine table ACL exempt count", qe.tableaclExemptCount.Load) - env.Exporter().NewGaugeFunc("QueryCacheLength", "Query engine query cache length", func() int64 { + // QueryCacheLength is deprecated in v21 and will be removed in >=v22. This metric is replaced by QueryEnginePlanCacheLength. + env.Exporter().NewGaugeFunc("QueryCacheLength", "Query engine query plan cache length (deprecated: please use QueryEnginePlanCacheLength)", func() int64 { return int64(qe.plans.Len()) }) - env.Exporter().NewGaugeFunc("QueryCacheSize", "Query engine query cache size", func() int64 { + env.Exporter().NewGaugeFunc("QueryEnginePlanCacheLength", "Query engine query plan cache length", func() int64 { + return int64(qe.plans.Len()) + }) + + // QueryCacheSize is deprecated in v21 and will be removed in >=v22. This metric is replaced QueryEnginePlanCacheSize. + env.Exporter().NewGaugeFunc("QueryCacheSize", "Query engine query plan cache size (deprecated: please use QueryEnginePlanCacheSize)", func() int64 { + return int64(qe.plans.UsedCapacity()) + }) + env.Exporter().NewGaugeFunc("QueryEnginePlanCacheSize", "Query engine query plan cache size", func() int64 { return int64(qe.plans.UsedCapacity()) }) - env.Exporter().NewGaugeFunc("QueryCacheCapacity", "Query engine query cache capacity", func() int64 { + + // QueryCacheCapacity is deprecated in v21 and will be removed in >=v22. This metric is replaced by QueryEnginePlanCacheCapacity. + env.Exporter().NewGaugeFunc("QueryCacheCapacity", "Query engine query plan cache capacity (deprecated: please use QueryEnginePlanCacheCapacity)", func() int64 { + return int64(qe.plans.MaxCapacity()) + }) + env.Exporter().NewGaugeFunc("QueryEnginePlanCacheCapacity", "Query engine query plan cache capacity", func() int64 { return int64(qe.plans.MaxCapacity()) }) - env.Exporter().NewCounterFunc("QueryCacheEvictions", "Query engine query cache evictions", func() int64 { + + // QueryCacheEvictions is deprecated in v21 and will be removed in >=v22. This metric is replaced by QueryEnginePlanCacheEvictions. + env.Exporter().NewCounterFunc("QueryCacheEvictions", "Query engine query plan cache evictions (deprecated: please use QueryEnginePlanCacheEvictions)", func() int64 { return qe.plans.Metrics.Evicted() }) - qe.queryCacheHits = env.Exporter().NewCounterFunc("QueryCacheHits", "Query engine query cache hits", func() int64 { + env.Exporter().NewCounterFunc("QueryEnginePlanCacheEvictions", "Query engine query plan cache evictions", func() int64 { + return qe.plans.Metrics.Evicted() + }) + + // QueryCacheHits is deprecated in v21 and will be removed in >=v22. This metric is replaced by QueryEnginePlanCacheHits. + qe.queryCacheHitsDeprecated = env.Exporter().NewCounterFunc("QueryCacheHits", "Query engine query plan cache hits (deprecated: please use QueryEnginePlanCacheHits)", func() int64 { + return qe.plans.Metrics.Hits() + }) + qe.queryEnginePlanCacheHits = env.Exporter().NewCounterFunc("QueryEnginePlanCacheHits", "Query engine query plan cache hits", func() int64 { return qe.plans.Metrics.Hits() }) - qe.queryCacheMisses = env.Exporter().NewCounterFunc("QueryCacheMisses", "Query engine query cache misses", func() int64 { + + // QueryCacheMisses is deprecated in v21 and will be removed in >=v22. This metric is replaced by QueryEnginePlanCacheMisses. + qe.queryCacheMissesDeprecated = env.Exporter().NewCounterFunc("QueryCacheMisses", "Query engine query plan cache misses (deprecated: please use QueryEnginePlanCacheMisses)", func() int64 { + return qe.plans.Metrics.Misses() + }) + qe.queryEnginePlanCacheMisses = env.Exporter().NewCounterFunc("QueryEnginePlanCacheMisses", "Query engine query plan cache misses", func() int64 { return qe.plans.Metrics.Misses() }) diff --git a/go/vt/vttablet/tabletserver/query_engine_test.go b/go/vt/vttablet/tabletserver/query_engine_test.go index 199dc0cf334..a1c293ea8ba 100644 --- a/go/vt/vttablet/tabletserver/query_engine_test.go +++ b/go/vt/vttablet/tabletserver/query_engine_test.go @@ -197,8 +197,10 @@ func TestQueryPlanCache(t *testing.T) { ctx := context.Background() logStats := tabletenv.NewLogStats(ctx, "GetPlanStats") - initialHits := qe.queryCacheHits.Get() - initialMisses := qe.queryCacheMisses.Get() + initialHits := qe.queryEnginePlanCacheHits.Get() + initialMisses := qe.queryEnginePlanCacheMisses.Get() + initialHitsDeprecated := qe.queryCacheHitsDeprecated.Get() + initialMissesDeprecated := qe.queryCacheMissesDeprecated.Get() firstPlan, err := qe.GetPlan(ctx, logStats, firstQuery, false) require.NoError(t, err) @@ -206,8 +208,11 @@ func TestQueryPlanCache(t *testing.T) { assertPlanCacheSize(t, qe, 1) - require.Equal(t, int64(0), qe.queryCacheHits.Get()-initialHits) - require.Equal(t, int64(1), qe.queryCacheMisses.Get()-initialMisses) + require.Equal(t, int64(0), qe.queryEnginePlanCacheHits.Get()-initialHits) + require.Equal(t, int64(1), qe.queryEnginePlanCacheMisses.Get()-initialMisses) + + require.Equal(t, int64(0), qe.queryCacheHitsDeprecated.Get()-initialHitsDeprecated) + require.Equal(t, int64(1), qe.queryCacheMissesDeprecated.Get()-initialMissesDeprecated) secondPlan, err := qe.GetPlan(ctx, logStats, firstQuery, false) require.NoError(t, err) @@ -215,8 +220,11 @@ func TestQueryPlanCache(t *testing.T) { assertPlanCacheSize(t, qe, 1) - require.Equal(t, int64(1), qe.queryCacheHits.Get()-initialHits) - require.Equal(t, int64(1), qe.queryCacheMisses.Get()-initialMisses) + require.Equal(t, int64(1), qe.queryEnginePlanCacheHits.Get()-initialHits) + require.Equal(t, int64(1), qe.queryEnginePlanCacheMisses.Get()-initialMisses) + + require.Equal(t, int64(1), qe.queryCacheHitsDeprecated.Get()-initialHitsDeprecated) + require.Equal(t, int64(1), qe.queryCacheMissesDeprecated.Get()-initialMissesDeprecated) qe.ClearQueryPlanCache() } diff --git a/go/vt/vttablet/tabletserver/query_executor.go b/go/vt/vttablet/tabletserver/query_executor.go index 86269050418..02b8dd9171a 100644 --- a/go/vt/vttablet/tabletserver/query_executor.go +++ b/go/vt/vttablet/tabletserver/query_executor.go @@ -203,7 +203,7 @@ func (qre *QueryExecutor) Execute() (reply *sqltypes.Result, err error) { case p.PlanRevertMigration: return qre.execRevertMigration() case p.PlanShowMigrations: - return qre.execShowMigrations() + return qre.execShowMigrations(nil) case p.PlanShowMigrationLogs: return qre.execShowMigrationLogs() case p.PlanShowThrottledApps: @@ -308,6 +308,8 @@ func (qre *QueryExecutor) txConnExec(conn *StatefulConnection) (*sqltypes.Result return qre.execLoad(conn) case p.PlanCallProc: return qre.execProc(conn) + case p.PlanShowMigrations: + return qre.execShowMigrations(conn) } return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "[BUG] %s unexpected plan type", qre.plan.PlanID.String()) } @@ -923,6 +925,8 @@ func (qre *QueryExecutor) execAlterMigration() (*sqltypes.Result, error) { return qre.tsv.onlineDDLExecutor.RetryMigration(qre.ctx, alterMigration.UUID) case sqlparser.CleanupMigrationType: return qre.tsv.onlineDDLExecutor.CleanupMigration(qre.ctx, alterMigration.UUID) + case sqlparser.CleanupAllMigrationType: + return qre.tsv.onlineDDLExecutor.CleanupAllMigrations(qre.ctx) case sqlparser.LaunchMigrationType: return qre.tsv.onlineDDLExecutor.LaunchMigration(qre.ctx, alterMigration.UUID, alterMigration.Shards) case sqlparser.LaunchAllMigrationType: @@ -958,7 +962,7 @@ func (qre *QueryExecutor) execRevertMigration() (*sqltypes.Result, error) { return qre.tsv.onlineDDLExecutor.SubmitMigration(qre.ctx, qre.plan.FullStmt) } -func (qre *QueryExecutor) execShowMigrations() (*sqltypes.Result, error) { +func (qre *QueryExecutor) execShowMigrations(conn *StatefulConnection) (*sqltypes.Result, error) { if showStmt, ok := qre.plan.FullStmt.(*sqlparser.Show); ok { return qre.tsv.onlineDDLExecutor.ShowMigrations(qre.ctx, showStmt) } diff --git a/go/vt/vttablet/tabletserver/query_executor_test.go b/go/vt/vttablet/tabletserver/query_executor_test.go index c4f3ed1b00c..771d9e3479d 100644 --- a/go/vt/vttablet/tabletserver/query_executor_test.go +++ b/go/vt/vttablet/tabletserver/query_executor_test.go @@ -1513,7 +1513,6 @@ func newTestTabletServer(ctx context.Context, flags executorFlags, db *fakesqldb } else { cfg.EnableOnlineDDL = true } - cfg.TwoPCCoordinatorAddress = "fake" if flags&shortTwopcAge > 0 { cfg.TwoPCAbandonAge = 0.5 } else { @@ -1704,10 +1703,10 @@ func addQueryExecutorSupportedQueries(db *fakesqldb.DB) { mysql.ShowPrimaryRow("msg", "id"), }, }, - "begin": {}, - "commit": {}, - "rollback": {}, - fmt.Sprintf(sqlReadAllRedo, "_vt", "_vt"): {}, + "begin": {}, + "commit": {}, + "rollback": {}, + fmt.Sprintf(readAllRedo, "_vt", "_vt"): {}, } sidecardb.AddSchemaInitQueries(db, true, sqlparser.NewTestParser()) diff --git a/go/vt/vttablet/tabletserver/repltracker/repltracker.go b/go/vt/vttablet/tabletserver/repltracker/repltracker.go index c98005851d1..59d2db128da 100644 --- a/go/vt/vttablet/tabletserver/repltracker/repltracker.go +++ b/go/vt/vttablet/tabletserver/repltracker/repltracker.go @@ -52,8 +52,7 @@ var ( // ReplTracker tracks replication lag. type ReplTracker struct { - mode string - forceHeartbeat bool + mode string mu sync.Mutex isPrimary bool @@ -66,11 +65,10 @@ type ReplTracker struct { // NewReplTracker creates a new ReplTracker. func NewReplTracker(env tabletenv.Env, alias *topodatapb.TabletAlias) *ReplTracker { return &ReplTracker{ - mode: env.Config().ReplicationTracker.Mode, - forceHeartbeat: env.Config().ReplicationTracker.HeartbeatOnDemand > 0, - hw: newHeartbeatWriter(env, alias), - hr: newHeartbeatReader(env), - poller: &poller{}, + mode: env.Config().ReplicationTracker.Mode, + hw: newHeartbeatWriter(env, alias), + hr: newHeartbeatReader(env), + poller: &poller{}, } } @@ -97,9 +95,7 @@ func (rt *ReplTracker) MakePrimary() { rt.hr.Close() rt.hw.Open() } - if rt.forceHeartbeat { - rt.hw.Open() - } + rt.hw.Open() } // MakeNonPrimary must be called if the tablet type becomes non-PRIMARY. @@ -117,9 +113,7 @@ func (rt *ReplTracker) MakeNonPrimary() { // Run the status once to pre-initialize values. rt.poller.Status() } - if rt.forceHeartbeat { - rt.hw.Close() - } + rt.hw.Close() } // Close closes ReplTracker. @@ -147,5 +141,9 @@ func (rt *ReplTracker) Status() (time.Duration, error) { // EnableHeartbeat enables or disables writes of heartbeat. This functionality // is only used by tests. func (rt *ReplTracker) EnableHeartbeat(enable bool) { - rt.hw.enableWrites(enable) + if enable { + rt.hw.enableWrites() + } else { + rt.hw.disableWrites() + } } diff --git a/go/vt/vttablet/tabletserver/repltracker/repltracker_test.go b/go/vt/vttablet/tabletserver/repltracker/repltracker_test.go index 5e6150ddeb3..40827fdcbda 100644 --- a/go/vt/vttablet/tabletserver/repltracker/repltracker_test.go +++ b/go/vt/vttablet/tabletserver/repltracker/repltracker_test.go @@ -22,6 +22,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "vitess.io/vitess/go/mysql/fakesqldb" "vitess.io/vitess/go/vt/dbconfigs" @@ -50,49 +51,89 @@ func TestReplTracker(t *testing.T) { target := &querypb.Target{} mysqld := mysqlctl.NewFakeMysqlDaemon(nil) - rt := NewReplTracker(env, alias) - rt.InitDBConfig(target, mysqld) - assert.Equal(t, tabletenv.Heartbeat, rt.mode) - assert.True(t, rt.hw.enabled) - assert.True(t, rt.hr.enabled) - - rt.MakePrimary() - assert.True(t, rt.hw.isOpen) - assert.False(t, rt.hr.isOpen) - assert.True(t, rt.isPrimary) - - lag, err := rt.Status() - assert.NoError(t, err) - assert.Equal(t, time.Duration(0), lag) - - rt.MakeNonPrimary() - assert.False(t, rt.hw.isOpen) - assert.True(t, rt.hr.isOpen) - assert.False(t, rt.isPrimary) - - rt.hr.lastKnownLag = 1 * time.Second - lag, err = rt.Status() - assert.NoError(t, err) - assert.Equal(t, 1*time.Second, lag) - - rt.Close() - assert.False(t, rt.hw.isOpen) - assert.False(t, rt.hr.isOpen) - - cfg.ReplicationTracker.Mode = tabletenv.Polling - rt = NewReplTracker(env, alias) - rt.InitDBConfig(target, mysqld) - assert.Equal(t, tabletenv.Polling, rt.mode) - assert.Equal(t, mysqld, rt.poller.mysqld) - assert.False(t, rt.hw.enabled) - assert.False(t, rt.hr.enabled) - - rt.MakeNonPrimary() - assert.False(t, rt.hw.isOpen) - assert.False(t, rt.hr.isOpen) - assert.False(t, rt.isPrimary) - - mysqld.ReplicationStatusError = errors.New("err") - _, err = rt.Status() - assert.Equal(t, "err", err.Error()) + t.Run("always-on heartbeat", func(t *testing.T) { + rt := NewReplTracker(env, alias) + rt.InitDBConfig(target, mysqld) + assert.Equal(t, tabletenv.Heartbeat, rt.mode) + assert.Equal(t, HeartbeatConfigTypeAlways, rt.hw.configType) + assert.Zero(t, rt.hw.onDemandDuration) + assert.True(t, rt.hr.enabled) + + rt.MakePrimary() + assert.True(t, rt.hw.isOpen) + assert.False(t, rt.hr.isOpen) + assert.True(t, rt.isPrimary) + + lag, err := rt.Status() + assert.NoError(t, err) + assert.Equal(t, time.Duration(0), lag) + + rt.MakeNonPrimary() + assert.False(t, rt.hw.isOpen) + assert.True(t, rt.hr.isOpen) + assert.False(t, rt.isPrimary) + + rt.hr.lastKnownLag = 1 * time.Second + lag, err = rt.Status() + assert.NoError(t, err) + assert.Equal(t, 1*time.Second, lag) + + rt.Close() + assert.False(t, rt.hw.isOpen) + assert.False(t, rt.hr.isOpen) + }) + t.Run("disabled heartbeat", func(t *testing.T) { + cfg.ReplicationTracker.Mode = tabletenv.Polling + rt := NewReplTracker(env, alias) + rt.InitDBConfig(target, mysqld) + assert.Equal(t, tabletenv.Polling, rt.mode) + assert.Equal(t, mysqld, rt.poller.mysqld) + assert.Equal(t, HeartbeatConfigTypeNone, rt.hw.configType) + require.NotZero(t, defaultOnDemandDuration) + assert.Equal(t, defaultOnDemandDuration, rt.hw.onDemandDuration) + assert.False(t, rt.hr.enabled) + + rt.MakeNonPrimary() + assert.False(t, rt.hw.isOpen) + assert.False(t, rt.hr.isOpen) + assert.False(t, rt.isPrimary) + + mysqld.ReplicationStatusError = errors.New("err") + _, err := rt.Status() + assert.Equal(t, "err", err.Error()) + }) + t.Run("on-demand heartbeat", func(t *testing.T) { + cfg.ReplicationTracker.Mode = tabletenv.Heartbeat + cfg.ReplicationTracker.HeartbeatOnDemand = time.Second + + rt := NewReplTracker(env, alias) + rt.InitDBConfig(target, mysqld) + assert.Equal(t, tabletenv.Heartbeat, rt.mode) + assert.Equal(t, HeartbeatConfigTypeOnDemand, rt.hw.configType) + assert.Equal(t, minimalOnDemandDuration, rt.hw.onDemandDuration) + assert.True(t, rt.hr.enabled) + + rt.MakePrimary() + assert.True(t, rt.hw.isOpen) + assert.False(t, rt.hr.isOpen) + assert.True(t, rt.isPrimary) + + lag, err := rt.Status() + assert.NoError(t, err) + assert.Equal(t, time.Duration(0), lag) + + rt.MakeNonPrimary() + assert.False(t, rt.hw.isOpen) + assert.True(t, rt.hr.isOpen) + assert.False(t, rt.isPrimary) + + rt.hr.lastKnownLag = 1 * time.Second + lag, err = rt.Status() + assert.NoError(t, err) + assert.Equal(t, 1*time.Second, lag) + + rt.Close() + assert.False(t, rt.hw.isOpen) + assert.False(t, rt.hr.isOpen) + }) } diff --git a/go/vt/vttablet/tabletserver/repltracker/writer.go b/go/vt/vttablet/tabletserver/repltracker/writer.go index a72b44d1845..11492fa92e4 100644 --- a/go/vt/vttablet/tabletserver/repltracker/writer.go +++ b/go/vt/vttablet/tabletserver/repltracker/writer.go @@ -38,52 +38,87 @@ import ( topodatapb "vitess.io/vitess/go/vt/proto/topodata" ) +// We identify these heartbeat configuration types: +// - No configuration: the heartbeat writer is generally disabled and does not produce heartbeats (but see below). +// - On-demand: on-demand heartbeat interval was specified. +// - Always: the heartbeat writer is always on and produces heartbeats at a regular interval. +type HeartbeatConfigType int + +const ( + HeartbeatConfigTypeNone HeartbeatConfigType = iota + HeartbeatConfigTypeOnDemand + HeartbeatConfigTypeAlways +) + const ( - sqlUpsertHeartbeat = "INSERT INTO %s.heartbeat (ts, tabletUid, keyspaceShard) VALUES (%a, %a, %a) ON DUPLICATE KEY UPDATE ts=VALUES(ts), tabletUid=VALUES(tabletUid)" + sqlUpsertHeartbeat = "INSERT INTO %s.heartbeat (ts, tabletUid, keyspaceShard) VALUES (%a, %a, %a) ON DUPLICATE KEY UPDATE ts=VALUES(ts), tabletUid=VALUES(tabletUid)" + minimalOnDemandDuration = 4 * time.Second +) + +var ( + // Can be overridden by unit tests + defaultOnDemandDuration = 10 * time.Second + defaultHeartbeatInterval = 1 * time.Second ) // heartbeatWriter runs on primary tablets and writes heartbeats to the heartbeat -// table at a regular interval, defined by heartbeat_interval. +// table, depending on the configuration: +// - HeartbeatConfigTypeAlways: while open, the writer produces heartbeats at a regular interval. +// RequetHeartbeats() is meaningless in this mode. +// - HeartbeatConfigTypeOnDemand: when opened, the writer produces heartbeats for the configured lease. +// The heartbeats then expire. Lease can be renewed (after expired) or extended (while running) via +// RequetHeartbeats(). +// - HeartbeatConfigTypeNone: the writer does not initiate any heartbeats. However, RequetHeartbeats() +// can be called to request a heartbeat lease. The lease duration is predetermined as `defaultOnDemandDuration`. type heartbeatWriter struct { env tabletenv.Env - enabled bool + configType HeartbeatConfigType interval time.Duration tabletAlias *topodatapb.TabletAlias keyspaceShard string now func() time.Time errorLog *logutil.ThrottledLogger - mu sync.Mutex - isOpen bool - appPool *dbconnpool.ConnectionPool - allPrivsPool *dbconnpool.ConnectionPool - ticks *timer.Timer - writeConnID atomic.Int64 - - onDemandDuration time.Duration - onDemandMu sync.Mutex - concurrentHeartbeatRequests int64 - onDemandRequestTicks int64 - onDemandLastRequestTick int64 + mu sync.Mutex + isOpen bool + appPool *dbconnpool.ConnectionPool + allPrivsPool *dbconnpool.ConnectionPool + ticks *timer.Timer + onDemandRequestsRateLimiter atomic.Pointer[timer.RateLimiter] + writeConnID atomic.Int64 + + onDemandDuration time.Duration } // newHeartbeatWriter creates a new heartbeatWriter. func newHeartbeatWriter(env tabletenv.Env, alias *topodatapb.TabletAlias) *heartbeatWriter { config := env.Config() - // config.EnableLagThrottler is a feature flag for the throttler; if throttler runs, then heartbeat must also run - if config.ReplicationTracker.Mode != tabletenv.Heartbeat && config.ReplicationTracker.HeartbeatOnDemand == 0 { - return &heartbeatWriter{} + configType := HeartbeatConfigTypeNone + onDemandDuration := defaultOnDemandDuration + switch { + case config.ReplicationTracker.HeartbeatOnDemand > 0: + configType = HeartbeatConfigTypeOnDemand + onDemandDuration = config.ReplicationTracker.HeartbeatOnDemand + if onDemandDuration < minimalOnDemandDuration { + onDemandDuration = minimalOnDemandDuration + } + case config.ReplicationTracker.Mode == tabletenv.Heartbeat: + configType = HeartbeatConfigTypeAlways + onDemandDuration = 0 } heartbeatInterval := config.ReplicationTracker.HeartbeatInterval + if heartbeatInterval == 0 { + heartbeatInterval = defaultHeartbeatInterval + } w := &heartbeatWriter{ env: env, - enabled: true, + configType: configType, tabletAlias: alias.CloneVT(), now: time.Now, interval: heartbeatInterval, - onDemandDuration: config.ReplicationTracker.HeartbeatOnDemand, + onDemandDuration: onDemandDuration, ticks: timer.NewTimer(heartbeatInterval), errorLog: logutil.NewThrottledLogger("HeartbeatWriter", 60*time.Second), // We make this pool size 2; to prevent pool exhausted @@ -91,21 +126,8 @@ func newHeartbeatWriter(env tabletenv.Env, alias *topodatapb.TabletAlias) *heart appPool: dbconnpool.NewConnectionPool("HeartbeatWriteAppPool", env.Exporter(), 2, mysqlctl.DbaIdleTimeout, 0, mysqlctl.PoolDynamicHostnameResolution), allPrivsPool: dbconnpool.NewConnectionPool("HeartbeatWriteAllPrivsPool", env.Exporter(), 2, mysqlctl.DbaIdleTimeout, 0, mysqlctl.PoolDynamicHostnameResolution), } + w.writeConnID.Store(-1) - if w.onDemandDuration > 0 { - // see RequestHeartbeats() for use of onDemandRequestTicks - // it's basically a mechanism to rate limit operation RequestHeartbeats(). - // and selectively drop excessive requests. - w.allowNextHeartbeatRequest() - go func() { - // this will allow up to 1 request per (w.onDemandDuration / 4) to pass through - tick := time.NewTicker(w.onDemandDuration / 4) - defer tick.Stop() - for range tick.C { - w.allowNextHeartbeatRequest() - } - }() - } return w } @@ -117,14 +139,14 @@ func (w *heartbeatWriter) InitDBConfig(target *querypb.Target) { // Open sets up the heartbeatWriter's db connection and launches the ticker // responsible for periodically writing to the heartbeat table. func (w *heartbeatWriter) Open() { - if !w.enabled { - return - } w.mu.Lock() defer w.mu.Unlock() if w.isOpen { return } + defer func() { + w.isOpen = true + }() log.Info("Heartbeat Writer: opening") // We cannot create the database and tables in this Open function @@ -133,34 +155,56 @@ func (w *heartbeatWriter) Open() { // block this thread, and we could end up in a deadlock. // Instead, we try creating the database and table in each tick which runs in a go routine // keeping us safe from hanging the main thread. - w.appPool.Open(w.env.Config().DB.AppWithDB()) - w.allPrivsPool.Open(w.env.Config().DB.AllPrivsWithDB()) - if w.onDemandDuration == 0 { - w.enableWrites(true) - // when onDemandDuration > 0 we only enable writes per request - } else { + + // This function could be running from within a unit test scope, in which case we use + // mock pools that are already open. This is why we test for the pool being open. + if !w.appPool.IsOpen() { + w.appPool.Open(w.env.Config().DB.AppWithDB()) + } + if !w.allPrivsPool.IsOpen() { + w.allPrivsPool.Open(w.env.Config().DB.AllPrivsWithDB()) + } + + if w.onDemandDuration > 0 { + // Clients are given access to RequestHeartbeats(). But such clients can also abuse + // the system by initiating heartbeats too frequently. We rate-limit these requests. + rateLimiter := timer.NewRateLimiter(time.Second) + w.onDemandRequestsRateLimiter.Store(rateLimiter) + } + + switch w.configType { + case HeartbeatConfigTypeNone: + // Do not kick any heartbeats + return + case HeartbeatConfigTypeAlways: + // Heartbeats are always on + w.enableWrites() + case HeartbeatConfigTypeOnDemand: // A one-time kick off of heartbeats upon Open() go w.RequestHeartbeats() } - - w.isOpen = true } // Close closes the heartbeatWriter's db connection and stops the periodic ticker. func (w *heartbeatWriter) Close() { - if !w.enabled { - return - } w.mu.Lock() defer w.mu.Unlock() if !w.isOpen { return } + defer func() { + w.isOpen = false + }() - w.enableWrites(false) + w.disableWrites() w.appPool.Close() w.allPrivsPool.Close() - w.isOpen = false + + if rateLimiter := w.onDemandRequestsRateLimiter.Load(); rateLimiter != nil { + rateLimiter.Stop() + } + w.onDemandRequestsRateLimiter.Store(nil) + log.Info("Heartbeat Writer: closed") } @@ -185,11 +229,23 @@ func (w *heartbeatWriter) bindHeartbeatVars(query string) (string, error) { func (w *heartbeatWriter) writeHeartbeat() { if err := w.write(); err != nil { w.recordError(err) - return + } else { + writes.Add(1) + } + + if w.onDemandDuration > 0 { + // See if we need to expire the heartbeats + go func() { + if rateLimiter := w.onDemandRequestsRateLimiter.Load(); rateLimiter != nil { + if rateLimiter.Diff() > int64(w.onDemandDuration.Seconds()) { + w.disableWrites() + } + } + }() } - writes.Add(1) } +// write writes a single heartbeat update. func (w *heartbeatWriter) write() error { defer w.env.LogError() ctx, cancel := context.WithDeadline(context.Background(), w.now().Add(w.interval)) @@ -221,41 +277,36 @@ func (w *heartbeatWriter) recordError(err error) { writeErrors.Add(1) } -// enableWrites activates or deactivates heartbeat writes -func (w *heartbeatWriter) enableWrites(enable bool) { - if w.ticks == nil { - return - } - switch enable { - case true: - // We must combat a potential race condition: the writer is Open, and a request comes - // to enableWrites(true), but simultaneously the writes gets Close()d. - // We must not send any more ticks while the writer is closed. - go func() { - w.mu.Lock() - defer w.mu.Unlock() - if !w.isOpen { - return - } - w.ticks.Start(w.writeHeartbeat) - }() - case false: - // We stop the ticks in a separate go routine because it can block if the write is stuck on semi-sync ACKs. - // At the same time we try and kill the write that is in progress. We use the context and its cancellation - // for coordination between the two go-routines. In the end we will have guaranteed that the ticks have stopped - // and no write is in progress. - ctx, cancel := context.WithCancel(context.Background()) - go func() { - w.ticks.Stop() - cancel() - }() - w.killWritesUntilStopped(ctx) - - if w.onDemandDuration > 0 { - // Let the next RequestHeartbeats() go through - w.allowNextHeartbeatRequest() +// enableWrites activates heartbeat writes +func (w *heartbeatWriter) enableWrites() { + // We must combat a potential race condition: the writer is Open, and a request comes + // to enableWrites(), but simultaneously the writes gets Close()d. + // We must not send any more ticks while the writer is closed. + go func() { + w.mu.Lock() + defer w.mu.Unlock() + if !w.isOpen { + return } - } + w.ticks.Start(w.writeHeartbeat) + }() +} + +// disableWrites deactivates heartbeat writes +func (w *heartbeatWriter) disableWrites() { + // We stop the ticks in a separate go routine because it can block if the write is stuck on semi-sync ACKs. + // At the same time we try and kill the write that is in progress. We use the context and its cancellation + // for coordination between the two go-routines. In the end we will have guaranteed that the ticks have stopped + // and no write is in progress. + ctx, cancel := context.WithCancel(context.Background()) + go func() { + w.ticks.Stop() + cancel() + }() + w.killWritesUntilStopped(ctx) + + // Let the next RequestHeartbeats() go through + w.allowNextHeartbeatRequest() } // killWritesUntilStopped tries to kill the write in progress until the ticks have stopped. @@ -298,9 +349,15 @@ func (w *heartbeatWriter) killWrite() error { } // allowNextHeartbeatRequest ensures that the next call to RequestHeartbeats() passes through and -// is not dropped. +// is not rate-limited. +// Use case: just as the on-demand lease expires, a new request for heartbeat comes, and it's in the same timeslot +// as the one before the expiration. We want to allow the new request to re-lease on demand heartbeats. func (w *heartbeatWriter) allowNextHeartbeatRequest() { - atomic.AddInt64(&w.onDemandRequestTicks, 1) + // The writer could be close()d while this function is running and thus the value of the rate limiter could be nil. + // We thus use golang atomic here to avoid locking mutexes. + if rateLimiter := w.onDemandRequestsRateLimiter.Load(); rateLimiter != nil { + rateLimiter.AllowOne() + } } // RequestHeartbeats implements heartbeat.HeartbeatWriter.RequestHeartbeats() @@ -309,41 +366,12 @@ func (w *heartbeatWriter) allowNextHeartbeatRequest() { // This function will selectively and silently drop some such requests, depending on arrival rate. // This function is safe to call concurrently from goroutines func (w *heartbeatWriter) RequestHeartbeats() { - if w.onDemandDuration == 0 { - // heartbeats are not by demand. Therefore they are just coming in on their own (if enabled) - return + // The writer could be close()d while this function is running and thus the value of the rate limiter could be nil. + // We thus use golang atomic here to avoid locking mutexes. + if rateLimiter := w.onDemandRequestsRateLimiter.Load(); rateLimiter != nil { + rateLimiter.Do(func() error { + w.enableWrites() + return nil + }) } - // In this function we're going to create a timer to activate heartbeats by-demand. Creating a timer has a cost. - // Now, this function can be spammed by clients (the lag throttler). We therefore only allow this function to - // actually operate once per X seconds (1/4 of onDemandDuration as a reasonable oversampling value): - if atomic.LoadInt64(&w.onDemandLastRequestTick) >= atomic.LoadInt64(&w.onDemandRequestTicks) { - // Too many requests. We're dropping this one. - return - } - atomic.StoreInt64(&w.onDemandLastRequestTick, atomic.LoadInt64(&w.onDemandRequestTicks)) - - // OK, the request passed through. - - w.onDemandMu.Lock() - defer w.onDemandMu.Unlock() - - // Now for the actual logic. A client requests heartbeats. If it were only this client, we would - // activate heartbeats for the duration of onDemandDuration, and then turn heartbeats off. - // However, there may be multiple clients interested in heartbeats, or maybe the same single client - // requesting heartbeats again and again. So we keep track of how many _concurrent_ requests we have. - // We enable heartbeats as soon as we have a request; we turn heartbeats off once - // we have zero concurrent requests - w.enableWrites(true) - w.concurrentHeartbeatRequests++ - - time.AfterFunc(w.onDemandDuration, func() { - w.onDemandMu.Lock() - defer w.onDemandMu.Unlock() - w.concurrentHeartbeatRequests-- - if w.concurrentHeartbeatRequests == 0 { - // means there are currently no more clients interested in heartbeats - w.enableWrites(false) - } - w.allowNextHeartbeatRequest() - }) } diff --git a/go/vt/vttablet/tabletserver/repltracker/writer_test.go b/go/vt/vttablet/tabletserver/repltracker/writer_test.go index 0add32a1de0..e9aead570a8 100644 --- a/go/vt/vttablet/tabletserver/repltracker/writer_test.go +++ b/go/vt/vttablet/tabletserver/repltracker/writer_test.go @@ -38,7 +38,8 @@ func TestWriteHeartbeat(t *testing.T) { defer db.Close() now := time.Now() - tw := newTestWriter(db, &now) + tw := newSimpleTestWriter(db, &now) + upsert := fmt.Sprintf("INSERT INTO %s.heartbeat (ts, tabletUid, keyspaceShard) VALUES (%d, %d, '%s') ON DUPLICATE KEY UPDATE ts=VALUES(ts), tabletUid=VALUES(tabletUid)", "_vt", now.UnixNano(), tw.tabletAlias.Uid, tw.keyspaceShard) db.AddQuery(upsert, &sqltypes.Result{}) @@ -47,8 +48,214 @@ func TestWriteHeartbeat(t *testing.T) { writeErrors.Reset() tw.writeHeartbeat() - assert.Equal(t, int64(1), writes.Get()) - assert.Equal(t, int64(0), writeErrors.Get()) + assert.EqualValues(t, 1, writes.Get()) + assert.EqualValues(t, 0, writeErrors.Get()) +} + +// TestWriteHeartbeatOpen tests that the heartbeat writer writes heartbeats when the writer is open. +func TestWriteHeartbeatOpen(t *testing.T) { + defaultOnDemandDuration = 3 * time.Second + + db := fakesqldb.New(t) + defer db.Close() + + tw := newSimpleTestWriter(db, nil) + + assert.Zero(t, tw.onDemandDuration) + + db.AddQueryPattern("^INSERT INTO.*", &sqltypes.Result{}) + + writes.Reset() + writeErrors.Reset() + + tw.writeHeartbeat() + lastWrites := writes.Get() + assert.EqualValues(t, 1, lastWrites) + assert.EqualValues(t, 0, writeErrors.Get()) + + t.Run("closed, no heartbeats", func(t *testing.T) { + <-time.After(3 * time.Second) + assert.EqualValues(t, 1, writes.Get()) + }) + + { + rateLimiter := tw.onDemandRequestsRateLimiter.Load() + assert.Nil(t, rateLimiter) + } + tw.Open() + defer tw.Close() + { + rateLimiter := tw.onDemandRequestsRateLimiter.Load() + assert.Nil(t, rateLimiter) + } + t.Run("open, heartbeats", func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + ticker := time.NewTicker(1 * time.Second) + defer ticker.Stop() + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + assert.EqualValues(t, 0, writeErrors.Get()) + currentWrites := writes.Get() + assert.Greater(t, currentWrites, lastWrites) + lastWrites = currentWrites + } + } + }) +} + +// TestWriteHeartbeatDisabled tests that the heartbeat writer doesn't write heartbeats when the writer is disabled, +// but that it does respond to RequestHeartbeats(), and generates heartbeats on a lease. +func TestWriteHeartbeatDisabled(t *testing.T) { + defaultOnDemandDuration = 3 * time.Second + + db := fakesqldb.New(t) + defer db.Close() + + tw := newTestWriter(db, nil, tabletenv.Disable, 0) + + // Even though disabled, the writer will have an on-demand duration set. + assert.Equal(t, defaultOnDemandDuration, tw.onDemandDuration) + + db.AddQueryPattern("^INSERT INTO.*", &sqltypes.Result{}) + + writes.Reset() + writeErrors.Reset() + + tw.writeHeartbeat() + lastWrites := writes.Get() + assert.EqualValues(t, 1, lastWrites) + assert.EqualValues(t, 0, writeErrors.Get()) + + t.Run("closed, no heartbeats", func(t *testing.T) { + <-time.After(3 * time.Second) + assert.EqualValues(t, 1, writes.Get()) + }) + { + rateLimiter := tw.onDemandRequestsRateLimiter.Load() + assert.Nil(t, rateLimiter) + } + tw.Open() + defer tw.Close() + { + rateLimiter := tw.onDemandRequestsRateLimiter.Load() + assert.NotNil(t, rateLimiter) + } + t.Run("open, no heartbeats", func(t *testing.T) { + <-time.After(3 * time.Second) + assert.EqualValues(t, 1, writes.Get()) + }) + t.Run("request heartbeats, heartbeats", func(t *testing.T) { + tw.RequestHeartbeats() + ctx, cancel := context.WithTimeout(context.Background(), tw.onDemandDuration-time.Second) + defer cancel() + ticker := time.NewTicker(1 * time.Second) + defer ticker.Stop() + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + assert.EqualValues(t, 0, writeErrors.Get()) + currentWrites := writes.Get() + assert.Greater(t, currentWrites, lastWrites) + lastWrites = currentWrites + } + } + }) + t.Run("exhaust lease, no heartbeats", func(t *testing.T) { + <-time.After(tw.onDemandDuration) + currentWrites := writes.Get() + <-time.After(3 * time.Second) + assert.EqualValues(t, currentWrites, writes.Get()) + }) + tw.Close() + { + rateLimiter := tw.onDemandRequestsRateLimiter.Load() + assert.Nil(t, rateLimiter) + } +} + +// TestWriteHeartbeatOnDemand tests that the heartbeat writer initiates leased heartbeats once opened, +// and then upon RequestHeartbeats(). +func TestWriteHeartbeatOnDemand(t *testing.T) { + defaultOnDemandDuration = 7 * time.Second + onDemandDuration := minimalOnDemandDuration + + db := fakesqldb.New(t) + defer db.Close() + + tw := newTestWriter(db, nil, tabletenv.Heartbeat, onDemandDuration) + + assert.Equal(t, onDemandDuration, tw.onDemandDuration) + + db.AddQueryPattern("^INSERT INTO.*", &sqltypes.Result{}) + + writes.Reset() + writeErrors.Reset() + + tw.writeHeartbeat() + lastWrites := writes.Get() + assert.EqualValues(t, 1, lastWrites) + assert.EqualValues(t, 0, writeErrors.Get()) + + t.Run("closed, no heartbeats", func(t *testing.T) { + <-time.After(3 * time.Second) + assert.EqualValues(t, 1, writes.Get()) + }) + { + rateLimiter := tw.onDemandRequestsRateLimiter.Load() + assert.Nil(t, rateLimiter) + } + tw.Open() + defer tw.Close() + { + rateLimiter := tw.onDemandRequestsRateLimiter.Load() + assert.NotNil(t, rateLimiter) + } + t.Run("open, initial heartbeats", func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), tw.onDemandDuration-time.Second) + defer cancel() + ticker := time.NewTicker(1 * time.Second) + defer ticker.Stop() + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + assert.EqualValues(t, 0, writeErrors.Get()) + currentWrites := writes.Get() + assert.Greater(t, currentWrites, lastWrites) + lastWrites = currentWrites + } + } + }) + t.Run("exhaust lease, no heartbeats", func(t *testing.T) { + <-time.After(tw.onDemandDuration) + currentWrites := writes.Get() + <-time.After(3 * time.Second) + assert.EqualValues(t, currentWrites, writes.Get()) + }) + t.Run("request heartbeats, heartbeats", func(t *testing.T) { + tw.RequestHeartbeats() + lastWrites := writes.Get() + <-time.After(tw.onDemandDuration) + assert.Greater(t, writes.Get(), lastWrites) + }) + t.Run("exhaust lease, no heartbeats", func(t *testing.T) { + <-time.After(tw.onDemandDuration) + currentWrites := writes.Get() + <-time.After(3 * time.Second) + assert.EqualValues(t, currentWrites, writes.Get()) + }) + tw.Close() + { + rateLimiter := tw.onDemandRequestsRateLimiter.Load() + assert.Nil(t, rateLimiter) + } } func TestWriteHeartbeatError(t *testing.T) { @@ -56,7 +263,7 @@ func TestWriteHeartbeatError(t *testing.T) { defer db.Close() now := time.Now() - tw := newTestWriter(db, &now) + tw := newSimpleTestWriter(db, &now) writes.Reset() writeErrors.Reset() @@ -69,7 +276,8 @@ func TestWriteHeartbeatError(t *testing.T) { // TestCloseWhileStuckWriting tests that Close shouldn't get stuck even if the heartbeat writer is stuck waiting for a semi-sync ACK. func TestCloseWhileStuckWriting(t *testing.T) { db := fakesqldb.New(t) - tw := newTestWriter(db, nil) + tw := newSimpleTestWriter(db, nil) + tw.isOpen = true killWg := sync.WaitGroup{} @@ -90,14 +298,14 @@ func TestCloseWhileStuckWriting(t *testing.T) { }) // Now we enable writes, but the first write will get blocked. - tw.enableWrites(true) + tw.enableWrites() // We wait until the write has blocked to ensure we only call Close after we are stuck writing. startedWaitWg.Wait() // Even if the write is blocked, we should be able to disable writes without waiting indefinitely. // This is what we call, when we try to Close the heartbeat writer. ctx, cancel := context.WithCancel(context.Background()) go func() { - tw.enableWrites(false) + tw.disableWrites() cancel() }() select { @@ -108,17 +316,22 @@ func TestCloseWhileStuckWriting(t *testing.T) { } } -func newTestWriter(db *fakesqldb.DB, frozenTime *time.Time) *heartbeatWriter { +func newSimpleTestWriter(db *fakesqldb.DB, frozenTime *time.Time) *heartbeatWriter { + return newTestWriter(db, frozenTime, tabletenv.Heartbeat, 0) +} + +func newTestWriter(db *fakesqldb.DB, frozenTime *time.Time, replTrackerMode string, onDemandInterval time.Duration) *heartbeatWriter { cfg := tabletenv.NewDefaultConfig() - cfg.ReplicationTracker.Mode = tabletenv.Heartbeat - cfg.ReplicationTracker.HeartbeatInterval = time.Second + cfg.ReplicationTracker.Mode = replTrackerMode + cfg.ReplicationTracker.HeartbeatOnDemand = onDemandInterval + cfg.ReplicationTracker.HeartbeatInterval = 250 * time.Millisecond // oversampling our 1*time.Second unit test interval in various functions params := db.ConnParams() cp := *params dbc := dbconfigs.NewTestDBConfigs(cp, cp, "") tw := newHeartbeatWriter(tabletenv.NewEnv(vtenv.NewTestEnv(), cfg, "WriterTest"), &topodatapb.TabletAlias{Cell: "test", Uid: 1111}) - tw.keyspaceShard = "test:0" + tw.keyspaceShard = "test/-" if frozenTime != nil { tw.now = func() time.Time { diff --git a/go/vt/vttablet/tabletserver/state_manager_test.go b/go/vt/vttablet/tabletserver/state_manager_test.go index f6345b9b29c..02896eeefe0 100644 --- a/go/vt/vttablet/tabletserver/state_manager_test.go +++ b/go/vt/vttablet/tabletserver/state_manager_test.go @@ -31,8 +31,6 @@ import ( "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vtenv" - "vitess.io/vitess/go/mysql/fakesqldb" - "vitess.io/vitess/go/vt/dbconfigs" "vitess.io/vitess/go/vt/log" querypb "vitess.io/vitess/go/vt/proto/query" topodatapb "vitess.io/vitess/go/vt/proto/topodata" @@ -69,7 +67,7 @@ func TestStateManagerStateByName(t *testing.T) { } func TestStateManagerServePrimary(t *testing.T) { - sm := newTestStateManager(t) + sm := newTestStateManager() defer sm.StopService() sm.EnterLameduck() err := sm.SetServingType(topodatapb.TabletType_PRIMARY, testNow, StateServing, "") @@ -100,7 +98,7 @@ func TestStateManagerServePrimary(t *testing.T) { } func TestStateManagerServeNonPrimary(t *testing.T) { - sm := newTestStateManager(t) + sm := newTestStateManager() defer sm.StopService() err := sm.SetServingType(topodatapb.TabletType_REPLICA, testNow, StateServing, "") require.NoError(t, err) @@ -125,7 +123,7 @@ func TestStateManagerServeNonPrimary(t *testing.T) { } func TestStateManagerUnservePrimary(t *testing.T) { - sm := newTestStateManager(t) + sm := newTestStateManager() defer sm.StopService() err := sm.SetServingType(topodatapb.TabletType_PRIMARY, testNow, StateNotServing, "") require.NoError(t, err) @@ -150,7 +148,7 @@ func TestStateManagerUnservePrimary(t *testing.T) { } func TestStateManagerUnserveNonPrimary(t *testing.T) { - sm := newTestStateManager(t) + sm := newTestStateManager() defer sm.StopService() err := sm.SetServingType(topodatapb.TabletType_RDONLY, testNow, StateNotServing, "") require.NoError(t, err) @@ -177,7 +175,7 @@ func TestStateManagerUnserveNonPrimary(t *testing.T) { } func TestStateManagerClose(t *testing.T) { - sm := newTestStateManager(t) + sm := newTestStateManager() defer sm.StopService() err := sm.SetServingType(topodatapb.TabletType_RDONLY, testNow, StateNotConnected, "") require.NoError(t, err) @@ -201,7 +199,7 @@ func TestStateManagerClose(t *testing.T) { } func TestStateManagerStopService(t *testing.T) { - sm := newTestStateManager(t) + sm := newTestStateManager() defer sm.StopService() err := sm.SetServingType(topodatapb.TabletType_REPLICA, testNow, StateServing, "") require.NoError(t, err) @@ -215,7 +213,7 @@ func TestStateManagerStopService(t *testing.T) { } func TestStateManagerGracePeriod(t *testing.T) { - sm := newTestStateManager(t) + sm := newTestStateManager() defer sm.StopService() sm.transitionGracePeriod = 10 * time.Millisecond @@ -269,7 +267,7 @@ func (te *testWatcher) Close() { func TestStateManagerSetServingTypeRace(t *testing.T) { // We don't call StopService because that in turn // will call Close again on testWatcher. - sm := newTestStateManager(t) + sm := newTestStateManager() te := &testWatcher{ t: t, sm: sm, @@ -288,7 +286,7 @@ func TestStateManagerSetServingTypeRace(t *testing.T) { func TestStateManagerSetServingTypeNoChange(t *testing.T) { log.Infof("starting") - sm := newTestStateManager(t) + sm := newTestStateManager() defer sm.StopService() err := sm.SetServingType(topodatapb.TabletType_REPLICA, testNow, StateServing, "") require.NoError(t, err) @@ -319,7 +317,7 @@ func TestStateManagerTransitionFailRetry(t *testing.T) { defer func(saved time.Duration) { transitionRetryInterval = saved }(transitionRetryInterval) transitionRetryInterval = 10 * time.Millisecond - sm := newTestStateManager(t) + sm := newTestStateManager() defer sm.StopService() sm.se.(*testSchemaEngine).failMySQL = true @@ -351,7 +349,7 @@ func TestStateManagerTransitionFailRetry(t *testing.T) { } func TestStateManagerNotConnectedType(t *testing.T) { - sm := newTestStateManager(t) + sm := newTestStateManager() defer sm.StopService() sm.EnterLameduck() err := sm.SetServingType(topodatapb.TabletType_RESTORE, testNow, StateNotServing, "") @@ -404,7 +402,7 @@ func (k *killableConn) SQLParser() *sqlparser.Parser { } func TestStateManagerShutdownGracePeriod(t *testing.T) { - sm := newTestStateManager(t) + sm := newTestStateManager() defer sm.StopService() sm.te = &delayedTxEngine{} @@ -459,7 +457,7 @@ func TestStateManagerCheckMySQL(t *testing.T) { defer func(saved time.Duration) { transitionRetryInterval = saved }(transitionRetryInterval) transitionRetryInterval = 10 * time.Millisecond - sm := newTestStateManager(t) + sm := newTestStateManager() defer sm.StopService() err := sm.SetServingType(topodatapb.TabletType_PRIMARY, testNow, StateServing, "") @@ -527,7 +525,7 @@ func TestStateManagerCheckMySQL(t *testing.T) { func TestStateManagerValidations(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - sm := newTestStateManager(t) + sm := newTestStateManager() target := &querypb.Target{TabletType: topodatapb.TabletType_PRIMARY} sm.target = target.CloneVT() err := sm.StartRequest(ctx, target, false) @@ -590,7 +588,7 @@ func TestStateManagerValidations(t *testing.T) { func TestStateManagerWaitForRequests(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - sm := newTestStateManager(t) + sm := newTestStateManager() defer sm.StopService() target := &querypb.Target{TabletType: topodatapb.TabletType_PRIMARY} sm.target = target @@ -630,7 +628,7 @@ func TestStateManagerWaitForRequests(t *testing.T) { } func TestStateManagerNotify(t *testing.T) { - sm := newTestStateManager(t) + sm := newTestStateManager() defer sm.StopService() blpFunc = testBlpFunc @@ -669,7 +667,7 @@ func TestStateManagerNotify(t *testing.T) { } func TestRefreshReplHealthLocked(t *testing.T) { - sm := newTestStateManager(t) + sm := newTestStateManager() defer sm.StopService() rt := sm.rt.(*testReplTracker) @@ -705,7 +703,7 @@ func TestRefreshReplHealthLocked(t *testing.T) { // TestPanicInWait tests that we don't panic when we wait for requests if more StartRequest calls come up after we start waiting. func TestPanicInWait(t *testing.T) { - sm := newTestStateManager(t) + sm := newTestStateManager() sm.wantState = StateServing sm.state = StateServing sm.replHealthy = true @@ -732,7 +730,7 @@ func verifySubcomponent(t *testing.T, order int64, component any, state testStat assert.Equal(t, state, tos.State()) } -func newTestStateManager(t *testing.T) *stateManager { +func newTestStateManager() *stateManager { order.Store(0) cfg := tabletenv.NewDefaultConfig() parser := sqlparser.NewTestParser() @@ -757,7 +755,7 @@ func newTestStateManager(t *testing.T) *stateManager { rw: newRequestsWaiter(), } sm.Init(env, &querypb.Target{}) - sm.hs.InitDBConfig(&querypb.Target{}, dbconfigs.New(fakesqldb.New(t).ConnParams())) + sm.hs.InitDBConfig(&querypb.Target{}) log.Infof("returning sm: %p", sm) return sm } diff --git a/go/vt/vttablet/tabletserver/tabletenv/config.go b/go/vt/vttablet/tabletserver/tabletenv/config.go index 1b89829825b..158f40d5202 100644 --- a/go/vt/vttablet/tabletserver/tabletenv/config.go +++ b/go/vt/vttablet/tabletserver/tabletenv/config.go @@ -157,7 +157,6 @@ func registerTabletEnvFlags(fs *pflag.FlagSet) { fs.BoolVar(¤tConfig.TrackSchemaVersions, "track_schema_versions", false, "When enabled, vttablet will store versions of schemas at each position that a DDL is applied and allow retrieval of the schema corresponding to a position") fs.Int64Var(¤tConfig.SchemaVersionMaxAgeSeconds, "schema-version-max-age-seconds", 0, "max age of schema version records to kept in memory by the vreplication historian") fs.BoolVar(¤tConfig.TwoPCEnable, "twopc_enable", defaultConfig.TwoPCEnable, "if the flag is on, 2pc is enabled. Other 2pc flags must be supplied.") - fs.StringVar(¤tConfig.TwoPCCoordinatorAddress, "twopc_coordinator_address", defaultConfig.TwoPCCoordinatorAddress, "address of the (VTGate) process(es) that will be used to notify of abandoned transactions.") SecondsVar(fs, ¤tConfig.TwoPCAbandonAge, "twopc_abandon_age", defaultConfig.TwoPCAbandonAge, "time in seconds. Any unresolved transaction older than this time will be sent to the coordinator to be resolved.") // Tx throttler config flagutil.DualFormatBoolVar(fs, ¤tConfig.EnableTxThrottler, "enable_tx_throttler", defaultConfig.EnableTxThrottler, "If true replication-lag-based throttling on transactions will be enabled.") @@ -200,7 +199,8 @@ func registerTabletEnvFlags(fs *pflag.FlagSet) { fs.BoolVar(&enableReplicationReporter, "enable_replication_reporter", false, "Use polling to track replication lag.") fs.BoolVar(¤tConfig.EnableOnlineDDL, "queryserver_enable_online_ddl", true, "Enable online DDL.") fs.BoolVar(¤tConfig.SanitizeLogMessages, "sanitize_log_messages", false, "Remove potentially sensitive information in tablet INFO, WARNING, and ERROR log messages such as query parameters.") - fs.BoolVar(¤tConfig.EnableSettingsPool, "queryserver-enable-settings-pool", true, "Enable pooling of connections with modified system settings") + _ = fs.Bool("queryserver-enable-settings-pool", true, "Enable pooling of connections with modified system settings") + _ = fs.MarkDeprecated("queryserver-enable-settings-pool", "New pool implementation does it internally and at the api level this has been enabled since v17") fs.Int64Var(¤tConfig.RowStreamer.MaxInnoDBTrxHistLen, "vreplication_copy_phase_max_innodb_history_list_length", 1000000, "The maximum InnoDB transaction history that can exist on a vstreamer (source) before starting another round of copying rows. This helps to limit the impact on the source tablet.") fs.Int64Var(¤tConfig.RowStreamer.MaxMySQLReplLagSecs, "vreplication_copy_phase_max_mysql_replication_lag", 43200, "The maximum MySQL replication lag (in seconds) that can exist on a vstreamer (source) before starting another round of copying rows. This helps to limit the impact on the source tablet.") @@ -311,34 +311,32 @@ type TabletConfig struct { ReplicationTracker ReplicationTrackerConfig `json:"replicationTracker,omitempty"` // Consolidator can be enable, disable, or notOnPrimary. Default is enable. - Consolidator string `json:"consolidator,omitempty"` - PassthroughDML bool `json:"passthroughDML,omitempty"` - StreamBufferSize int `json:"streamBufferSize,omitempty"` - ConsolidatorStreamTotalSize int64 `json:"consolidatorStreamTotalSize,omitempty"` - ConsolidatorStreamQuerySize int64 `json:"consolidatorStreamQuerySize,omitempty"` - QueryCacheMemory int64 `json:"queryCacheMemory,omitempty"` - QueryCacheDoorkeeper bool `json:"queryCacheDoorkeeper,omitempty"` - SchemaReloadInterval time.Duration `json:"schemaReloadIntervalSeconds,omitempty"` - SignalSchemaChangeReloadInterval time.Duration `json:"signalSchemaChangeReloadIntervalSeconds,omitempty"` - SchemaChangeReloadTimeout time.Duration `json:"schemaChangeReloadTimeout,omitempty"` - WatchReplication bool `json:"watchReplication,omitempty"` - TrackSchemaVersions bool `json:"trackSchemaVersions,omitempty"` - SchemaVersionMaxAgeSeconds int64 `json:"schemaVersionMaxAgeSeconds,omitempty"` - TerseErrors bool `json:"terseErrors,omitempty"` - TruncateErrorLen int `json:"truncateErrorLen,omitempty"` - AnnotateQueries bool `json:"annotateQueries,omitempty"` - MessagePostponeParallelism int `json:"messagePostponeParallelism,omitempty"` - SignalWhenSchemaChange bool `json:"signalWhenSchemaChange,omitempty"` + Consolidator string `json:"consolidator,omitempty"` + PassthroughDML bool `json:"passthroughDML,omitempty"` + StreamBufferSize int `json:"streamBufferSize,omitempty"` + ConsolidatorStreamTotalSize int64 `json:"consolidatorStreamTotalSize,omitempty"` + ConsolidatorStreamQuerySize int64 `json:"consolidatorStreamQuerySize,omitempty"` + QueryCacheMemory int64 `json:"queryCacheMemory,omitempty"` + QueryCacheDoorkeeper bool `json:"queryCacheDoorkeeper,omitempty"` + SchemaReloadInterval time.Duration `json:"schemaReloadIntervalSeconds,omitempty"` + SchemaChangeReloadTimeout time.Duration `json:"schemaChangeReloadTimeout,omitempty"` + WatchReplication bool `json:"watchReplication,omitempty"` + TrackSchemaVersions bool `json:"trackSchemaVersions,omitempty"` + SchemaVersionMaxAgeSeconds int64 `json:"schemaVersionMaxAgeSeconds,omitempty"` + TerseErrors bool `json:"terseErrors,omitempty"` + TruncateErrorLen int `json:"truncateErrorLen,omitempty"` + AnnotateQueries bool `json:"annotateQueries,omitempty"` + MessagePostponeParallelism int `json:"messagePostponeParallelism,omitempty"` + SignalWhenSchemaChange bool `json:"signalWhenSchemaChange,omitempty"` ExternalConnections map[string]*dbconfigs.DBConfigs `json:"externalConnections,omitempty"` - SanitizeLogMessages bool `json:"-"` - StrictTableACL bool `json:"-"` - EnableTableACLDryRun bool `json:"-"` - TableACLExemptACL string `json:"-"` - TwoPCEnable bool `json:"-"` - TwoPCCoordinatorAddress string `json:"-"` - TwoPCAbandonAge Seconds `json:"-"` + SanitizeLogMessages bool `json:"-"` + StrictTableACL bool `json:"-"` + EnableTableACLDryRun bool `json:"-"` + TableACLExemptACL string `json:"-"` + TwoPCEnable bool `json:"-"` + TwoPCAbandonAge Seconds `json:"-"` EnableTxThrottler bool `json:"-"` TxThrottlerConfig *TxThrottlerConfigFlag `json:"-"` @@ -354,7 +352,6 @@ type TabletConfig struct { EnforceStrictTransTables bool `json:"-"` EnableOnlineDDL bool `json:"-"` - EnableSettingsPool bool `json:"-"` RowStreamer RowStreamerConfig `json:"rowStreamer,omitempty"` @@ -368,9 +365,8 @@ func (cfg *TabletConfig) MarshalJSON() ([]byte, error) { tmp := struct { TCProxy - SchemaReloadInterval string `json:"schemaReloadIntervalSeconds,omitempty"` - SignalSchemaChangeReloadInterval string `json:"signalSchemaChangeReloadIntervalSeconds,omitempty"` - SchemaChangeReloadTimeout string `json:"schemaChangeReloadTimeout,omitempty"` + SchemaReloadInterval string `json:"schemaReloadIntervalSeconds,omitempty"` + SchemaChangeReloadTimeout string `json:"schemaChangeReloadTimeout,omitempty"` }{ TCProxy: TCProxy(*cfg), } @@ -379,10 +375,6 @@ func (cfg *TabletConfig) MarshalJSON() ([]byte, error) { tmp.SchemaReloadInterval = d.String() } - if d := cfg.SignalSchemaChangeReloadInterval; d != 0 { - tmp.SignalSchemaChangeReloadInterval = d.String() - } - if d := cfg.SchemaChangeReloadTimeout; d != 0 { tmp.SchemaChangeReloadTimeout = d.String() } @@ -395,9 +387,8 @@ func (cfg *TabletConfig) UnmarshalJSON(data []byte) (err error) { var tmp struct { TCProxy - SchemaReloadInterval string `json:"schemaReloadIntervalSeconds,omitempty"` - SignalSchemaChangeReloadInterval string `json:"signalSchemaChangeReloadIntervalSeconds,omitempty"` - SchemaChangeReloadTimeout string `json:"schemaChangeReloadTimeout,omitempty"` + SchemaReloadInterval string `json:"schemaReloadIntervalSeconds,omitempty"` + SchemaChangeReloadTimeout string `json:"schemaChangeReloadTimeout,omitempty"` } tmp.TCProxy = TCProxy(*cfg) @@ -413,17 +404,6 @@ func (cfg *TabletConfig) UnmarshalJSON(data []byte) (err error) { if err != nil { return err } - } else { - cfg.SchemaReloadInterval = 0 - } - - if tmp.SignalSchemaChangeReloadInterval != "" { - cfg.SignalSchemaChangeReloadInterval, err = time.ParseDuration(tmp.SignalSchemaChangeReloadInterval) - if err != nil { - return err - } - } else { - cfg.SignalSchemaChangeReloadInterval = 0 } if tmp.SchemaChangeReloadTimeout != "" { @@ -431,8 +411,6 @@ func (cfg *TabletConfig) UnmarshalJSON(data []byte) (err error) { if err != nil { return err } - } else { - cfg.SchemaChangeReloadTimeout = 0 } return nil @@ -1076,7 +1054,6 @@ var defaultConfig = TabletConfig{ }, EnablePerWorkloadTableMetrics: false, - EnableSettingsPool: true, } // defaultTxThrottlerConfig returns the default TxThrottlerConfigFlag object based on diff --git a/go/vt/vttablet/tabletserver/tabletenv/config_test.go b/go/vt/vttablet/tabletserver/tabletenv/config_test.go index a51a3c599e8..d16b6276964 100644 --- a/go/vt/vttablet/tabletserver/tabletenv/config_test.go +++ b/go/vt/vttablet/tabletserver/tabletenv/config_test.go @@ -58,6 +58,8 @@ func TestConfigParse(t *testing.T) { MaxInnoDBTrxHistLen: 1000, MaxMySQLReplLagSecs: 400, }, + SchemaChangeReloadTimeout: 30 * time.Second, + SchemaReloadInterval: 30 * time.Minute, } gotBytes, err := yaml2.Marshal(&cfg) @@ -93,6 +95,8 @@ replicationTracker: {} rowStreamer: maxInnoDBTrxHistLen: 1000 maxMySQLReplLagSecs: 400 +schemaChangeReloadTimeout: 30s +schemaReloadIntervalSeconds: 30m0s txPool: {} ` assert.Equal(t, wantBytes, string(gotBytes)) diff --git a/go/vt/vttablet/tabletserver/tabletserver.go b/go/vt/vttablet/tabletserver/tabletserver.go index db01e6f2912..8a6d1a0be39 100644 --- a/go/vt/vttablet/tabletserver/tabletserver.go +++ b/go/vt/vttablet/tabletserver/tabletserver.go @@ -44,6 +44,10 @@ import ( "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/logutil" "vitess.io/vitess/go/vt/mysqlctl" + binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" + querypb "vitess.io/vitess/go/vt/proto/query" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" + vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" "vitess.io/vitess/go/vt/servenv" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/srvtopo" @@ -62,15 +66,11 @@ import ( "vitess.io/vitess/go/vt/vttablet/tabletserver/schema" "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle" + "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/throttlerapp" "vitess.io/vitess/go/vt/vttablet/tabletserver/txserializer" "vitess.io/vitess/go/vt/vttablet/tabletserver/txthrottler" "vitess.io/vitess/go/vt/vttablet/tabletserver/vstreamer" - - binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" - querypb "vitess.io/vitess/go/vt/proto/query" - topodatapb "vitess.io/vitess/go/vt/proto/topodata" - vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" ) // logPoolFull is for throttling transaction / query pool full messages in the log. @@ -181,7 +181,7 @@ func NewTabletServer(ctx context.Context, env *vtenv.Environment, name string, c tsv.watcher = NewBinlogWatcher(tsv, tsv.vstreamer, tsv.config) tsv.qe = NewQueryEngine(tsv, tsv.se) tsv.txThrottler = txthrottler.NewTxThrottler(tsv, topoServer) - tsv.te = NewTxEngine(tsv) + tsv.te = NewTxEngine(tsv, tsv.hs.sendUnresolvedTransactionSignal) tsv.messager = messager.NewEngine(tsv, tsv.se, tsv.vstreamer) tsv.tableGC = gc.NewTableGC(tsv, topoServer, tsv.lagThrottler) @@ -271,7 +271,7 @@ func (tsv *TabletServer) InitDBConfig(target *querypb.Target, dbcfgs *dbconfigs. tsv.rt.InitDBConfig(target, mysqld) tsv.txThrottler.InitDBConfig(target) tsv.vstreamer.InitDBConfig(target.Keyspace, target.Shard) - tsv.hs.InitDBConfig(target, tsv.config.DB.DbaWithDB()) + tsv.hs.InitDBConfig(target) tsv.onlineDDLExecutor.InitDBConfig(target.Keyspace, target.Shard, dbcfgs.DBName) tsv.lagThrottler.InitDBConfig(target.Keyspace, target.Shard) tsv.tableGC.InitDBConfig(target.Keyspace, target.Shard, dbcfgs.DBName) @@ -645,11 +645,7 @@ func (tsv *TabletServer) Prepare(ctx context.Context, target *querypb.Target, tr "Prepare", "prepare", nil, target, nil, true, /* allowOnShutdown */ func(ctx context.Context, logStats *tabletenv.LogStats) error { - txe := &TxExecutor{ - ctx: ctx, - logStats: logStats, - te: tsv.te, - } + txe := NewDTExecutor(ctx, tsv.te, logStats) return txe.Prepare(transactionID, dtid) }, ) @@ -662,11 +658,7 @@ func (tsv *TabletServer) CommitPrepared(ctx context.Context, target *querypb.Tar "CommitPrepared", "commit_prepared", nil, target, nil, true, /* allowOnShutdown */ func(ctx context.Context, logStats *tabletenv.LogStats) error { - txe := &TxExecutor{ - ctx: ctx, - logStats: logStats, - te: tsv.te, - } + txe := NewDTExecutor(ctx, tsv.te, logStats) return txe.CommitPrepared(dtid) }, ) @@ -679,11 +671,7 @@ func (tsv *TabletServer) RollbackPrepared(ctx context.Context, target *querypb.T "RollbackPrepared", "rollback_prepared", nil, target, nil, true, /* allowOnShutdown */ func(ctx context.Context, logStats *tabletenv.LogStats) error { - txe := &TxExecutor{ - ctx: ctx, - logStats: logStats, - te: tsv.te, - } + txe := NewDTExecutor(ctx, tsv.te, logStats) return txe.RollbackPrepared(dtid, originalID) }, ) @@ -696,11 +684,7 @@ func (tsv *TabletServer) CreateTransaction(ctx context.Context, target *querypb. "CreateTransaction", "create_transaction", nil, target, nil, true, /* allowOnShutdown */ func(ctx context.Context, logStats *tabletenv.LogStats) error { - txe := &TxExecutor{ - ctx: ctx, - logStats: logStats, - te: tsv.te, - } + txe := NewDTExecutor(ctx, tsv.te, logStats) return txe.CreateTransaction(dtid, participants) }, ) @@ -714,11 +698,7 @@ func (tsv *TabletServer) StartCommit(ctx context.Context, target *querypb.Target "StartCommit", "start_commit", nil, target, nil, true, /* allowOnShutdown */ func(ctx context.Context, logStats *tabletenv.LogStats) error { - txe := &TxExecutor{ - ctx: ctx, - logStats: logStats, - te: tsv.te, - } + txe := NewDTExecutor(ctx, tsv.te, logStats) return txe.StartCommit(transactionID, dtid) }, ) @@ -732,11 +712,7 @@ func (tsv *TabletServer) SetRollback(ctx context.Context, target *querypb.Target "SetRollback", "set_rollback", nil, target, nil, true, /* allowOnShutdown */ func(ctx context.Context, logStats *tabletenv.LogStats) error { - txe := &TxExecutor{ - ctx: ctx, - logStats: logStats, - te: tsv.te, - } + txe := NewDTExecutor(ctx, tsv.te, logStats) return txe.SetRollback(dtid, transactionID) }, ) @@ -750,11 +726,7 @@ func (tsv *TabletServer) ConcludeTransaction(ctx context.Context, target *queryp "ConcludeTransaction", "conclude_transaction", nil, target, nil, true, /* allowOnShutdown */ func(ctx context.Context, logStats *tabletenv.LogStats) error { - txe := &TxExecutor{ - ctx: ctx, - logStats: logStats, - te: tsv.te, - } + txe := NewDTExecutor(ctx, tsv.te, logStats) return txe.ConcludeTransaction(dtid) }, ) @@ -767,11 +739,7 @@ func (tsv *TabletServer) ReadTransaction(ctx context.Context, target *querypb.Ta "ReadTransaction", "read_transaction", nil, target, nil, true, /* allowOnShutdown */ func(ctx context.Context, logStats *tabletenv.LogStats) error { - txe := &TxExecutor{ - ctx: ctx, - logStats: logStats, - te: tsv.te, - } + txe := NewDTExecutor(ctx, tsv.te, logStats) metadata, err = txe.ReadTransaction(dtid) return err }, @@ -779,6 +747,21 @@ func (tsv *TabletServer) ReadTransaction(ctx context.Context, target *querypb.Ta return metadata, err } +// UnresolvedTransactions returns the unresolved distributed transaction record. +func (tsv *TabletServer) UnresolvedTransactions(ctx context.Context, target *querypb.Target) (transactions []*querypb.TransactionMetadata, err error) { + err = tsv.execRequest( + ctx, tsv.loadQueryTimeout(), + "UnresolvedTransactions", "unresolved_transaction", nil, + target, nil, false, /* allowOnShutdown */ + func(ctx context.Context, logStats *tabletenv.LogStats) error { + txe := NewDTExecutor(ctx, tsv.te, logStats) + transactions, err = txe.UnresolvedTransactions() + return err + }, + ) + return +} + // Execute executes the query and returns the result as response. func (tsv *TabletServer) Execute(ctx context.Context, target *querypb.Target, sql string, bindVariables map[string]*querypb.BindVariable, transactionID, reservedID int64, options *querypb.ExecuteOptions) (result *sqltypes.Result, err error) { span, ctx := trace.NewSpan(ctx, "TabletServer.Execute") @@ -1221,19 +1204,19 @@ func (tsv *TabletServer) VStreamResults(ctx context.Context, target *querypb.Tar // ReserveBeginExecute implements the QueryService interface func (tsv *TabletServer) ReserveBeginExecute(ctx context.Context, target *querypb.Target, preQueries []string, postBeginQueries []string, sql string, bindVariables map[string]*querypb.BindVariable, options *querypb.ExecuteOptions) (state queryservice.ReservedTransactionState, result *sqltypes.Result, err error) { - if tsv.config.EnableSettingsPool { - state, result, err = tsv.beginExecuteWithSettings(ctx, target, preQueries, postBeginQueries, sql, bindVariables, options) - // If there is an error and the error message is about allowing query in reserved connection only, - // then we do not return an error from here and continue to use the reserved connection path. - // This is specially for get_lock function call from vtgate that needs a reserved connection. - if err == nil || !strings.Contains(err.Error(), "not allowed without reserved connection") { - return state, result, err - } - // rollback if transaction was started. - if state.TransactionID != 0 { - _, _ = tsv.Rollback(ctx, target, state.TransactionID) - } + state, result, err = tsv.beginExecuteWithSettings(ctx, target, preQueries, postBeginQueries, sql, bindVariables, options) + // If there is an error and the error message is about allowing query in reserved connection only, + // then we do not return an error from here and continue to use the reserved connection path. + // This is specially for get_lock function call from vtgate that needs a reserved connection. + if err == nil || !strings.Contains(err.Error(), "not allowed without reserved connection") { + return state, result, err } + // rollback if transaction was started. + if state.TransactionID != 0 { + _, _ = tsv.Rollback(ctx, target, state.TransactionID) + } + + // needs a reserved connection. var connID int64 var sessionStateChanges string state.TabletAlias = tsv.alias @@ -1274,65 +1257,34 @@ func (tsv *TabletServer) ReserveBeginExecute(ctx context.Context, target *queryp func (tsv *TabletServer) ReserveBeginStreamExecute( ctx context.Context, target *querypb.Target, - preQueries []string, - postBeginQueries []string, + settings []string, + savepointQueries []string, sql string, bindVariables map[string]*querypb.BindVariable, options *querypb.ExecuteOptions, callback func(*sqltypes.Result) error, ) (state queryservice.ReservedTransactionState, err error) { - if tsv.config.EnableSettingsPool { - return tsv.beginStreamExecuteWithSettings(ctx, target, preQueries, postBeginQueries, sql, bindVariables, options, callback) - } - - var connID int64 - var sessionStateChanges string - - err = tsv.execRequest( - ctx, tsv.loadQueryTimeout(), - "ReserveBegin", "begin", bindVariables, - target, options, false, /* allowOnShutdown */ - func(ctx context.Context, logStats *tabletenv.LogStats) error { - defer tsv.stats.QueryTimings.Record("RESERVE", time.Now()) - targetType, err := tsv.resolveTargetType(ctx, target) - if err != nil { - return err - } - defer tsv.stats.QueryTimingsByTabletType.Record(targetType.String(), time.Now()) - connID, sessionStateChanges, err = tsv.te.ReserveBegin(ctx, options, preQueries, postBeginQueries) - if err != nil { - return err - } - logStats.TransactionID = connID - logStats.ReservedID = connID - return nil - }, - ) - + txState, err := tsv.begin(ctx, target, savepointQueries, 0, settings, options) if err != nil { - return state, err + return txToReserveState(txState), err } - state.ReservedID = connID - state.TransactionID = connID - state.TabletAlias = tsv.alias - state.SessionStateChanges = sessionStateChanges - err = tsv.streamExecute(ctx, target, sql, bindVariables, state.TransactionID, state.ReservedID, nil, options, callback) - return state, err + err = tsv.streamExecute(ctx, target, sql, bindVariables, txState.TransactionID, 0, settings, options, callback) + return txToReserveState(txState), err } // ReserveExecute implements the QueryService interface func (tsv *TabletServer) ReserveExecute(ctx context.Context, target *querypb.Target, preQueries []string, sql string, bindVariables map[string]*querypb.BindVariable, transactionID int64, options *querypb.ExecuteOptions) (state queryservice.ReservedState, result *sqltypes.Result, err error) { - if tsv.config.EnableSettingsPool { - result, err = tsv.executeWithSettings(ctx, target, preQueries, sql, bindVariables, transactionID, options) - // If there is an error and the error message is about allowing query in reserved connection only, - // then we do not return an error from here and continue to use the reserved connection path. - // This is specially for get_lock function call from vtgate that needs a reserved connection. - if err == nil || !strings.Contains(err.Error(), "not allowed without reserved connection") { - return state, result, err - } + + result, err = tsv.executeWithSettings(ctx, target, preQueries, sql, bindVariables, transactionID, options) + // If there is an error and the error message is about allowing query in reserved connection only, + // then we do not return an error from here and continue to use the reserved connection path. + // This is specially for get_lock function call from vtgate that needs a reserved connection. + if err == nil || !strings.Contains(err.Error(), "not allowed without reserved connection") { + return state, result, err } + // needs a reserved connection to execute the query. state.TabletAlias = tsv.alias allowOnShutdown := false @@ -1386,48 +1338,7 @@ func (tsv *TabletServer) ReserveStreamExecute( options *querypb.ExecuteOptions, callback func(*sqltypes.Result) error, ) (state queryservice.ReservedState, err error) { - if tsv.config.EnableSettingsPool { - return state, tsv.streamExecute(ctx, target, sql, bindVariables, transactionID, 0, preQueries, options, callback) - } - - state.TabletAlias = tsv.alias - - allowOnShutdown := false - var timeout time.Duration - if transactionID != 0 { - allowOnShutdown = true - // Use the transaction timeout. ReserveStreamExecute is used for OLAP - // only, so we can directly fetch the OLAP TX timeout. - timeout = tsv.config.TxTimeoutForWorkload(querypb.ExecuteOptions_OLAP) - } - - err = tsv.execRequest( - ctx, timeout, - "Reserve", "", bindVariables, - target, options, allowOnShutdown, - func(ctx context.Context, logStats *tabletenv.LogStats) error { - defer tsv.stats.QueryTimings.Record("RESERVE", time.Now()) - targetType, err := tsv.resolveTargetType(ctx, target) - if err != nil { - return err - } - defer tsv.stats.QueryTimingsByTabletType.Record(targetType.String(), time.Now()) - state.ReservedID, err = tsv.te.Reserve(ctx, options, transactionID, preQueries) - if err != nil { - return err - } - logStats.TransactionID = state.ReservedID - logStats.ReservedID = state.ReservedID - return nil - }, - ) - - if err != nil { - return state, err - } - - err = tsv.streamExecute(ctx, target, sql, bindVariables, transactionID, state.ReservedID, nil, options, callback) - return state, err + return state, tsv.streamExecute(ctx, target, sql, bindVariables, transactionID, 0, preQueries, options, callback) } // Release implements the QueryService interface @@ -1477,16 +1388,6 @@ func (tsv *TabletServer) beginExecuteWithSettings(ctx context.Context, target *q return txToReserveState(txState), result, err } -func (tsv *TabletServer) beginStreamExecuteWithSettings(ctx context.Context, target *querypb.Target, settings []string, savepointQueries []string, sql string, bindVariables map[string]*querypb.BindVariable, options *querypb.ExecuteOptions, callback func(*sqltypes.Result) error) (queryservice.ReservedTransactionState, error) { - txState, err := tsv.begin(ctx, target, savepointQueries, 0, settings, options) - if err != nil { - return txToReserveState(txState), err - } - - err = tsv.streamExecute(ctx, target, sql, bindVariables, txState.TransactionID, 0, settings, options, callback) - return txToReserveState(txState), err -} - func txToReserveState(state queryservice.TransactionState) queryservice.ReservedTransactionState { return queryservice.ReservedTransactionState{ TabletAlias: state.TabletAlias, @@ -1777,7 +1678,13 @@ func (tsv *TabletServer) TopoServer() *topo.Server { // CheckThrottler issues a self check func (tsv *TabletServer) CheckThrottler(ctx context.Context, appName string, flags *throttle.CheckFlags) *throttle.CheckResult { - r := tsv.lagThrottler.CheckByType(ctx, appName, "", flags, throttle.ThrottleCheckSelf) + r := tsv.lagThrottler.Check(ctx, appName, nil, flags) + return r +} + +// GetThrottlerStatus gets the status of the tablet throttler +func (tsv *TabletServer) GetThrottlerStatus(ctx context.Context) *throttle.ThrottlerStatus { + r := tsv.lagThrottler.Status() return r } @@ -1860,11 +1767,7 @@ func (tsv *TabletServer) registerQueryListHandlers(queryLists []*QueryList) { func (tsv *TabletServer) registerTwopczHandler() { tsv.exporter.HandleFunc("/twopcz", func(w http.ResponseWriter, r *http.Request) { ctx := tabletenv.LocalContext() - txe := &TxExecutor{ - ctx: ctx, - logStats: tabletenv.NewLogStats(ctx, "twopcz"), - te: tsv.te, - } + txe := NewDTExecutor(ctx, tsv.te, tabletenv.NewLogStats(ctx, "twopcz")) twopczHandler(txe, w, r) }) } @@ -1883,22 +1786,20 @@ func (tsv *TabletServer) registerMigrationStatusHandler() { // registerThrottlerCheckHandlers registers throttler "check" requests func (tsv *TabletServer) registerThrottlerCheckHandlers() { - handle := func(path string, checkType throttle.ThrottleCheckType) { + handle := func(path string, scope base.Scope) { tsv.exporter.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) { ctx := tabletenv.LocalContext() - remoteAddr := r.Header.Get("X-Forwarded-For") - if remoteAddr == "" { - remoteAddr = r.RemoteAddr - remoteAddr = strings.Split(remoteAddr, ":")[0] - } appName := r.URL.Query().Get("app") if appName == "" { - appName = throttlerapp.DefaultName.String() + appName = throttlerapp.VitessName.String() } flags := &throttle.CheckFlags{ + Scope: scope, SkipRequestHeartbeats: (r.URL.Query().Get("s") == "true"), + MultiMetricsEnabled: true, } - checkResult := tsv.lagThrottler.CheckByType(ctx, appName, remoteAddr, flags, checkType) + metricNames := tsv.lagThrottler.MetricNames(r.URL.Query()["m"]) + checkResult := tsv.lagThrottler.Check(ctx, appName, metricNames, flags) if checkResult.StatusCode == http.StatusNotFound && flags.OKIfNotExists { checkResult.StatusCode = http.StatusOK // 200 } @@ -1912,8 +1813,8 @@ func (tsv *TabletServer) registerThrottlerCheckHandlers() { } }) } - handle("/throttler/check", throttle.ThrottleCheckPrimaryWrite) - handle("/throttler/check-self", throttle.ThrottleCheckSelf) + handle("/throttler/check", base.ShardScope) + handle("/throttler/check-self", base.SelfScope) } // registerThrottlerStatusHandler registers a throttler "status" request diff --git a/go/vt/vttablet/tabletserver/tabletserver_test.go b/go/vt/vttablet/tabletserver/tabletserver_test.go index ee91f05c2a5..7ffd201c0a4 100644 --- a/go/vt/vttablet/tabletserver/tabletserver_test.go +++ b/go/vt/vttablet/tabletserver/tabletserver_test.go @@ -675,7 +675,6 @@ func TestTabletServerReserveConnection(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() db, tsv := setupTabletServerTest(t, ctx, "") - tsv.config.EnableSettingsPool = false defer tsv.StopService() defer db.Close() @@ -684,7 +683,7 @@ func TestTabletServerReserveConnection(t *testing.T) { options := &querypb.ExecuteOptions{} // reserve a connection - state, _, err := tsv.ReserveExecute(ctx, &target, nil, "select 42", nil, 0, options) + state, _, err := tsv.ReserveExecute(ctx, &target, nil, "set sql_mode = ''", nil, 0, options) require.NoError(t, err) // run a query in it @@ -747,7 +746,6 @@ func TestTabletServerReserveAndBeginCommit(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() db, tsv := setupTabletServerTest(t, ctx, "") - tsv.config.EnableSettingsPool = false defer tsv.StopService() defer db.Close() @@ -756,7 +754,7 @@ func TestTabletServerReserveAndBeginCommit(t *testing.T) { options := &querypb.ExecuteOptions{} // reserve a connection and a transaction - state, _, err := tsv.ReserveBeginExecute(ctx, &target, nil, nil, "select 42", nil, options) + state, _, err := tsv.ReserveBeginExecute(ctx, &target, nil, nil, "set sql_mode = ''", nil, options) require.NoError(t, err) defer func() { // fallback so the test finishes quickly @@ -2192,20 +2190,19 @@ func TestReserveBeginExecute(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() db, tsv := setupTabletServerTest(t, ctx, "") - tsv.config.EnableSettingsPool = false defer tsv.StopService() defer db.Close() target := querypb.Target{TabletType: topodatapb.TabletType_PRIMARY} + db.AddQueryPattern("set @@sql_mode = ''", &sqltypes.Result{}) - state, _, err := tsv.ReserveBeginExecute(ctx, &target, []string{"select 43"}, nil, "select 42", nil, &querypb.ExecuteOptions{}) + state, _, err := tsv.ReserveBeginExecute(ctx, &target, nil, nil, "set @@sql_mode = ''", nil, &querypb.ExecuteOptions{}) require.NoError(t, err) assert.Greater(t, state.TransactionID, int64(0), "transactionID") - assert.Equal(t, state.ReservedID, state.TransactionID, "reservedID should equal transactionID") + assert.Equal(t, state.TransactionID, state.ReservedID, "reservedID should equal transactionID") expected := []string{ - "select 43", "begin", - "select 42 from dual limit 10001", + "set @@sql_mode = ''", } splitOutput := strings.Split(db.QueryLog(), ";") for _, exp := range expected { @@ -2219,18 +2216,17 @@ func TestReserveExecute_WithoutTx(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() db, tsv := setupTabletServerTest(t, ctx, "") - tsv.config.EnableSettingsPool = false defer tsv.StopService() defer db.Close() + db.AddQueryPattern("set @@sql_mode = ''", &sqltypes.Result{}) target := querypb.Target{TabletType: topodatapb.TabletType_PRIMARY} - state, _, err := tsv.ReserveExecute(ctx, &target, []string{"select 43"}, "select 42", nil, 0, &querypb.ExecuteOptions{}) + state, _, err := tsv.ReserveExecute(ctx, &target, nil, "set sql_mode = ''", nil, 0, &querypb.ExecuteOptions{}) require.NoError(t, err) assert.NotEqual(t, int64(0), state.ReservedID, "reservedID should not be zero") expected := []string{ - "select 43", - "select 42 from dual limit 10001", + "set @@sql_mode = ''", } splitOutput := strings.Split(db.QueryLog(), ";") for _, exp := range expected { @@ -2244,9 +2240,10 @@ func TestReserveExecute_WithTx(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() db, tsv := setupTabletServerTest(t, ctx, "") - tsv.config.EnableSettingsPool = false defer tsv.StopService() defer db.Close() + + db.AddQueryPattern("set @@sql_mode = ''", &sqltypes.Result{}) target := querypb.Target{TabletType: topodatapb.TabletType_PRIMARY} beginState, err := tsv.Begin(ctx, &target, &querypb.ExecuteOptions{}) @@ -2254,13 +2251,12 @@ func TestReserveExecute_WithTx(t *testing.T) { require.NotEqual(t, int64(0), beginState.TransactionID) db.ResetQueryLog() - reserveState, _, err := tsv.ReserveExecute(ctx, &target, []string{"select 43"}, "select 42", nil, beginState.TransactionID, &querypb.ExecuteOptions{}) + reserveState, _, err := tsv.ReserveExecute(ctx, &target, nil, "set sql_mode = ''", nil, beginState.TransactionID, &querypb.ExecuteOptions{}) require.NoError(t, err) defer tsv.Release(ctx, &target, beginState.TransactionID, reserveState.ReservedID) assert.Equal(t, beginState.TransactionID, reserveState.ReservedID, "reservedID should be equal to transactionID") expected := []string{ - "select 43", - "select 42 from dual limit 10001", + "set @@sql_mode = ''", } splitOutput := strings.Split(db.QueryLog(), ";") for _, exp := range expected { @@ -2306,7 +2302,6 @@ func TestRelease(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() db, tsv := setupTabletServerTest(t, ctx, "") - tsv.config.EnableSettingsPool = false defer tsv.StopService() defer db.Close() db.AddQueryPattern(".*", &sqltypes.Result{}) @@ -2316,7 +2311,7 @@ func TestRelease(t *testing.T) { switch { case test.begin && test.reserve: - state, _, err := tsv.ReserveBeginExecute(ctx, &target, []string{"select 1212"}, nil, "select 42", nil, &querypb.ExecuteOptions{}) + state, _, err := tsv.ReserveBeginExecute(ctx, &target, nil, nil, "set sql_mode = ''", nil, &querypb.ExecuteOptions{}) require.NoError(t, err) transactionID = state.TransactionID reservedID = state.ReservedID @@ -2328,7 +2323,7 @@ func TestRelease(t *testing.T) { transactionID = state.TransactionID require.NotEqual(t, int64(0), transactionID) case test.reserve: - state, _, err := tsv.ReserveExecute(ctx, &target, nil, "select 42", nil, 0, &querypb.ExecuteOptions{}) + state, _, err := tsv.ReserveExecute(ctx, &target, nil, "set sql_mode = ''", nil, 0, &querypb.ExecuteOptions{}) require.NoError(t, err) reservedID = state.ReservedID require.NotEqual(t, int64(0), reservedID) @@ -2351,10 +2346,10 @@ func TestReserveStats(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() db, tsv := setupTabletServerTest(t, ctx, "") - tsv.config.EnableSettingsPool = false defer tsv.StopService() defer db.Close() + db.AddQueryPattern("set @@sql_mode = ''", &sqltypes.Result{}) target := querypb.Target{TabletType: topodatapb.TabletType_PRIMARY} callerID := &querypb.VTGateCallerID{ @@ -2363,12 +2358,12 @@ func TestReserveStats(t *testing.T) { ctx = callerid.NewContext(ctx, nil, callerID) // Starts reserved connection and transaction - rbeState, _, err := tsv.ReserveBeginExecute(ctx, &target, nil, nil, "select 42", nil, &querypb.ExecuteOptions{}) + rbeState, _, err := tsv.ReserveBeginExecute(ctx, &target, nil, nil, "set sql_mode = ''", nil, &querypb.ExecuteOptions{}) require.NoError(t, err) assert.EqualValues(t, 1, tsv.te.txPool.env.Stats().UserActiveReservedCount.Counts()["test"]) // Starts reserved connection - reState, _, err := tsv.ReserveExecute(ctx, &target, nil, "select 42", nil, 0, &querypb.ExecuteOptions{}) + reState, _, err := tsv.ReserveExecute(ctx, &target, nil, "set sql_mode = ''", nil, 0, &querypb.ExecuteOptions{}) require.NoError(t, err) assert.EqualValues(t, 2, tsv.te.txPool.env.Stats().UserActiveReservedCount.Counts()["test"]) @@ -2383,7 +2378,7 @@ func TestReserveStats(t *testing.T) { assert.EqualValues(t, 2, tsv.te.txPool.env.Stats().UserActiveReservedCount.Counts()["test"]) // Reserved the connection on previous transaction - beReState, _, err := tsv.ReserveExecute(ctx, &target, nil, "select 42", nil, beState.TransactionID, &querypb.ExecuteOptions{}) + beReState, _, err := tsv.ReserveExecute(ctx, &target, nil, "set sql_mode = ''", nil, beState.TransactionID, &querypb.ExecuteOptions{}) require.NoError(t, err) assert.EqualValues(t, 3, tsv.te.txPool.env.Stats().UserActiveReservedCount.Counts()["test"]) @@ -2526,12 +2521,11 @@ func TestDatabaseNameReplaceByKeyspaceNameReserveExecuteMethod(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() db, tsv := setupTabletServerTest(t, ctx, "keyspaceName") - tsv.config.EnableSettingsPool = false setDBName(db, tsv, "databaseInMysql") defer tsv.StopService() defer db.Close() - executeSQL := "select * from test_table limit 1000" + executeSQL := "select 43" executeSQLResult := &sqltypes.Result{ Fields: []*querypb.Field{ { @@ -2539,24 +2533,21 @@ func TestDatabaseNameReplaceByKeyspaceNameReserveExecuteMethod(t *testing.T) { Database: "databaseInMysql", }, }, - RowsAffected: 1, Rows: [][]sqltypes.Value{ - {sqltypes.NewVarBinary("row01")}, + {sqltypes.NewInt64(43)}, }, } - db.AddQuery(executeSQL, executeSQLResult) + db.AddQuery("select 43 from dual limit 10001", executeSQLResult) target := tsv.sm.target // Test ReserveExecute - state, res, err := tsv.ReserveExecute(ctx, target, nil, executeSQL, nil, 0, &querypb.ExecuteOptions{ + _, res, err := tsv.ReserveExecute(ctx, target, nil, executeSQL, nil, 0, &querypb.ExecuteOptions{ IncludedFields: querypb.ExecuteOptions_ALL, }) require.NoError(t, err) for _, field := range res.Fields { require.Equal(t, "keyspaceName", field.Database) } - err = tsv.Release(ctx, target, 0, state.ReservedID) - require.NoError(t, err) } func TestDatabaseNameReplaceByKeyspaceNameReserveBeginExecuteMethod(t *testing.T) { @@ -2754,10 +2745,10 @@ func addTabletServerSupportedQueries(db *fakesqldb.DB) { Type: sqltypes.Int64, }}, }, - "begin": {}, - "commit": {}, - "rollback": {}, - fmt.Sprintf(sqlReadAllRedo, "_vt", "_vt"): {}, + "begin": {}, + "commit": {}, + "rollback": {}, + fmt.Sprintf(readAllRedo, "_vt", "_vt"): {}, } parser := sqlparser.NewTestParser() sidecardb.AddSchemaInitQueries(db, true, parser) diff --git a/go/vt/vttablet/tabletserver/throttle/config/store_config.go b/go/vt/vttablet/tabletserver/throttle/base/inventory.go similarity index 81% rename from go/vt/vttablet/tabletserver/throttle/config/store_config.go rename to go/vt/vttablet/tabletserver/throttle/base/inventory.go index 7e5594050d9..5294caf1115 100644 --- a/go/vt/vttablet/tabletserver/throttle/config/store_config.go +++ b/go/vt/vttablet/tabletserver/throttle/base/inventory.go @@ -39,15 +39,20 @@ limitations under the License. SOFTWARE. */ -package config - -// -// General-store configuration -// - -// StoresSettings is a general settings container for specific stores. -type StoresSettings struct { - MySQL MySQLConfigurationSettings // Any and all MySQL setups go here +package base + +// Inventory has the operational data about probes, their metrics, and relevant configuration +type Inventory struct { + ClustersProbes Probes + IgnoreHostsCount int + IgnoreHostsThreshold float64 + TabletMetrics TabletResultMap +} - // Futuristic stores can come here. +// NewInventory creates a Inventory +func NewInventory() *Inventory { + inventory := &Inventory{ + TabletMetrics: make(TabletResultMap), + } + return inventory } diff --git a/go/vt/vttablet/tabletserver/throttle/base/inventory_test.go b/go/vt/vttablet/tabletserver/throttle/base/inventory_test.go new file mode 100644 index 00000000000..2850a3b3035 --- /dev/null +++ b/go/vt/vttablet/tabletserver/throttle/base/inventory_test.go @@ -0,0 +1,47 @@ +/* +Copyright 2024 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 base + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "golang.org/x/exp/maps" +) + +func TestTabletResultMapSplit(t *testing.T) { + tabletResultMap := TabletResultMap{ + "a": make(MetricResultMap), + "b": make(MetricResultMap), + "c": make(MetricResultMap), + } + { + withAlias, all := tabletResultMap.Split("b") + + assert.Equal(t, 1, len(withAlias)) + assert.EqualValues(t, maps.Keys(withAlias), []string{"b"}) + assert.Equal(t, 3, len(all)) + assert.ElementsMatch(t, maps.Keys(all), []string{"a", "b", "c"}) + } + { + withAlias, all := tabletResultMap.Split("x") + + assert.Equal(t, 0, len(withAlias)) + assert.Equal(t, 3, len(all)) + assert.ElementsMatch(t, maps.Keys(all), []string{"a", "b", "c"}) + } +} diff --git a/go/vt/vttablet/tabletserver/throttle/mysql/probe.go b/go/vt/vttablet/tabletserver/throttle/base/probe.go similarity index 97% rename from go/vt/vttablet/tabletserver/throttle/mysql/probe.go rename to go/vt/vttablet/tabletserver/throttle/base/probe.go index 8c3e069c0d1..0fe813d571e 100644 --- a/go/vt/vttablet/tabletserver/throttle/mysql/probe.go +++ b/go/vt/vttablet/tabletserver/throttle/base/probe.go @@ -39,7 +39,7 @@ limitations under the License. SOFTWARE. */ -package mysql +package base import ( "fmt" @@ -50,7 +50,6 @@ import ( // Probe is the minimal configuration required to connect to a MySQL server type Probe struct { Alias string - MetricQuery string Tablet *topodatapb.Tablet CacheMillis int QueryInProgress int64 @@ -61,7 +60,6 @@ type Probes map[string](*Probe) // ClusterProbes has the probes for a specific cluster type ClusterProbes struct { - ClusterName string IgnoreHostsCount int IgnoreHostsThreshold float64 TabletProbes Probes diff --git a/go/vt/vttablet/tabletserver/throttle/mysql/probe_test.go b/go/vt/vttablet/tabletserver/throttle/base/probe_test.go similarity index 99% rename from go/vt/vttablet/tabletserver/throttle/mysql/probe_test.go rename to go/vt/vttablet/tabletserver/throttle/base/probe_test.go index 8f489f39258..af1b09ec181 100644 --- a/go/vt/vttablet/tabletserver/throttle/mysql/probe_test.go +++ b/go/vt/vttablet/tabletserver/throttle/base/probe_test.go @@ -39,7 +39,7 @@ limitations under the License. SOFTWARE. */ -package mysql +package base import ( "testing" diff --git a/go/vt/vttablet/tabletserver/throttle/base/recent_app.go b/go/vt/vttablet/tabletserver/throttle/base/recent_app.go index 64527c4cc1c..148e6b31fe4 100644 --- a/go/vt/vttablet/tabletserver/throttle/base/recent_app.go +++ b/go/vt/vttablet/tabletserver/throttle/base/recent_app.go @@ -46,15 +46,17 @@ import ( // RecentApp indicates when an app was last checked type RecentApp struct { - CheckedAtEpoch int64 - MinutesSinceChecked int64 + AppName string + CheckedAt time.Time + StatusCode int } // NewRecentApp creates a RecentApp -func NewRecentApp(checkedAt time.Time) *RecentApp { +func NewRecentApp(appName string, statusCode int) *RecentApp { result := &RecentApp{ - CheckedAtEpoch: checkedAt.Unix(), - MinutesSinceChecked: int64(time.Since(checkedAt).Minutes()), + AppName: appName, + CheckedAt: time.Now(), + StatusCode: statusCode, } return result } diff --git a/go/vt/vttablet/tabletserver/throttle/mysql.go b/go/vt/vttablet/tabletserver/throttle/base/tablet_results.go similarity index 52% rename from go/vt/vttablet/tabletserver/throttle/mysql.go rename to go/vt/vttablet/tabletserver/throttle/base/tablet_results.go index 81a967ddacb..88e958e884e 100644 --- a/go/vt/vttablet/tabletserver/throttle/mysql.go +++ b/go/vt/vttablet/tabletserver/throttle/base/tablet_results.go @@ -14,62 +14,42 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This codebase originates from https://github.com/github/freno, See https://github.com/github/freno/blob/master/LICENSE -/* - MIT License - - Copyright (c) 2017 GitHub - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ +package base -package throttle +import "sort" -import ( - "context" - "sort" +// TabletResultMap maps a tablet to a result +type TabletResultMap map[string]MetricResultMap - "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base" - "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/mysql" -) +func (m TabletResultMap) Split(alias string) (withAlias TabletResultMap, all TabletResultMap) { + withAlias = make(TabletResultMap) + if val, ok := m[alias]; ok { + withAlias[alias] = val + } + return withAlias, m +} -func aggregateMySQLProbes( - ctx context.Context, - probes mysql.Probes, - clusterName string, - tabletResultsMap mysql.TabletResultMap, +func AggregateTabletMetricResults( + metricName MetricName, + tabletResultsMap TabletResultMap, ignoreHostsCount int, IgnoreDialTCPErrors bool, ignoreHostsThreshold float64, -) (worstMetric base.MetricResult) { +) (worstMetric MetricResult) { // probes is known not to change. It can be *replaced*, but not changed. // so it's safe to iterate it probeValues := []float64{} - for _, probe := range probes { - tabletMetricResult, ok := tabletResultsMap[mysql.GetClusterTablet(clusterName, probe.Alias)] + for _, tabletMetricResults := range tabletResultsMap { + tabletMetricResult, ok := tabletMetricResults[metricName] if !ok { - return base.NoMetricResultYet + return NoSuchMetric + } + if tabletMetricResult == nil { + return NoMetricResultYet } - value, err := tabletMetricResult.Get() if err != nil { - if IgnoreDialTCPErrors && base.IsDialTCPError(err) { + if IgnoreDialTCPErrors && IsDialTCPError(err) { continue } if ignoreHostsCount > 0 { @@ -84,7 +64,7 @@ func aggregateMySQLProbes( probeValues = append(probeValues, value) } if len(probeValues) == 0 { - return base.NoHostsMetricResult + return NoHostsMetricResult } // If we got here, that means no errors (or good-to-skip errors) @@ -114,6 +94,6 @@ func aggregateMySQLProbes( ignoreHostsCount = ignoreHostsCount - 1 } worstValue := probeValues[len(probeValues)-1] - worstMetric = base.NewSimpleMetricResult(worstValue) + worstMetric = NewSimpleMetricResult(worstValue) return worstMetric } diff --git a/go/vt/vttablet/tabletserver/throttle/base/tablet_results_test.go b/go/vt/vttablet/tabletserver/throttle/base/tablet_results_test.go new file mode 100644 index 00000000000..98888eebbb8 --- /dev/null +++ b/go/vt/vttablet/tabletserver/throttle/base/tablet_results_test.go @@ -0,0 +1,199 @@ +/* +Copyright 2024 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 base + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +var ( + alias1 = "zone1-0001" + alias2 = "zone1-0002" + alias3 = "zone1-0003" + alias4 = "zone1-0004" + alias5 = "zone1-0005" +) + +const ( + nonexistentMetricName MetricName = "nonexistent" +) + +func newMetricResultMap(val float64) MetricResultMap { + return MetricResultMap{ + DefaultMetricName: NewSimpleMetricResult(val), + LagMetricName: NewSimpleMetricResult(val), + LoadAvgMetricName: NewSimpleMetricResult(3.14), + } +} +func noSuchMetricMap() MetricResultMap { + result := make(MetricResultMap) + for _, metricName := range KnownMetricNames { + result[metricName] = NoSuchMetric + } + return result +} + +func TestAggregateTabletMetricResultsNoErrors(t *testing.T) { + tabletResultsMap := TabletResultMap{ + alias1: newMetricResultMap(1.2), + alias2: newMetricResultMap(1.7), + alias3: newMetricResultMap(0.3), + alias4: newMetricResultMap(0.6), + alias5: newMetricResultMap(1.1), + } + + { + worstMetric := AggregateTabletMetricResults(DefaultMetricName, tabletResultsMap, 0, false, 0) + value, err := worstMetric.Get() + assert.NoError(t, err) + assert.Equal(t, value, 1.7) + } + { + worstMetric := AggregateTabletMetricResults(DefaultMetricName, tabletResultsMap, 1, false, 0) + value, err := worstMetric.Get() + assert.NoError(t, err) + assert.Equal(t, value, 1.2) + } + { + worstMetric := AggregateTabletMetricResults(DefaultMetricName, tabletResultsMap, 2, false, 0) + value, err := worstMetric.Get() + assert.NoError(t, err) + assert.Equal(t, value, 1.1) + } + { + worstMetric := AggregateTabletMetricResults(DefaultMetricName, tabletResultsMap, 3, false, 0) + value, err := worstMetric.Get() + assert.NoError(t, err) + assert.Equal(t, value, 0.6) + } + { + worstMetric := AggregateTabletMetricResults(DefaultMetricName, tabletResultsMap, 4, false, 0) + value, err := worstMetric.Get() + assert.NoError(t, err) + assert.Equal(t, value, 0.3) + } + { + worstMetric := AggregateTabletMetricResults(DefaultMetricName, tabletResultsMap, 5, false, 0) + value, err := worstMetric.Get() + assert.NoError(t, err) + assert.Equal(t, value, 0.3) + } +} + +func TestAggregateTabletMetricResultsNoErrorsIgnoreHostsThreshold(t *testing.T) { + tabletResultsMap := TabletResultMap{ + alias1: newMetricResultMap(1.2), + alias2: newMetricResultMap(1.7), + alias3: newMetricResultMap(0.3), + alias4: newMetricResultMap(0.6), + alias5: newMetricResultMap(1.1), + } + + { + worstMetric := AggregateTabletMetricResults(DefaultMetricName, tabletResultsMap, 0, false, 1.0) + value, err := worstMetric.Get() + assert.NoError(t, err) + assert.Equal(t, value, 1.7) + } + { + worstMetric := AggregateTabletMetricResults(DefaultMetricName, tabletResultsMap, 1, false, 1.0) + value, err := worstMetric.Get() + assert.NoError(t, err) + assert.Equal(t, value, 1.2) + } + { + worstMetric := AggregateTabletMetricResults(DefaultMetricName, tabletResultsMap, 2, false, 1.0) + value, err := worstMetric.Get() + assert.NoError(t, err) + assert.Equal(t, value, 1.1) + } + { + worstMetric := AggregateTabletMetricResults(DefaultMetricName, tabletResultsMap, 3, false, 1.0) + value, err := worstMetric.Get() + assert.NoError(t, err) + assert.Equal(t, value, 0.6) + } + { + worstMetric := AggregateTabletMetricResults(DefaultMetricName, tabletResultsMap, 4, false, 1.0) + value, err := worstMetric.Get() + assert.NoError(t, err) + assert.Equal(t, value, 0.6) + } + { + worstMetric := AggregateTabletMetricResults(DefaultMetricName, tabletResultsMap, 5, false, 1.0) + value, err := worstMetric.Get() + assert.NoError(t, err) + assert.Equal(t, value, 0.6) + } +} + +func TestAggregateTabletMetricResultsWithErrors(t *testing.T) { + tabletResultsMap := TabletResultMap{ + alias1: newMetricResultMap(1.2), + alias2: newMetricResultMap(1.7), + alias3: newMetricResultMap(0.3), + alias4: noSuchMetricMap(), + alias5: newMetricResultMap(1.1), + } + + t.Run("nonexistent", func(t *testing.T) { + worstMetric := AggregateTabletMetricResults(nonexistentMetricName, tabletResultsMap, 0, false, 0) + _, err := worstMetric.Get() + assert.Error(t, err) + assert.Equal(t, ErrNoSuchMetric, err) + }) + t.Run("no ignore", func(t *testing.T) { + worstMetric := AggregateTabletMetricResults(DefaultMetricName, tabletResultsMap, 0, false, 0) + _, err := worstMetric.Get() + assert.Error(t, err) + assert.Equal(t, ErrNoSuchMetric, err) + }) + t.Run("ignore 1", func(t *testing.T) { + worstMetric := AggregateTabletMetricResults(DefaultMetricName, tabletResultsMap, 1, false, 0) + value, err := worstMetric.Get() + assert.NoError(t, err) + assert.Equal(t, 1.7, value) + }) + t.Run("ignore 2", func(t *testing.T) { + worstMetric := AggregateTabletMetricResults(DefaultMetricName, tabletResultsMap, 2, false, 0) + value, err := worstMetric.Get() + assert.NoError(t, err) + assert.Equal(t, 1.2, value) + }) + + tabletResultsMap[alias1][DefaultMetricName] = NoSuchMetric + t.Run("no such metric", func(t *testing.T) { + worstMetric := AggregateTabletMetricResults(DefaultMetricName, tabletResultsMap, 0, false, 0) + _, err := worstMetric.Get() + assert.Error(t, err) + assert.Equal(t, ErrNoSuchMetric, err) + }) + t.Run("no such metric, ignore 1", func(t *testing.T) { + worstMetric := AggregateTabletMetricResults(DefaultMetricName, tabletResultsMap, 1, false, 0) + _, err := worstMetric.Get() + assert.Error(t, err) + assert.Equal(t, ErrNoSuchMetric, err) + }) + t.Run("metric found", func(t *testing.T) { + worstMetric := AggregateTabletMetricResults(DefaultMetricName, tabletResultsMap, 2, false, 0) + value, err := worstMetric.Get() + assert.NoError(t, err) + assert.Equal(t, value, 1.7) + }) +} diff --git a/go/vt/vttablet/tabletserver/throttle/base/throttle_metric.go b/go/vt/vttablet/tabletserver/throttle/base/throttle_metric.go index 3d4c4f95a2e..054687cdd3f 100644 --- a/go/vt/vttablet/tabletserver/throttle/base/throttle_metric.go +++ b/go/vt/vttablet/tabletserver/throttle/base/throttle_metric.go @@ -14,38 +14,169 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This codebase originates from https://github.com/github/freno, See https://github.com/github/freno/blob/master/LICENSE -/* - MIT License - - Copyright (c) 2017 GitHub - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ - package base import ( "errors" + "fmt" + "slices" "strings" ) +// Scope defines the tablet range from which a metric is collected. This can be the local tablet +// ("self") or the entire shard ("shard") +type Scope string + +const ( + UndefinedScope Scope = "" + ShardScope Scope = "shard" + SelfScope Scope = "self" +) + +func (s Scope) String() string { + return string(s) +} + +func ScopeFromString(s string) (Scope, error) { + switch scope := Scope(s); scope { + case UndefinedScope, ShardScope, SelfScope: + return scope, nil + default: + return "", fmt.Errorf("unknown scope: %s", s) + } +} + +// MetricName is a formalized name for a metric, such as "lag" or "threads_running". A metric name +// may include a scope, such as "self/lag" or "shard/threads_running". It is possible to add a +// scope to a name, or to parse the scope out of a name, and there is also always a default scope +// associated with a metric name. +type MetricName string + +// MetricNames is a formalized list of metric names +type MetricNames []MetricName + +func (names MetricNames) Contains(name MetricName) bool { + return slices.Contains(names, name) +} + +func (names MetricNames) String() string { + s := make([]string, len(names)) + for i, name := range names { + s[i] = name.String() + } + return strings.Join(s, ",") +} + +// Unique returns a subset of unique metric names, in same order as the original names +func (names MetricNames) Unique() MetricNames { + if names == nil { + return nil + } + uniqueMetricNamesMap := map[MetricName]bool{} + uniqueMetricNames := MetricNames{} + for _, metricName := range names { + if _, ok := uniqueMetricNamesMap[metricName]; !ok { + uniqueMetricNames = append(uniqueMetricNames, metricName) + uniqueMetricNamesMap[metricName] = true + } + } + return uniqueMetricNames +} + +const ( + DefaultMetricName MetricName = "default" + LagMetricName MetricName = "lag" + ThreadsRunningMetricName MetricName = "threads_running" + CustomMetricName MetricName = "custom" + LoadAvgMetricName MetricName = "loadavg" +) + +func (metric MetricName) DefaultScope() Scope { + switch metric { + case LagMetricName: + return ShardScope + default: + return SelfScope + } +} + +func (metric MetricName) String() string { + return string(metric) +} + +// AggregatedName returns the string representation of this metric in the given scope, e.g.: +// - "self/loadavg" +// - "shard/lag" +func (metric MetricName) AggregatedName(scope Scope) string { + if metric == DefaultMetricName { + // backwards (v20) compatibility + return scope.String() + } + if scope == UndefinedScope { + scope = metric.DefaultScope() + } + return fmt.Sprintf("%s/%s", scope.String(), metric.String()) +} + +// Disaggregated returns a breakdown of this metric into scope + name. +func (metric MetricName) Disaggregated() (scope Scope, metricName MetricName, err error) { + return DisaggregateMetricName(metric.String()) +} + +var KnownMetricNames = MetricNames{ + DefaultMetricName, + LagMetricName, + ThreadsRunningMetricName, + CustomMetricName, + LoadAvgMetricName, +} + +type AggregatedMetricName struct { + Scope Scope + Metric MetricName +} + +var ( + // aggregatedMetricNames precomputes the aggregated metric names for all known metric names, + // mapped to their breakdowns. e.g. "self/loadavg" -> {SelfScope, LoadAvgMetricName} + // This means: + // - no textual parsing is needed in the critical path + // - we can easily check if a metric name is valid + aggregatedMetricNames map[string]AggregatedMetricName +) + +func init() { + aggregatedMetricNames = make(map[string]AggregatedMetricName, 3*len(KnownMetricNames)) + for _, metricName := range KnownMetricNames { + aggregatedMetricNames[metricName.String()] = AggregatedMetricName{ + Scope: metricName.DefaultScope(), + Metric: metricName, + } + for _, scope := range []Scope{ShardScope, SelfScope} { + aggregatedName := metricName.AggregatedName(scope) + aggregatedMetricNames[aggregatedName] = AggregatedMetricName{ + Scope: scope, + Metric: metricName, + } + } + } +} + +// DisaggregateMetricName splits a metric name into its scope name and metric name +// aggregated metric name could be in the form: +// - loadavg +// - self +// - self/threads_running +// - shard +// - shard/lag +func DisaggregateMetricName(aggregatedMetricName string) (scope Scope, metricName MetricName, err error) { + breakdown, ok := aggregatedMetricNames[aggregatedMetricName] + if !ok { + return UndefinedScope, DefaultMetricName, ErrNoSuchMetric + } + return breakdown.Scope, breakdown.Metric, nil +} + // MetricResult is what we expect our probes to return. This can be a numeric result, or // a special type of result indicating more meta-information type MetricResult interface { @@ -55,15 +186,25 @@ type MetricResult interface { // MetricResultFunc is a function that returns a metric result type MetricResultFunc func() (metricResult MetricResult, threshold float64) +type MetricResultMap map[MetricName]MetricResult + +func NewMetricResultMap() MetricResultMap { + result := make(MetricResultMap, len(KnownMetricNames)) + for _, metricName := range KnownMetricNames { + result[metricName] = nil + } + return result +} + // ErrThresholdExceeded is the common error one may get checking on metric result -var ErrThresholdExceeded = errors.New("Threshold exceeded") -var errNoResultYet = errors.New("Metric not collected yet") +var ErrThresholdExceeded = errors.New("threshold exceeded") +var ErrNoResultYet = errors.New("metric not collected yet") // ErrNoSuchMetric is for when a user requests a metric by an unknown metric name -var ErrNoSuchMetric = errors.New("No such metric") +var ErrNoSuchMetric = errors.New("no such metric") // ErrInvalidCheckType is an internal error indicating an unknown check type -var ErrInvalidCheckType = errors.New("Unknown throttler check type") +var ErrInvalidCheckType = errors.New("unknown throttler check type") // IsDialTCPError sees if the given error indicates a TCP issue func IsDialTCPError(e error) bool { @@ -87,7 +228,7 @@ type noMetricResultYet struct{} // Get implements MetricResult func (metricResult *noMetricResultYet) Get() (float64, error) { - return 0, errNoResultYet + return 0, ErrNoResultYet } // NoMetricResultYet is a result indicating "no data" diff --git a/go/vt/vttablet/tabletserver/throttle/mysql/mysql_throttle_metric.go b/go/vt/vttablet/tabletserver/throttle/base/throttle_metric_cache.go similarity index 59% rename from go/vt/vttablet/tabletserver/throttle/mysql/mysql_throttle_metric.go rename to go/vt/vttablet/tabletserver/throttle/base/throttle_metric_cache.go index 966c7a93d7f..8695cb83229 100644 --- a/go/vt/vttablet/tabletserver/throttle/mysql/mysql_throttle_metric.go +++ b/go/vt/vttablet/tabletserver/throttle/base/throttle_metric_cache.go @@ -39,10 +39,10 @@ limitations under the License. SOFTWARE. */ -package mysql +package base import ( - "fmt" + "context" "strings" "time" @@ -65,29 +65,31 @@ const ( MetricsQueryTypeUnknown ) -var mysqlMetricCache = cache.New(cache.NoExpiration, 10*time.Second) +var metricCache = cache.New(cache.NoExpiration, 10*time.Second) -func getMySQLMetricCacheKey(probe *Probe) string { - return fmt.Sprintf("%s:%s", probe.Alias, probe.MetricQuery) +func getMetricCacheKey(probe *Probe) string { + return probe.Alias } -func cacheMySQLThrottleMetric(probe *Probe, mySQLThrottleMetric *MySQLThrottleMetric) *MySQLThrottleMetric { - if mySQLThrottleMetric.Err != nil { - return mySQLThrottleMetric +func cacheThrottleMetric(probe *Probe, throttleMetrics ThrottleMetrics) ThrottleMetrics { + for _, metric := range throttleMetrics { + if metric.Err != nil { + return throttleMetrics + } } if probe.CacheMillis > 0 { - mysqlMetricCache.Set(getMySQLMetricCacheKey(probe), mySQLThrottleMetric, time.Duration(probe.CacheMillis)*time.Millisecond) + metricCache.Set(getMetricCacheKey(probe), throttleMetrics, time.Duration(probe.CacheMillis)*time.Millisecond) } - return mySQLThrottleMetric + return throttleMetrics } -func getCachedMySQLThrottleMetric(probe *Probe) *MySQLThrottleMetric { +func getCachedThrottleMetrics(probe *Probe) ThrottleMetrics { if probe.CacheMillis == 0 { return nil } - if metric, found := mysqlMetricCache.Get(getMySQLMetricCacheKey(probe)); found { - mySQLThrottleMetric, _ := metric.(*MySQLThrottleMetric) - return mySQLThrottleMetric + if metrics, found := metricCache.Get(getMetricCacheKey(probe)); found { + throttleMetrics, _ := metrics.(ThrottleMetrics) + return throttleMetrics } return nil } @@ -106,52 +108,58 @@ func GetMetricsQueryType(query string) MetricsQueryType { return MetricsQueryTypeUnknown } -// MySQLThrottleMetric has the probed metric for a tablet -type MySQLThrottleMetric struct { // nolint:revive - ClusterName string - Alias string - Value float64 - Err error +// ThrottleMetric has the probed metric for a tablet +type ThrottleMetric struct { // nolint:revive + Name MetricName + Scope Scope + Alias string + Value float64 + Err error } -// NewMySQLThrottleMetric creates a new MySQLThrottleMetric -func NewMySQLThrottleMetric() *MySQLThrottleMetric { - return &MySQLThrottleMetric{Value: 0} +type ThrottleMetrics map[MetricName]*ThrottleMetric // nolint:revive + +// NewThrottleMetric creates a new ThrottleMetric +func NewThrottleMetric() *ThrottleMetric { + return &ThrottleMetric{Value: 0} } // GetClusterTablet returns the ClusterTablet part of the metric -func (metric *MySQLThrottleMetric) GetClusterTablet() ClusterTablet { - return GetClusterTablet(metric.ClusterName, metric.Alias) +func (metric *ThrottleMetric) GetTabletAlias() string { + return metric.Alias } // Get implements MetricResult -func (metric *MySQLThrottleMetric) Get() (float64, error) { +func (metric *ThrottleMetric) Get() (float64, error) { return metric.Value, metric.Err } -// ReadThrottleMetric returns a metric for the given probe. Either by explicit query +// WithError returns this metric with given error +func (metric *ThrottleMetric) WithError(err error) *ThrottleMetric { + metric.Err = err + return metric +} + +// ReadThrottleMetrics returns a metric for the given probe. Either by explicit query // or via SHOW REPLICA STATUS -func ReadThrottleMetric(probe *Probe, clusterName string, overrideGetMetricFunc func() *MySQLThrottleMetric) (mySQLThrottleMetric *MySQLThrottleMetric) { - if mySQLThrottleMetric := getCachedMySQLThrottleMetric(probe); mySQLThrottleMetric != nil { - return mySQLThrottleMetric - // On cached results we avoid taking latency metrics +func ReadThrottleMetrics(ctx context.Context, probe *Probe, metricsFunc func(context.Context) ThrottleMetrics) ThrottleMetrics { + if metrics := getCachedThrottleMetrics(probe); metrics != nil { + return metrics } started := time.Now() - mySQLThrottleMetric = NewMySQLThrottleMetric() - mySQLThrottleMetric.ClusterName = clusterName - mySQLThrottleMetric.Alias = probe.Alias - - defer func(metric *MySQLThrottleMetric, started time.Time) { - go func() { - stats.GetOrNewGauge("ThrottlerProbesLatency", "probes latency").Set(time.Since(started).Nanoseconds()) - stats.GetOrNewCounter("ThrottlerProbesTotal", "total probes").Add(1) + throttleMetrics := metricsFunc(ctx) + + go func(metrics ThrottleMetrics, started time.Time) { + stats.GetOrNewGauge("ThrottlerProbesLatency", "probes latency").Set(time.Since(started).Nanoseconds()) + stats.GetOrNewCounter("ThrottlerProbesTotal", "total probes").Add(1) + for _, metric := range metrics { if metric.Err != nil { stats.GetOrNewCounter("ThrottlerProbesError", "total probes errors").Add(1) + break } - }() - }(mySQLThrottleMetric, started) + } + }(throttleMetrics, started) - mySQLThrottleMetric = overrideGetMetricFunc() - return cacheMySQLThrottleMetric(probe, mySQLThrottleMetric) + return cacheThrottleMetric(probe, throttleMetrics) } diff --git a/go/vt/vttablet/tabletserver/throttle/base/throttle_metric_test.go b/go/vt/vttablet/tabletserver/throttle/base/throttle_metric_test.go new file mode 100644 index 00000000000..8a0f9b85a16 --- /dev/null +++ b/go/vt/vttablet/tabletserver/throttle/base/throttle_metric_test.go @@ -0,0 +1,232 @@ +/* +Copyright 2024 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 base + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAggregateName(t *testing.T) { + tcases := []struct { + aggregatedName string + scope Scope + metricName MetricName + expectErr string + }{ + { + aggregatedName: "", + expectErr: ErrNoSuchMetric.Error(), + }, + { + aggregatedName: "self", + scope: SelfScope, + metricName: DefaultMetricName, + }, + { + aggregatedName: "shard", + scope: ShardScope, + metricName: DefaultMetricName, + }, + { + aggregatedName: "self/default", + expectErr: ErrNoSuchMetric.Error(), + }, + { + aggregatedName: "lag", + scope: ShardScope, + metricName: LagMetricName, + }, + { + aggregatedName: "loadavg", + scope: SelfScope, + metricName: LoadAvgMetricName, + }, + { + aggregatedName: "lag2", + expectErr: ErrNoSuchMetric.Error(), + }, + { + aggregatedName: "self/lag", + scope: SelfScope, + metricName: LagMetricName, + }, + { + aggregatedName: "shard/lag", + scope: ShardScope, + metricName: LagMetricName, + }, + { + aggregatedName: "shard/lag3", + expectErr: ErrNoSuchMetric.Error(), + }, + { + aggregatedName: "shard/lag/zone1-01", + expectErr: ErrNoSuchMetric.Error(), + }, + { + aggregatedName: "shard/loadavg", + scope: ShardScope, + metricName: LoadAvgMetricName, + }, + } + assert.Equal(t, 3*len(KnownMetricNames), len(aggregatedMetricNames)) + for _, tcase := range tcases { + t.Run(tcase.aggregatedName, func(t *testing.T) { + scope, metricName, err := DisaggregateMetricName(tcase.aggregatedName) + { + scope2, metricName2, err2 := MetricName(tcase.aggregatedName).Disaggregated() + assert.Equal(t, scope, scope2) + assert.Equal(t, metricName, metricName2) + assert.Equal(t, err, err2) + } + if tcase.expectErr != "" { + assert.ErrorContains(t, err, tcase.expectErr) + return + } + assert.NoError(t, err) + assert.NotEqual(t, UndefinedScope, scope) + assert.Equal(t, tcase.scope, scope) + assert.Equal(t, tcase.metricName, metricName) + + if strings.Contains(tcase.aggregatedName, "/") && tcase.metricName != DefaultMetricName { + // Run the reverse. + // Remember that for backwards compatibility, we do not add "default" to the aggregated name, + // and we therefore skip tests that would fail because of this. + aggregatedName := metricName.AggregatedName(scope) + assert.Equal(t, tcase.aggregatedName, aggregatedName) + } + }) + } +} + +func TestScopeFromString(t *testing.T) { + { + scope, err := ScopeFromString("") + assert.NoError(t, err) + assert.Equal(t, UndefinedScope, scope) + } + { + scope, err := ScopeFromString("self") + assert.NoError(t, err) + assert.Equal(t, SelfScope, scope) + } + { + scope, err := ScopeFromString("shard") + assert.NoError(t, err) + assert.Equal(t, ShardScope, scope) + } + { + _, err := ScopeFromString("something") + assert.ErrorContains(t, err, "unknown scope") + } + { + _, err := ScopeFromString("self/lag") + assert.ErrorContains(t, err, "unknown scope") + } +} + +func TestUnique(t *testing.T) { + tcases := []struct { + names MetricNames + expect MetricNames + }{ + { + names: nil, + expect: nil, + }, + { + names: MetricNames{}, + expect: MetricNames{}, + }, + { + names: MetricNames{LagMetricName}, + expect: MetricNames{LagMetricName}, + }, + { + names: MetricNames{LagMetricName, LagMetricName}, + expect: MetricNames{LagMetricName}, + }, + { + names: MetricNames{LagMetricName, ThreadsRunningMetricName, LagMetricName}, + expect: MetricNames{LagMetricName, ThreadsRunningMetricName}, + }, + { + names: MetricNames{LagMetricName, ThreadsRunningMetricName, LagMetricName, LoadAvgMetricName, LoadAvgMetricName, CustomMetricName}, + expect: MetricNames{LagMetricName, ThreadsRunningMetricName, LoadAvgMetricName, CustomMetricName}, + }, + } + for _, tcase := range tcases { + t.Run(tcase.names.String(), func(t *testing.T) { + assert.Equal(t, tcase.expect, tcase.names.Unique()) + }) + } +} + +func TestContains(t *testing.T) { + tcases := []struct { + names MetricNames + name MetricName + expect bool + }{ + { + names: nil, + name: LagMetricName, + }, + { + names: MetricNames{}, + name: LagMetricName, + }, + { + names: MetricNames{LagMetricName}, + name: LagMetricName, + expect: true, + }, + { + names: MetricNames{LagMetricName}, + name: ThreadsRunningMetricName, + expect: false, + }, + { + names: MetricNames{LagMetricName, LagMetricName}, + name: LagMetricName, + expect: true, + }, + { + names: MetricNames{LagMetricName, ThreadsRunningMetricName, LagMetricName}, + name: LagMetricName, + expect: true, + }, + { + names: MetricNames{LagMetricName, ThreadsRunningMetricName, LagMetricName, LoadAvgMetricName, LoadAvgMetricName, CustomMetricName}, + name: LoadAvgMetricName, + expect: true, + }, + { + names: MetricNames{LagMetricName, ThreadsRunningMetricName, LagMetricName, LoadAvgMetricName, LoadAvgMetricName}, + name: CustomMetricName, + expect: false, + }, + } + for _, tcase := range tcases { + t.Run(tcase.names.String(), func(t *testing.T) { + assert.Equal(t, tcase.expect, tcase.names.Contains(tcase.name)) + }) + } +} diff --git a/go/vt/vttablet/tabletserver/throttle/check.go b/go/vt/vttablet/tabletserver/throttle/check.go index c15d8963d05..e43c4cab043 100644 --- a/go/vt/vttablet/tabletserver/throttle/check.go +++ b/go/vt/vttablet/tabletserver/throttle/check.go @@ -45,7 +45,6 @@ import ( "context" "fmt" "net/http" - "strings" "time" "vitess.io/vitess/go/stats" @@ -65,14 +64,18 @@ var ( // CheckFlags provide hints for a check type CheckFlags struct { + Scope base.Scope ReadCheck bool OverrideThreshold float64 OKIfNotExists bool SkipRequestHeartbeats bool + MultiMetricsEnabled bool } -// StandardCheckFlags have no special hints -var StandardCheckFlags = &CheckFlags{} +// selfCheckFlags have no special hints +var selfCheckFlags = &CheckFlags{ + MultiMetricsEnabled: true, +} // ThrottlerCheck provides methods for an app checking on metrics type ThrottlerCheck struct { @@ -87,7 +90,7 @@ func NewThrottlerCheck(throttler *Throttler) *ThrottlerCheck { } // checkAppMetricResult allows an app to check on a metric -func (check *ThrottlerCheck) checkAppMetricResult(ctx context.Context, appName string, storeType string, storeName string, metricResultFunc base.MetricResultFunc, flags *CheckFlags) (checkResult *CheckResult) { +func (check *ThrottlerCheck) checkAppMetricResult(ctx context.Context, appName string, metricResultFunc base.MetricResultFunc, flags *CheckFlags) (checkResult *CheckResult) { // Handle deprioritized app logic denyApp := false // @@ -124,72 +127,125 @@ func (check *ThrottlerCheck) checkAppMetricResult(ctx context.Context, appName s } // Check is the core function that runs when a user wants to check a metric -func (check *ThrottlerCheck) Check(ctx context.Context, appName string, storeType string, storeName string, remoteAddr string, flags *CheckFlags) (checkResult *CheckResult) { - var metricResultFunc base.MetricResultFunc - switch storeType { - case "mysql": - { - metricResultFunc = func() (metricResult base.MetricResult, threshold float64) { - return check.throttler.getMySQLClusterMetrics(ctx, storeName) - } - } +func (check *ThrottlerCheck) Check(ctx context.Context, appName string, scope base.Scope, metricNames base.MetricNames, flags *CheckFlags) (checkResult *CheckResult) { + checkResult = &CheckResult{ + StatusCode: http.StatusOK, + Metrics: make(map[string]*MetricResult), } - if metricResultFunc == nil { - return NoSuchMetricCheckResult + if len(metricNames) == 0 { + metricNames = base.MetricNames{check.throttler.metricNameUsedAsDefault()} + } + metricNames = metricNames.Unique() + applyMetricToCheckResult := func(metric *MetricResult) { + checkResult.StatusCode = metric.StatusCode + checkResult.Value = metric.Value + checkResult.Threshold = metric.Threshold + checkResult.Error = metric.Error + checkResult.Message = metric.Message } + for _, metricName := range metricNames { + // Make sure not to modify the given scope. We create a new scope variable to work with. + metricScope := scope + // It's possible that the metric name looks like "shard/loadavg". This means the the check is meant to + // check the "loadavg" metric for the "shard" scope (while normally "loadavg" is a "self" scope metric). + // So we first need to find out what the underlying metric name is ("loadavg" in this case), and then + // see whether we need to change the scope. + // It's also possible that the metric name is just "loadavg", in which case we extract the default + // scope for this metric. + // If given scope is defined, then it overrides any metric scope. + // Noteworthy that self checks will always have a defined scope, because those are based on aggregated metrics. + if disaggregatedScope, disaggregatedName, err := metricName.Disaggregated(); err == nil { + if metricScope == base.UndefinedScope { + // Client has not indicated any specific scope, so we use the disaggregated scope + metricScope = disaggregatedScope + } + metricName = disaggregatedName + } - checkResult = check.checkAppMetricResult(ctx, appName, storeType, storeName, metricResultFunc, flags) - check.throttler.markRecentApp(appName, remoteAddr) - if !throttlerapp.VitessName.Equals(appName) { - go func(statusCode int) { - statsThrottlerCheckAnyTotal.Add(1) - stats.GetOrNewCounter(fmt.Sprintf("ThrottlerCheckAny%s%sTotal", textutil.SingleWordCamel(storeType), textutil.SingleWordCamel(storeName)), "").Add(1) + metricResultFunc := func() (metricResult base.MetricResult, threshold float64) { + return check.throttler.getScopedMetric(metricScope, metricName) + } - if statusCode != http.StatusOK { - statsThrottlerCheckAnyError.Add(1) - stats.GetOrNewCounter(fmt.Sprintf("ThrottlerCheckAny%s%sError", textutil.SingleWordCamel(storeType), textutil.SingleWordCamel(storeName)), "").Add(1) - } - }(checkResult.StatusCode) + metricCheckResult := check.checkAppMetricResult(ctx, appName, metricResultFunc, flags) + if !throttlerapp.VitessName.Equals(appName) { + go func(statusCode int) { + if metricScope == base.UndefinedScope { + // While we should never get here, the following code will panic if we do + // because it will attempt to recreate ThrottlerCheckAnyTotal. + // Out of abundance of caution, we will protect against such a scenario. + return + } + stats.GetOrNewCounter(fmt.Sprintf("ThrottlerCheck%s%sTotal", textutil.SingleWordCamel(metricScope.String()), textutil.SingleWordCamel(metricName.String())), "").Add(1) + if statusCode != http.StatusOK { + stats.GetOrNewCounter(fmt.Sprintf("ThrottlerCheck%s%sError", textutil.SingleWordCamel(metricScope.String()), textutil.SingleWordCamel(metricName.String())), "").Add(1) + } + }(metricCheckResult.StatusCode) + } + if metricCheckResult.RecentlyChecked { + checkResult.RecentlyChecked = true + } + metric := &MetricResult{ + StatusCode: metricCheckResult.StatusCode, + Value: metricCheckResult.Value, + Threshold: metricCheckResult.Threshold, + Error: metricCheckResult.Error, + Message: metricCheckResult.Message, + Scope: metricScope.String(), // This reports back the actual scope used for the check + } + checkResult.Metrics[metricName.String()] = metric + if flags.MultiMetricsEnabled && !metricCheckResult.IsOK() && metricName != base.DefaultMetricName { + // If we're checking multiple metrics, and one of them fails, we should return any of the failing metric. + // For backwards compatibility, if flags.MultiMetricsEnabled is not set, we do not report back failing + // metrics, because a v20 primary would not know how to deal with it, and is not expecting any of those + // metrics. + // The only metric we ever report back is the default metric, see below. + applyMetricToCheckResult(metric) + } } - return checkResult -} - -func (check *ThrottlerCheck) splitMetricTokens(metricName string) (storeType string, storeName string, err error) { - metricTokens := strings.Split(metricName, "/") - if len(metricTokens) != 2 { - return storeType, storeName, base.ErrNoSuchMetric + if metric, ok := checkResult.Metrics[check.throttler.metricNameUsedAsDefault().String()]; ok && checkResult.IsOK() { + applyMetricToCheckResult(metric) } - storeType = metricTokens[0] - storeName = metricTokens[1] - - return storeType, storeName, nil + if metric, ok := checkResult.Metrics[base.DefaultMetricName.String()]; ok && checkResult.IsOK() { + // v20 compatibility: if this v21 server is a replica, reporting to a v20 primary, + // then we must supply the v20-flavor check result. + // If checkResult is not OK, then we will have populated these fields already by the failing metric. + applyMetricToCheckResult(metric) + } + go func(statusCode int) { + statsThrottlerCheckAnyTotal.Add(1) + if statusCode != http.StatusOK { + statsThrottlerCheckAnyError.Add(1) + } + }(checkResult.StatusCode) + go check.throttler.markRecentApp(appName, checkResult.StatusCode) + return checkResult } // localCheck -func (check *ThrottlerCheck) localCheck(ctx context.Context, metricName string) (checkResult *CheckResult) { - storeType, storeName, err := check.splitMetricTokens(metricName) +func (check *ThrottlerCheck) localCheck(ctx context.Context, aggregatedMetricName string) (checkResult *CheckResult) { + scope, metricName, err := base.DisaggregateMetricName(aggregatedMetricName) if err != nil { return NoSuchMetricCheckResult } - checkResult = check.Check(ctx, throttlerapp.VitessName.String(), storeType, storeName, "local", StandardCheckFlags) + checkResult = check.Check(ctx, throttlerapp.VitessName.String(), scope, base.MetricNames{metricName}, selfCheckFlags) if checkResult.StatusCode == http.StatusOK { - check.throttler.markMetricHealthy(metricName) + check.throttler.markMetricHealthy(aggregatedMetricName) } - if timeSinceHealthy, found := check.throttler.timeSinceMetricHealthy(metricName); found { - stats.GetOrNewGauge(fmt.Sprintf("ThrottlerCheck%s%sSecondsSinceHealthy", textutil.SingleWordCamel(storeType), textutil.SingleWordCamel(storeName)), fmt.Sprintf("seconds since last healthy cehck for %s.%s", storeType, storeName)).Set(int64(timeSinceHealthy.Seconds())) + if timeSinceHealthy, found := check.throttler.timeSinceMetricHealthy(aggregatedMetricName); found { + go stats.GetOrNewGauge(fmt.Sprintf("ThrottlerCheck%sSecondsSinceHealthy", textutil.SingleWordCamel(scope.String())), fmt.Sprintf("seconds since last healthy check for %v", scope)).Set(int64(timeSinceHealthy.Seconds())) } return checkResult } -func (check *ThrottlerCheck) reportAggregated(metricName string, metricResult base.MetricResult) { - storeType, storeName, err := check.splitMetricTokens(metricName) +func (check *ThrottlerCheck) reportAggregated(aggregatedMetricName string, metricResult base.MetricResult) { + scope, metricName, err := base.DisaggregateMetricName(aggregatedMetricName) if err != nil { return } if value, err := metricResult.Get(); err == nil { - stats.GetOrNewGaugeFloat64(fmt.Sprintf("ThrottlerAggregated%s%s", textutil.SingleWordCamel(storeType), textutil.SingleWordCamel(storeName)), fmt.Sprintf("aggregated value for %s.%s", storeType, storeName)).Set(value) + stats.GetOrNewGaugeFloat64(fmt.Sprintf("ThrottlerAggregated%s%s", textutil.SingleWordCamel(scope.String()), textutil.SingleWordCamel(metricName.String())), fmt.Sprintf("aggregated value for %v", scope)).Set(value) } } @@ -198,11 +254,6 @@ func (check *ThrottlerCheck) AggregatedMetrics(ctx context.Context) map[string]b return check.throttler.aggregatedMetricsSnapshot() } -// MetricsHealth is a convenience access method into throttler's `metricsHealthSnapshot` -func (check *ThrottlerCheck) MetricsHealth() map[string](*base.MetricHealth) { - return check.throttler.metricsHealthSnapshot() -} - // SelfChecks runs checks on all known metrics as if we were an app. // This runs asynchronously, continuously, and independently of any user interaction func (check *ThrottlerCheck) SelfChecks(ctx context.Context) { @@ -214,11 +265,11 @@ func (check *ThrottlerCheck) SelfChecks(ctx context.Context) { return case <-selfCheckTicker.C: for metricName, metricResult := range check.AggregatedMetrics(ctx) { - metricName := metricName + aggregatedMetricName := metricName metricResult := metricResult - go check.localCheck(ctx, metricName) - go check.reportAggregated(metricName, metricResult) + go check.localCheck(ctx, aggregatedMetricName) + go check.reportAggregated(aggregatedMetricName, metricResult) } } } diff --git a/go/vt/vttablet/tabletserver/throttle/check_result.go b/go/vt/vttablet/tabletserver/throttle/check_result.go index 41a1b240934..3c8852e4042 100644 --- a/go/vt/vttablet/tabletserver/throttle/check_result.go +++ b/go/vt/vttablet/tabletserver/throttle/check_result.go @@ -47,14 +47,24 @@ import ( "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base" ) +type MetricResult struct { + StatusCode int `json:"StatusCode"` + Scope string `json:"Scope"` + Value float64 `json:"Value"` + Threshold float64 `json:"Threshold"` + Error error `json:"-"` + Message string `json:"Message"` +} + // CheckResult is the result for an app inquiring on a metric. It also exports as JSON via the API type CheckResult struct { - StatusCode int `json:"StatusCode"` - Value float64 `json:"Value"` - Threshold float64 `json:"Threshold"` - Error error `json:"-"` - Message string `json:"Message"` - RecentlyChecked bool `json:"RecentlyChecked"` + StatusCode int `json:"StatusCode"` + Value float64 `json:"Value"` + Threshold float64 `json:"Threshold"` + Error error `json:"-"` + Message string `json:"Message"` + RecentlyChecked bool `json:"RecentlyChecked"` + Metrics map[string]*MetricResult `json:"Metrics"` // New in multi-metrics support. Will eventually replace the above fields. } // NewCheckResult returns a CheckResult @@ -71,6 +81,10 @@ func NewCheckResult(statusCode int, value float64, threshold float64, err error) return result } +func (c *CheckResult) IsOK() bool { + return c.StatusCode == http.StatusOK +} + // NewErrorCheckResult returns a check result that indicates an error func NewErrorCheckResult(statusCode int, err error) *CheckResult { return NewCheckResult(statusCode, 0, 0, err) diff --git a/go/vt/vttablet/tabletserver/throttle/client.go b/go/vt/vttablet/tabletserver/throttle/client.go index 5194ba19f98..e8eed627e04 100644 --- a/go/vt/vttablet/tabletserver/throttle/client.go +++ b/go/vt/vttablet/tabletserver/throttle/client.go @@ -23,6 +23,7 @@ import ( "sync/atomic" "time" + "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/throttlerapp" ) @@ -35,6 +36,7 @@ var throttleInit sync.Once func initThrottleTicker() { throttleInit.Do(func() { + throttleTicks = 1 // above zero so that `lastSuccessfulThrottle` is initially stale go func() { tick := time.NewTicker(throttleCheckDuration) defer tick.Stop() @@ -49,24 +51,37 @@ func initThrottleTicker() { type Client struct { throttler *Throttler appName throttlerapp.Name - checkType ThrottleCheckType flags CheckFlags lastSuccessfulThrottleMu sync.Mutex - lastSuccessfulThrottle int64 + // lastSuccessfulThrottle records the latest tick (value of `throttleTicks`) when the throttler was + // satisfied for a given metric. This makes it possible to potentially skip a throttler check. + // key is the app name. + lastSuccessfulThrottle map[string]int64 } -// NewBackgroundClient creates a client -func NewBackgroundClient(throttler *Throttler, appName throttlerapp.Name, checkType ThrottleCheckType) *Client { +// NewBackgroundClient creates a client suitable for background jobs, which have low priority over production traffic, +// e.g. migration, table pruning, vreplication +func NewBackgroundClient(throttler *Throttler, appName throttlerapp.Name, scope base.Scope) *Client { initThrottleTicker() return &Client{ throttler: throttler, appName: appName, - checkType: checkType, - flags: CheckFlags{}, + flags: CheckFlags{ + Scope: scope, + MultiMetricsEnabled: true, + }, + lastSuccessfulThrottle: make(map[string]int64), } } +// clearSuccessfulResultsCache clears lastSuccessfulThrottleMu, so that the next check will be fresh. +func (c *Client) clearSuccessfulResultsCache() { + c.lastSuccessfulThrottleMu.Lock() + defer c.lastSuccessfulThrottleMu.Unlock() + c.lastSuccessfulThrottle = make(map[string]int64) +} + // ThrottleCheckOK checks the throttler, and returns 'true' when the throttler is satisfied. // It does not sleep. // The function caches results for a brief amount of time, hence it's safe and efficient to @@ -81,22 +96,27 @@ func (c *Client) ThrottleCheckOK(ctx context.Context, overrideAppName throttlera // no throttler return true } + checkApp := c.appName + if overrideAppName != "" { + checkApp = overrideAppName + } c.lastSuccessfulThrottleMu.Lock() defer c.lastSuccessfulThrottleMu.Unlock() - if c.lastSuccessfulThrottle >= atomic.LoadInt64(&throttleTicks) { + if c.lastSuccessfulThrottle[checkApp.String()] >= atomic.LoadInt64(&throttleTicks) { // if last check was OK just very recently there is no need to check again return true } // It's time to run a throttler check - checkApp := c.appName - if overrideAppName != "" { - checkApp = overrideAppName - } - checkResult := c.throttler.CheckByType(ctx, checkApp.String(), "", &c.flags, c.checkType) + checkResult := c.throttler.Check(ctx, checkApp.String(), nil, &c.flags) if checkResult.StatusCode != http.StatusOK { return false } - c.lastSuccessfulThrottle = atomic.LoadInt64(&throttleTicks) + for _, metricResult := range checkResult.Metrics { + if metricResult.StatusCode != http.StatusOK { + return false + } + } + c.lastSuccessfulThrottle[checkApp.String()] = atomic.LoadInt64(&throttleTicks) return true } @@ -106,11 +126,15 @@ func (c *Client) ThrottleCheckOK(ctx context.Context, overrideAppName throttlera // Non-empty appName overrides the default appName. // The function is not thread safe. func (c *Client) ThrottleCheckOKOrWaitAppName(ctx context.Context, appName throttlerapp.Name) bool { - ok := c.ThrottleCheckOK(ctx, appName) - if !ok { - time.Sleep(throttleCheckDuration) + if c.ThrottleCheckOK(ctx, appName) { + return true } - return ok + if ctx.Err() != nil { + // context expired, skip sleeping + return false + } + time.Sleep(throttleCheckDuration) + return false } // ThrottleCheckOKOrWait checks the throttler; if throttler is satisfied, the function returns 'true' immediately, @@ -124,12 +148,7 @@ func (c *Client) ThrottleCheckOKOrWait(ctx context.Context) bool { // The function sleeps between throttle checks. // The function is not thread safe. func (c *Client) Throttle(ctx context.Context) { - for { - if ctx.Err() != nil { - return - } - if c.ThrottleCheckOKOrWait(ctx) { - return - } + for !c.ThrottleCheckOKOrWait(ctx) { + // The function incorporates a bit of sleep so this is not a busy wait. } } diff --git a/go/vt/vttablet/tabletserver/throttle/config/config.go b/go/vt/vttablet/tabletserver/throttle/config/config.go index f6234955cc4..26311bc5981 100644 --- a/go/vt/vttablet/tabletserver/throttle/config/config.go +++ b/go/vt/vttablet/tabletserver/throttle/config/config.go @@ -41,11 +41,6 @@ limitations under the License. package config -// NewConfigurationSettings creates new throttler configuration settings. -func NewConfigurationSettings() *ConfigurationSettings { - return &ConfigurationSettings{} -} - // ConfigurationSettings models a set of configurable values, that can be // provided by the user via one or several JSON formatted files. // @@ -57,5 +52,10 @@ type ConfigurationSettings struct { Environment string Domain string EnableProfiling bool // enable pprof profiling http api - Stores StoresSettings + MySQLStore MySQLConfigurationSettings +} + +// NewConfigurationSettings creates new throttler configuration settings. +func NewConfigurationSettings() *ConfigurationSettings { + return &ConfigurationSettings{} } diff --git a/go/vt/vttablet/tabletserver/throttle/config/mysql_config.go b/go/vt/vttablet/tabletserver/throttle/config/mysql_config.go index 3aa0607fb28..d4beb40deb4 100644 --- a/go/vt/vttablet/tabletserver/throttle/config/mysql_config.go +++ b/go/vt/vttablet/tabletserver/throttle/config/mysql_config.go @@ -43,31 +43,23 @@ package config import ( "sync/atomic" + + "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base" ) // // MySQL-specific configuration // -// MySQLClusterConfigurationSettings has the settings for a specific MySQL cluster. It derives its information -// from MySQLConfigurationSettings -type MySQLClusterConfigurationSettings struct { - MetricQuery string // override MySQLConfigurationSettings's, or leave empty to inherit those settings - CacheMillis int // override MySQLConfigurationSettings's, or leave empty to inherit those settings - ThrottleThreshold *atomic.Uint64 // override MySQLConfigurationSettings's, or leave empty to inherit those settings - Port int // Specify if different than 3306 or if different than specified by MySQLConfigurationSettings - IgnoreHostsCount int // Number of hosts that can be skipped/ignored even on error or on exceeding thresholds - IgnoreHostsThreshold float64 // Threshold beyond which IgnoreHostsCount applies (default: 0) - HTTPCheckPort int // Specify if different than specified by MySQLConfigurationSettings. -1 to disable HTTP check - HTTPCheckPath string // Specify if different than specified by MySQLConfigurationSettings - IgnoreHosts []string // override MySQLConfigurationSettings's, or leave empty to inherit those settings +type MySQLMetricConfigurationSettings struct { + Name base.MetricName + CustomQuery string + Threshold atomic.Uint64 } // MySQLConfigurationSettings has the general configuration for all MySQL clusters type MySQLConfigurationSettings struct { - MetricQuery string - CacheMillis int // optional, if defined then probe result will be cached, and future probes may use cached value - ThrottleThreshold *atomic.Uint64 + CacheMillis int // optional, if defined then probe result will be cached, and future probes may use cached value Port int // Specify if different than 3306; applies to all clusters IgnoreDialTCPErrors bool // Skip hosts where a metric cannot be retrieved due to TCP dial errors IgnoreHostsCount int // Number of hosts that can be skipped/ignored even on error or on exceeding thresholds @@ -76,5 +68,5 @@ type MySQLConfigurationSettings struct { HTTPCheckPath string // If non-empty, requires HTTPCheckPort IgnoreHosts []string // If non empty, substrings to indicate hosts to be ignored/skipped - Clusters map[string](*MySQLClusterConfigurationSettings) // cluster name -> cluster config + Metrics map[base.MetricName]*MySQLMetricConfigurationSettings } diff --git a/go/vt/vttablet/tabletserver/throttle/mysql/mysql_inventory.go b/go/vt/vttablet/tabletserver/throttle/mysql/mysql_inventory.go deleted file mode 100644 index 744bcc99a44..00000000000 --- a/go/vt/vttablet/tabletserver/throttle/mysql/mysql_inventory.go +++ /dev/null @@ -1,79 +0,0 @@ -/* -Copyright 2023 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. -*/ - -// This codebase originates from https://github.com/github/freno, See https://github.com/github/freno/blob/master/LICENSE -/* - MIT License - - Copyright (c) 2017 GitHub - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ - -package mysql - -import ( - "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base" -) - -// ClusterTablet combines a cluster name with a tablet alias -type ClusterTablet struct { - ClusterName string - Alias string -} - -// GetClusterTablet creates a GetClusterTablet object -func GetClusterTablet(clusterName string, alias string) ClusterTablet { - return ClusterTablet{ClusterName: clusterName, Alias: alias} -} - -// TabletResultMap maps a cluster-tablet to a result -type TabletResultMap map[ClusterTablet]base.MetricResult - -// Inventory has the operational data about probes, their metrics, and relevant configuration -type Inventory struct { - ClustersProbes map[string](Probes) - IgnoreHostsCount map[string]int - IgnoreHostsThreshold map[string]float64 - TabletMetrics TabletResultMap -} - -// NewInventory creates a Inventory -func NewInventory() *Inventory { - inventory := &Inventory{ - ClustersProbes: make(map[string](Probes)), - IgnoreHostsCount: make(map[string]int), - IgnoreHostsThreshold: make(map[string]float64), - TabletMetrics: make(map[ClusterTablet]base.MetricResult), - } - return inventory -} diff --git a/go/vt/vttablet/tabletserver/throttle/mysql_test.go b/go/vt/vttablet/tabletserver/throttle/mysql_test.go deleted file mode 100644 index 15d6feab03f..00000000000 --- a/go/vt/vttablet/tabletserver/throttle/mysql_test.go +++ /dev/null @@ -1,233 +0,0 @@ -/* -Copyright 2023 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. -*/ - -// This codebase originates from https://github.com/github/freno, See https://github.com/github/freno/blob/master/LICENSE -/* - MIT License - - Copyright (c) 2017 GitHub - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ - -package throttle - -import ( - "context" - "testing" - - "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base" - "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/mysql" - - "github.com/stretchr/testify/assert" -) - -var ( - alias1 = "zone1-0001" - alias2 = "zone1-0002" - alias3 = "zone1-0003" - alias4 = "zone1-0004" - alias5 = "zone1-0005" -) - -func TestAggregateMySQLProbesNoErrors(t *testing.T) { - ctx := context.Background() - clusterName := "c0" - key1cluster := mysql.GetClusterTablet(clusterName, alias1) - key2cluster := mysql.GetClusterTablet(clusterName, alias2) - key3cluster := mysql.GetClusterTablet(clusterName, alias3) - key4cluster := mysql.GetClusterTablet(clusterName, alias4) - key5cluster := mysql.GetClusterTablet(clusterName, alias5) - tabletResultsMap := mysql.TabletResultMap{ - key1cluster: base.NewSimpleMetricResult(1.2), - key2cluster: base.NewSimpleMetricResult(1.7), - key3cluster: base.NewSimpleMetricResult(0.3), - key4cluster: base.NewSimpleMetricResult(0.6), - key5cluster: base.NewSimpleMetricResult(1.1), - } - var probes mysql.Probes = map[string](*mysql.Probe){} - for clusterKey := range tabletResultsMap { - probes[clusterKey.Alias] = &mysql.Probe{Alias: clusterKey.Alias} - } - { - worstMetric := aggregateMySQLProbes(ctx, probes, clusterName, tabletResultsMap, 0, false, 0) - value, err := worstMetric.Get() - assert.NoError(t, err) - assert.Equal(t, value, 1.7) - } - { - worstMetric := aggregateMySQLProbes(ctx, probes, clusterName, tabletResultsMap, 1, false, 0) - value, err := worstMetric.Get() - assert.NoError(t, err) - assert.Equal(t, value, 1.2) - } - { - worstMetric := aggregateMySQLProbes(ctx, probes, clusterName, tabletResultsMap, 2, false, 0) - value, err := worstMetric.Get() - assert.NoError(t, err) - assert.Equal(t, value, 1.1) - } - { - worstMetric := aggregateMySQLProbes(ctx, probes, clusterName, tabletResultsMap, 3, false, 0) - value, err := worstMetric.Get() - assert.NoError(t, err) - assert.Equal(t, value, 0.6) - } - { - worstMetric := aggregateMySQLProbes(ctx, probes, clusterName, tabletResultsMap, 4, false, 0) - value, err := worstMetric.Get() - assert.NoError(t, err) - assert.Equal(t, value, 0.3) - } - { - worstMetric := aggregateMySQLProbes(ctx, probes, clusterName, tabletResultsMap, 5, false, 0) - value, err := worstMetric.Get() - assert.NoError(t, err) - assert.Equal(t, value, 0.3) - } -} - -func TestAggregateMySQLProbesNoErrorsIgnoreHostsThreshold(t *testing.T) { - ctx := context.Background() - clusterName := "c0" - key1cluster := mysql.GetClusterTablet(clusterName, alias1) - key2cluster := mysql.GetClusterTablet(clusterName, alias2) - key3cluster := mysql.GetClusterTablet(clusterName, alias3) - key4cluster := mysql.GetClusterTablet(clusterName, alias4) - key5cluster := mysql.GetClusterTablet(clusterName, alias5) - tableteResultsMap := mysql.TabletResultMap{ - key1cluster: base.NewSimpleMetricResult(1.2), - key2cluster: base.NewSimpleMetricResult(1.7), - key3cluster: base.NewSimpleMetricResult(0.3), - key4cluster: base.NewSimpleMetricResult(0.6), - key5cluster: base.NewSimpleMetricResult(1.1), - } - var probes mysql.Probes = map[string](*mysql.Probe){} - for clusterKey := range tableteResultsMap { - probes[clusterKey.Alias] = &mysql.Probe{Alias: clusterKey.Alias} - } - { - worstMetric := aggregateMySQLProbes(ctx, probes, clusterName, tableteResultsMap, 0, false, 1.0) - value, err := worstMetric.Get() - assert.NoError(t, err) - assert.Equal(t, value, 1.7) - } - { - worstMetric := aggregateMySQLProbes(ctx, probes, clusterName, tableteResultsMap, 1, false, 1.0) - value, err := worstMetric.Get() - assert.NoError(t, err) - assert.Equal(t, value, 1.2) - } - { - worstMetric := aggregateMySQLProbes(ctx, probes, clusterName, tableteResultsMap, 2, false, 1.0) - value, err := worstMetric.Get() - assert.NoError(t, err) - assert.Equal(t, value, 1.1) - } - { - worstMetric := aggregateMySQLProbes(ctx, probes, clusterName, tableteResultsMap, 3, false, 1.0) - value, err := worstMetric.Get() - assert.NoError(t, err) - assert.Equal(t, value, 0.6) - } - { - worstMetric := aggregateMySQLProbes(ctx, probes, clusterName, tableteResultsMap, 4, false, 1.0) - value, err := worstMetric.Get() - assert.NoError(t, err) - assert.Equal(t, value, 0.6) - } - { - worstMetric := aggregateMySQLProbes(ctx, probes, clusterName, tableteResultsMap, 5, false, 1.0) - value, err := worstMetric.Get() - assert.NoError(t, err) - assert.Equal(t, value, 0.6) - } -} - -func TestAggregateMySQLProbesWithErrors(t *testing.T) { - ctx := context.Background() - clusterName := "c0" - key1cluster := mysql.GetClusterTablet(clusterName, alias1) - key2cluster := mysql.GetClusterTablet(clusterName, alias2) - key3cluster := mysql.GetClusterTablet(clusterName, alias3) - key4cluster := mysql.GetClusterTablet(clusterName, alias4) - key5cluster := mysql.GetClusterTablet(clusterName, alias5) - tabletResultsMap := mysql.TabletResultMap{ - key1cluster: base.NewSimpleMetricResult(1.2), - key2cluster: base.NewSimpleMetricResult(1.7), - key3cluster: base.NewSimpleMetricResult(0.3), - key4cluster: base.NoSuchMetric, - key5cluster: base.NewSimpleMetricResult(1.1), - } - var probes mysql.Probes = map[string](*mysql.Probe){} - for clusterKey := range tabletResultsMap { - probes[clusterKey.Alias] = &mysql.Probe{Alias: clusterKey.Alias} - } - { - worstMetric := aggregateMySQLProbes(ctx, probes, clusterName, tabletResultsMap, 0, false, 0) - _, err := worstMetric.Get() - assert.Error(t, err) - assert.Equal(t, err, base.ErrNoSuchMetric) - } - { - worstMetric := aggregateMySQLProbes(ctx, probes, clusterName, tabletResultsMap, 1, false, 0) - value, err := worstMetric.Get() - assert.NoError(t, err) - assert.Equal(t, value, 1.7) - } - { - worstMetric := aggregateMySQLProbes(ctx, probes, clusterName, tabletResultsMap, 2, false, 0) - value, err := worstMetric.Get() - assert.NoError(t, err) - assert.Equal(t, value, 1.2) - } - - tabletResultsMap[key1cluster] = base.NoSuchMetric - { - worstMetric := aggregateMySQLProbes(ctx, probes, clusterName, tabletResultsMap, 0, false, 0) - _, err := worstMetric.Get() - assert.Error(t, err) - assert.Equal(t, err, base.ErrNoSuchMetric) - } - { - worstMetric := aggregateMySQLProbes(ctx, probes, clusterName, tabletResultsMap, 1, false, 0) - _, err := worstMetric.Get() - assert.Error(t, err) - assert.Equal(t, err, base.ErrNoSuchMetric) - } - { - worstMetric := aggregateMySQLProbes(ctx, probes, clusterName, tabletResultsMap, 2, false, 0) - value, err := worstMetric.Get() - assert.NoError(t, err) - assert.Equal(t, value, 1.7) - } -} diff --git a/go/vt/vttablet/tabletserver/throttle/throttler.go b/go/vt/vttablet/tabletserver/throttle/throttler.go index 803f331cef4..73458974dcb 100644 --- a/go/vt/vttablet/tabletserver/throttle/throttler.go +++ b/go/vt/vttablet/tabletserver/throttle/throttler.go @@ -42,12 +42,14 @@ limitations under the License. package throttle import ( + "bufio" "context" "errors" "fmt" "math" "math/rand/v2" "net/http" + "os" "strconv" "strings" "sync" @@ -76,42 +78,47 @@ import ( "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/config" - "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/mysql" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/throttlerapp" "vitess.io/vitess/go/vt/vttablet/tmclient" ) const ( leaderCheckInterval = 5 * time.Second - mysqlCollectInterval = 250 * time.Millisecond // PRIMARY polls replicas - mysqlDormantCollectInterval = 5 * time.Second // PRIMARY polls replicas when dormant (no recent checks) - mysqlRefreshInterval = 10 * time.Second // Refreshing tablet inventory - mysqlAggregateInterval = 125 * time.Millisecond + activeCollectInterval = 250 * time.Millisecond // PRIMARY polls replicas + dormantCollectInterval = 5 * time.Second // PRIMARY polls replicas when dormant (no recent checks) + inventoryRefreshInterval = 10 * time.Second // Refreshing tablet inventory + metricsAggregateInterval = 125 * time.Millisecond throttledAppsSnapshotInterval = 5 * time.Second recentCheckRateLimiterInterval = 1 * time.Second // Ticker assisting in determining when the throttler was last checked aggregatedMetricsExpiration = 5 * time.Second - recentAppsExpiration = time.Hour * 24 + recentAppsExpiration = time.Hour dormantPeriod = time.Minute // How long since last check to be considered dormant DefaultAppThrottleDuration = time.Hour DefaultThrottleRatio = 1.0 - shardStoreName = "shard" - selfStoreName = "self" - defaultReplicationLagQuery = "select unix_timestamp(now(6))-max(ts/1000000000) as replication_lag from %s.heartbeat" + threadsRunningQuery = "show global status like 'threads_running'" + + inventoryPrefix = "inventory/" + throttlerConfigPrefix = "config/" ) var ( - // flag vars - defaultThrottleLagThreshold = 5 * time.Second - throttleTabletTypes = "replica" + throttleTabletTypes = "replica" + + defaultThresholds = map[base.MetricName]float64{ + base.DefaultMetricName: 5 * time.Second.Seconds(), + base.LagMetricName: 5 * time.Second.Seconds(), + base.ThreadsRunningMetricName: 100, + base.CustomMetricName: 0, + base.LoadAvgMetricName: 1.0, + } ) var ( statsThrottlerHeartbeatRequests = stats.NewCounter("ThrottlerHeartbeatRequests", "heartbeat requests") - statsThrottlerRecentlyChecked = stats.NewCounter("ThrottlerRecentlyChecked", "recently checked") statsThrottlerProbeRecentlyChecked = stats.NewCounter("ThrottlerProbeRecentlyChecked", "probe recently checked") ) @@ -128,16 +135,6 @@ var ( ErrThrottlerNotOpen = errors.New("throttler not open") ) -// ThrottleCheckType allows a client to indicate what type of check it wants to issue. See available types below. -type ThrottleCheckType int // nolint:revive - -const ( - // ThrottleCheckPrimaryWrite indicates a check before making a write on a primary server - ThrottleCheckPrimaryWrite ThrottleCheckType = iota - // ThrottleCheckSelf indicates a check on a specific server health - ThrottleCheckSelf -) - // throttlerTopoService represents the functionality we expect from a TopoServer, abstracted so that // it can be mocked in unit tests type throttlerTopoService interface { @@ -159,10 +156,10 @@ type Throttler struct { isOpen atomic.Bool leaderCheckInterval time.Duration - mysqlCollectInterval time.Duration - mysqlDormantCollectInterval time.Duration - mysqlRefreshInterval time.Duration - mysqlAggregateInterval time.Duration + activeCollectInterval time.Duration + dormantCollectInterval time.Duration + inventoryRefreshInterval time.Duration + metricsAggregateInterval time.Duration throttledAppsSnapshotInterval time.Duration dormantPeriod time.Duration @@ -174,6 +171,7 @@ type Throttler struct { srvTopoServer srvtopo.Server heartbeatWriter heartbeat.HeartbeatWriter overrideTmClient tmclient.TabletManagerClient + tabletAlias string recentCheckRateLimiter *timer.RateLimiter recentCheckDormantDiff int64 @@ -181,22 +179,24 @@ type Throttler struct { throttleTabletTypesMap map[topodatapb.TabletType]bool - mysqlThrottleMetricChan chan *mysql.MySQLThrottleMetric - mysqlInventoryChan chan *mysql.Inventory - mysqlClusterProbesChan chan *mysql.ClusterProbes - throttlerConfigChan chan *topodatapb.ThrottlerConfig + throttleMetricChan chan *base.ThrottleMetric + clusterProbesChan chan *base.ClusterProbes + throttlerConfigChan chan *topodatapb.ThrottlerConfig + serialFuncChan chan func() // Used by unit tests to inject non-racy behavior - mysqlInventory *mysql.Inventory + inventory *base.Inventory - metricsQuery atomic.Value - MetricsThreshold atomic.Uint64 - checkAsCheckSelf atomic.Bool + metricsQuery atomic.Value + customMetricsQuery atomic.Value + MetricsThreshold atomic.Uint64 + checkAsCheckSelf atomic.Bool - mysqlClusterThresholds *cache.Cache - aggregatedMetrics *cache.Cache - throttledApps *cache.Cache - recentApps *cache.Cache - metricsHealth *cache.Cache + metricThresholds *cache.Cache + aggregatedMetrics *cache.Cache + throttledApps *cache.Cache + recentApps *cache.Cache + metricsHealth *cache.Cache + appCheckedMetrics *cache.Cache initMutex sync.Mutex enableMutex sync.Mutex @@ -204,9 +204,11 @@ type Throttler struct { cancelEnableContext context.CancelFunc throttledAppsMutex sync.Mutex - readSelfThrottleMetric func(context.Context, *mysql.Probe) *mysql.MySQLThrottleMetric // overwritten by unit test + readSelfThrottleMetrics func(context.Context) base.ThrottleMetrics // overwritten by unit test httpClient *http.Client + + hostCpuCoreCount atomic.Int32 } // ThrottlerStatus published some status values from the throttler @@ -214,17 +216,23 @@ type ThrottlerStatus struct { Keyspace string Shard string - IsLeader bool - IsOpen bool - IsEnabled bool - IsDormant bool - IsRecentlyChecked bool + IsLeader bool + IsOpen bool + IsEnabled bool + IsDormant bool + RecentlyChecked bool - Query string - Threshold float64 + Query string + CustomQuery string + Threshold float64 + MetricNameUsedAsDefault string AggregatedMetrics map[string]base.MetricResult + MetricsThresholds map[string]float64 MetricsHealth base.MetricHealthMap + ThrottledApps []base.AppThrottle + AppCheckedMetrics map[string]string + RecentApps map[string](*base.RecentApp) } // NewThrottler creates a Throttler @@ -242,27 +250,28 @@ func NewThrottler(env tabletenv.Env, srvTopoServer srvtopo.Server, ts *topo.Serv }), } - throttler.mysqlThrottleMetricChan = make(chan *mysql.MySQLThrottleMetric) - throttler.mysqlInventoryChan = make(chan *mysql.Inventory, 1) - throttler.mysqlClusterProbesChan = make(chan *mysql.ClusterProbes) + throttler.throttleMetricChan = make(chan *base.ThrottleMetric) + throttler.clusterProbesChan = make(chan *base.ClusterProbes) throttler.throttlerConfigChan = make(chan *topodatapb.ThrottlerConfig) - throttler.mysqlInventory = mysql.NewInventory() + throttler.serialFuncChan = make(chan func()) + throttler.inventory = base.NewInventory() throttler.throttledApps = cache.New(cache.NoExpiration, 0) - throttler.mysqlClusterThresholds = cache.New(cache.NoExpiration, 0) + throttler.metricThresholds = cache.New(cache.NoExpiration, 0) throttler.aggregatedMetrics = cache.New(aggregatedMetricsExpiration, 0) - throttler.recentApps = cache.New(recentAppsExpiration, 0) + throttler.recentApps = cache.New(recentAppsExpiration, recentAppsExpiration) throttler.metricsHealth = cache.New(cache.NoExpiration, 0) + throttler.appCheckedMetrics = cache.New(cache.NoExpiration, 0) - throttler.httpClient = base.SetupHTTPClient(2 * mysqlCollectInterval) + throttler.httpClient = base.SetupHTTPClient(2 * activeCollectInterval) throttler.initThrottleTabletTypes() throttler.check = NewThrottlerCheck(throttler) throttler.leaderCheckInterval = leaderCheckInterval - throttler.mysqlCollectInterval = mysqlCollectInterval - throttler.mysqlDormantCollectInterval = mysqlDormantCollectInterval - throttler.mysqlRefreshInterval = mysqlRefreshInterval - throttler.mysqlAggregateInterval = mysqlAggregateInterval + throttler.activeCollectInterval = activeCollectInterval + throttler.dormantCollectInterval = dormantCollectInterval + throttler.inventoryRefreshInterval = inventoryRefreshInterval + throttler.metricsAggregateInterval = metricsAggregateInterval throttler.throttledAppsSnapshotInterval = throttledAppsSnapshotInterval throttler.dormantPeriod = dormantPeriod throttler.recentCheckDormantDiff = int64(throttler.dormantPeriod / recentCheckRateLimiterInterval) @@ -271,9 +280,9 @@ func NewThrottler(env tabletenv.Env, srvTopoServer srvtopo.Server, ts *topo.Serv throttler.recentCheckDiff = 1 } - throttler.StoreMetricsThreshold(defaultThrottleLagThreshold.Seconds()) //default - throttler.readSelfThrottleMetric = func(ctx context.Context, p *mysql.Probe) *mysql.MySQLThrottleMetric { - return throttler.readSelfMySQLThrottleMetric(ctx, p) + throttler.StoreMetricsThreshold(defaultThresholds[base.LagMetricName]) + throttler.readSelfThrottleMetrics = func(ctx context.Context) base.ThrottleMetrics { + return throttler.readSelfThrottleMetricsInternal(ctx) } return throttler @@ -309,6 +318,14 @@ func (throttler *Throttler) GetMetricsQuery() string { return throttler.metricsQuery.Load().(string) } +func (throttler *Throttler) GetCustomMetricsQuery() string { + val := throttler.customMetricsQuery.Load() + if val == nil { + return "" + } + return val.(string) +} + func (throttler *Throttler) GetMetricsThreshold() float64 { return math.Float64frombits(throttler.MetricsThreshold.Load()) } @@ -318,23 +335,31 @@ func (throttler *Throttler) initConfig() { log.Infof("Throttler: initializing config") throttler.configSettings = &config.ConfigurationSettings{ - Stores: config.StoresSettings{ - MySQL: config.MySQLConfigurationSettings{ - IgnoreDialTCPErrors: true, - Clusters: map[string](*config.MySQLClusterConfigurationSettings){}, - }, + MySQLStore: config.MySQLConfigurationSettings{ + IgnoreDialTCPErrors: true, }, } - throttler.configSettings.Stores.MySQL.Clusters[selfStoreName] = &config.MySQLClusterConfigurationSettings{ - MetricQuery: throttler.GetMetricsQuery(), - ThrottleThreshold: &throttler.MetricsThreshold, - IgnoreHostsCount: 0, - } - throttler.configSettings.Stores.MySQL.Clusters[shardStoreName] = &config.MySQLClusterConfigurationSettings{ - MetricQuery: throttler.GetMetricsQuery(), - ThrottleThreshold: &throttler.MetricsThreshold, - IgnoreHostsCount: 0, + metrics := make(map[base.MetricName]*config.MySQLMetricConfigurationSettings) + for _, metricsName := range base.KnownMetricNames { + metrics[metricsName] = &config.MySQLMetricConfigurationSettings{ + Name: metricsName, + } } + metrics[base.DefaultMetricName].CustomQuery = "" + metrics[base.DefaultMetricName].Threshold.Store(throttler.MetricsThreshold.Load()) + + metrics[base.LagMetricName].CustomQuery = sqlparser.BuildParsedQuery(defaultReplicationLagQuery, sidecar.GetIdentifier()).Query + metrics[base.LagMetricName].Threshold.Store(throttler.MetricsThreshold.Load()) + + metrics[base.ThreadsRunningMetricName].CustomQuery = threadsRunningQuery + metrics[base.ThreadsRunningMetricName].Threshold.Store(math.Float64bits(defaultThresholds[base.ThreadsRunningMetricName])) + + metrics[base.CustomMetricName].CustomQuery = "" + metrics[base.CustomMetricName].Threshold.Store(math.Float64bits(defaultThresholds[base.CustomMetricName])) + + metrics[base.LoadAvgMetricName].Threshold.Store(math.Float64bits(defaultThresholds[base.LoadAvgMetricName])) + + throttler.configSettings.MySQLStore.Metrics = metrics } // readThrottlerConfig proactively reads the throttler's config from SrvKeyspace in local topo @@ -354,10 +379,16 @@ func (throttler *Throttler) normalizeThrottlerConfig(throttlerConfig *topodatapb if throttlerConfig.ThrottledApps == nil { throttlerConfig.ThrottledApps = make(map[string]*topodatapb.ThrottledAppRule) } + if throttlerConfig.AppCheckedMetrics == nil { + throttlerConfig.AppCheckedMetrics = make(map[string]*topodatapb.ThrottlerConfig_MetricNames) + } + if throttlerConfig.MetricThresholds == nil { + throttlerConfig.MetricThresholds = make(map[string]float64) + } if throttlerConfig.CustomQuery == "" { // no custom query; we check replication lag if throttlerConfig.Threshold == 0 { - throttlerConfig.Threshold = defaultThrottleLagThreshold.Seconds() + throttlerConfig.Threshold = defaultThresholds[base.LagMetricName] } } return throttlerConfig @@ -388,6 +419,24 @@ func (throttler *Throttler) WatchSrvKeyspaceCallback(srvks *topodatapb.SrvKeyspa return true } +// convergeMetricThresholds looks at metric thresholds as defined by: +// - inventory (also includes changes to throttler.MetricsThreshold). This always includes all known metrics +// ie lag, threads_running, etc... +// - throttler config. This can be a list of zero or more entries. These metrics override the inventory. +func (throttler *Throttler) convergeMetricThresholds() { + for _, metricName := range base.KnownMetricNames { + if val, ok := throttler.metricThresholds.Get(throttlerConfigPrefix + metricName.String()); ok { + // Value supplied by throttler config takes precedence + throttler.metricThresholds.Set(metricName.String(), val, cache.DefaultExpiration) + continue + } + // metric not indicated in the throttler config, therefore we should use the default threshold for that metric + if val, ok := throttler.metricThresholds.Get(inventoryPrefix + metricName.String()); ok { + throttler.metricThresholds.Set(metricName.String(), val, cache.DefaultExpiration) + } + } +} + // applyThrottlerConfig receives a Throttlerconfig as read from SrvKeyspace, and applies the configuration. // This may cause the throttler to be enabled/disabled, and of course it affects the throttling query/threshold. // Note: you should be holding the initMutex when calling this function. @@ -398,10 +447,70 @@ func (throttler *Throttler) applyThrottlerConfig(ctx context.Context, throttlerC } else { throttler.metricsQuery.Store(throttlerConfig.CustomQuery) } - throttler.StoreMetricsThreshold(throttlerConfig.Threshold) + throttler.customMetricsQuery.Store(throttlerConfig.CustomQuery) + if throttlerConfig.Threshold > 0 || throttlerConfig.CustomQuery != "" { + // We do not allow Threshold=0, unless there is a custom query. + // Without a custom query, the theshold applies to replication lag, + // which does not make sense to have as zero. + // This is already validated in VtctldServer.UpdateThrottlerConfig() in grpcvtctldserver/server.go, + // but worth validating again. + // Once transition to multi-metrics is complete (1 or 2 versions after first shipping it), + // this legacy behavior can be removed. We won't be using `Threadhold` anymore, and we will + // require per-metric threshold. + throttler.StoreMetricsThreshold(throttlerConfig.Threshold) + } throttler.checkAsCheckSelf.Store(throttlerConfig.CheckAsCheckSelf) - for _, appRule := range throttlerConfig.ThrottledApps { - throttler.ThrottleApp(appRule.Name, protoutil.TimeFromProto(appRule.ExpiresAt).UTC(), appRule.Ratio, appRule.Exempt) + { + // Throttled apps/rules + for _, appRule := range throttlerConfig.ThrottledApps { + throttler.ThrottleApp(appRule.Name, protoutil.TimeFromProto(appRule.ExpiresAt).UTC(), appRule.Ratio, appRule.Exempt) + } + for app := range throttler.throttledAppsSnapshot() { + if app == throttlerapp.TestingAlwaysThrottlerName.String() { + // Never remove this app + continue + } + if _, ok := throttlerConfig.ThrottledApps[app]; !ok { + // app not indicated in the throttler config, therefore should be removed from the map + throttler.UnthrottleApp(app) + } + } + } + { + // throttler.appCheckedMetrics needs to reflect throttlerConfig.AppCheckedMetrics + for app, metrics := range throttlerConfig.AppCheckedMetrics { + metricNames := base.MetricNames{} + if len(metrics.Names) > 0 { + for _, name := range metrics.Names { + metricName := base.MetricName(name) + metricNames = append(metricNames, metricName) + } + throttler.appCheckedMetrics.Set(app, metricNames, cache.DefaultExpiration) + } else { + // Empty list of metrics means we should use the default metrics + throttler.appCheckedMetrics.Delete(app) + } + } + for app := range throttler.appCheckedMetricsSnapshot() { + if _, ok := throttlerConfig.AppCheckedMetrics[app]; !ok { + // app not indicated in the throttler config, therefore should be removed from the map + throttler.appCheckedMetrics.Delete(app) + } + } + } + { + // Metric thresholds + for metricName, threshold := range throttlerConfig.MetricThresholds { + throttler.metricThresholds.Set(throttlerConfigPrefix+metricName, threshold, cache.DefaultExpiration) + } + for _, metricName := range base.KnownMetricNames { + if _, ok := throttlerConfig.MetricThresholds[metricName.String()]; !ok { + // metric not indicated in the throttler config, therefore should be removed from the map + // so that we know to apply the inventory default threshold + throttler.metricThresholds.Delete(throttlerConfigPrefix + metricName.String()) + } + } + throttler.convergeMetricThresholds() } if throttlerConfig.Enabled { go throttler.Enable() @@ -469,7 +578,6 @@ func (throttler *Throttler) Disable() bool { return false } log.Infof("Throttler: disabling") - // _ = throttler.updateConfig(ctx, false, throttler.MetricsThreshold.Get()) // TODO(shlomi) throttler.cancelEnableContext() return true @@ -542,10 +650,11 @@ func (throttler *Throttler) Open() error { // is not known when the TabletServer is created, which in turn creates the // Throttler. throttler.metricsQuery.Store(sqlparser.BuildParsedQuery(defaultReplicationLagQuery, sidecar.GetIdentifier()).Query) // default + throttler.customMetricsQuery.Store("") throttler.initConfig() throttler.pool.Open(throttler.env.Config().DB.AppWithDB(), throttler.env.Config().DB.DbaWithDB(), throttler.env.Config().DB.AppDebugWithDB()) - throttler.ThrottleApp("always-throttled-app", time.Now().Add(time.Hour*24*365*10), DefaultThrottleRatio, false) + throttler.ThrottleApp(throttlerapp.TestingAlwaysThrottlerName.String(), time.Now().Add(time.Hour*24*365*10), DefaultThrottleRatio, false) go throttler.retryReadAndApplyThrottlerConfig(ctx) @@ -617,48 +726,91 @@ func (throttler *Throttler) stimulatePrimaryThrottler(ctx context.Context, tmCli return nil } -func (throttler *Throttler) generateSelfMySQLThrottleMetricFunc(ctx context.Context, probe *mysql.Probe) func() *mysql.MySQLThrottleMetric { - f := func() *mysql.MySQLThrottleMetric { - return throttler.readSelfThrottleMetric(ctx, probe) +func (throttler *Throttler) readSelfLoadAvgPerCore(ctx context.Context) *base.ThrottleMetric { + metric := &base.ThrottleMetric{ + Scope: base.SelfScope, + Alias: throttler.tabletAlias, + } + + coreCount := throttler.hostCpuCoreCount.Load() + if coreCount == 0 { + // Count cores. This number is not going to change in the lifetime of this tablet, + // hence it makes sense to read it once then cache it. + + // We choose to read /proc/cpuinfo over executing "nproc" or similar commands. + var coreCount int32 + f, err := os.Open("/proc/cpuinfo") + if err != nil { + return metric.WithError(err) + } + defer f.Close() + + scanner := bufio.NewScanner(f) + for scanner.Scan() { + if strings.HasPrefix(scanner.Text(), "processor") { + coreCount++ + } + } + + if err := scanner.Err(); err != nil { + return metric.WithError(err) + } + throttler.hostCpuCoreCount.Store(coreCount) + } + if coreCount == 0 { + return metric.WithError(fmt.Errorf("could not determine number of cores")) + } + { + content, err := os.ReadFile("/proc/loadavg") + if err != nil { + return metric.WithError(err) + } + fields := strings.Fields(string(content)) + if len(fields) == 0 { + return metric.WithError(fmt.Errorf("unexpected /proc/loadavg content")) + } + loadAvg, err := strconv.ParseFloat(fields[0], 64) + if err != nil { + return metric.WithError(err) + } + metric.Value = loadAvg / float64(throttler.hostCpuCoreCount.Load()) } - return f + return metric } -// readSelfMySQLThrottleMetric reads the mysql metric from thi very tablet's backend mysql. -func (throttler *Throttler) readSelfMySQLThrottleMetric(ctx context.Context, probe *mysql.Probe) *mysql.MySQLThrottleMetric { - metric := &mysql.MySQLThrottleMetric{ - ClusterName: selfStoreName, - Alias: "", - Value: 0, - Err: nil, +// readSelfMySQLThrottleMetric reads the metric from this very tablet or from its backend mysql. +func (throttler *Throttler) readSelfMySQLThrottleMetric(ctx context.Context, query string) *base.ThrottleMetric { + metric := &base.ThrottleMetric{ + Scope: base.SelfScope, + Alias: throttler.tabletAlias, + } + if query == "" { + return metric } conn, err := throttler.pool.Get(ctx, nil) if err != nil { - metric.Err = err - return metric + return metric.WithError(err) } defer conn.Recycle() - tm, err := conn.Conn.Exec(ctx, probe.MetricQuery, 1, true) + tm, err := conn.Conn.Exec(ctx, query, 1, true) if err != nil { - metric.Err = err - return metric + return metric.WithError(err) } row := tm.Named().Row() if row == nil { - metric.Err = fmt.Errorf("no results for readSelfMySQLThrottleMetric") - return metric + return metric.WithError(fmt.Errorf("no results for readSelfThrottleMetric")) } - metricsQueryType := mysql.GetMetricsQueryType(throttler.GetMetricsQuery()) + metricsQueryType := base.GetMetricsQueryType(query) switch metricsQueryType { - case mysql.MetricsQueryTypeSelect: + case base.MetricsQueryTypeSelect: // We expect a single row, single column result. // The "for" iteration below is just a way to get first result without knowing column name for k := range row { metric.Value, metric.Err = row.ToFloat64(k) } - case mysql.MetricsQueryTypeShowGlobal: + case base.MetricsQueryTypeShowGlobal: metric.Value, metric.Err = strconv.ParseFloat(row["Value"].ToString(), 64) default: metric.Err = fmt.Errorf("Unsupported metrics query type for query: %s", throttler.GetMetricsQuery()) @@ -709,22 +861,23 @@ func (throttler *Throttler) Operate(ctx context.Context, wg *sync.WaitGroup) { return t } leaderCheckTicker := addTicker(throttler.leaderCheckInterval) - mysqlCollectTicker := addTicker(throttler.mysqlCollectInterval) - mysqlDormantCollectTicker := addTicker(throttler.mysqlDormantCollectInterval) - mysqlRefreshTicker := addTicker(throttler.mysqlRefreshInterval) - mysqlAggregateTicker := addTicker(throttler.mysqlAggregateInterval) + activeCollectTicker := addTicker(throttler.activeCollectInterval) + dormantCollectTicker := addTicker(throttler.dormantCollectInterval) + inventoryRefreshTicker := addTicker(throttler.inventoryRefreshInterval) + metricsAggregateTicker := addTicker(throttler.metricsAggregateInterval) throttledAppsTicker := addTicker(throttler.throttledAppsSnapshotInterval) primaryStimulatorRateLimiter := timer.NewRateLimiter(throttler.dormantPeriod) throttler.recentCheckRateLimiter = timer.NewRateLimiter(recentCheckRateLimiterInterval) wg.Add(1) go func() { + defer wg.Done() // Called last, once all tickers are stopped. + defer func() { throttler.recentCheckRateLimiter.Stop() primaryStimulatorRateLimiter.Stop() throttler.aggregatedMetrics.Flush() throttler.recentApps.Flush() - wg.Done() }() // we do not flush throttler.throttledApps because this is data submitted by the user; the user expects the data to survive a disable+enable @@ -770,21 +923,17 @@ func (throttler *Throttler) Operate(ctx context.Context, wg *sync.WaitGroup) { if transitionedIntoLeader { // transitioned into leadership, let's speed up the next 'refresh' and 'collect' ticks - go mysqlRefreshTicker.TickNow() + go inventoryRefreshTicker.TickNow() throttler.requestHeartbeats() } }() - case <-mysqlCollectTicker.C: + case <-activeCollectTicker.C: if throttler.IsOpen() { // frequent // Always collect self metrics: - throttler.collectMySQLMetrics(ctx, tmClient, func(clusterName string) bool { - return clusterName == selfStoreName - }) + throttler.collectSelfMetrics(ctx) if !throttler.isDormant() { - throttler.collectMySQLMetrics(ctx, tmClient, func(clusterName string) bool { - return clusterName != selfStoreName - }) + throttler.collectShardMetrics(ctx, tmClient) } // if throttler.recentlyChecked() { @@ -806,29 +955,32 @@ func (throttler *Throttler) Operate(ctx context.Context, wg *sync.WaitGroup) { } } - case <-mysqlDormantCollectTicker.C: + case <-dormantCollectTicker.C: if throttler.IsOpen() { // infrequent if throttler.isDormant() { - throttler.collectMySQLMetrics(ctx, tmClient, func(clusterName string) bool { - return clusterName != selfStoreName - }) + throttler.collectShardMetrics(ctx, tmClient) } } - case metric := <-throttler.mysqlThrottleMetricChan: - // incoming MySQL metric, frequent, as result of collectMySQLMetrics() - throttler.mysqlInventory.TabletMetrics[metric.GetClusterTablet()] = metric - case <-mysqlRefreshTicker.C: + case metric := <-throttler.throttleMetricChan: + // incoming metric, frequent, as result of collectMetrics() + metricResultsMap, ok := throttler.inventory.TabletMetrics[metric.GetTabletAlias()] + if !ok { + metricResultsMap = base.NewMetricResultMap() + throttler.inventory.TabletMetrics[metric.GetTabletAlias()] = metricResultsMap + } + metricResultsMap[metric.Name] = metric + case <-inventoryRefreshTicker.C: // sparse if throttler.IsOpen() { - throttler.refreshMySQLInventory(ctx) + throttler.refreshInventory(ctx) } - case probes := <-throttler.mysqlClusterProbesChan: - // incoming structural update, sparse, as result of refreshMySQLInventory() - throttler.updateMySQLClusterProbes(ctx, probes) - case <-mysqlAggregateTicker.C: + case probes := <-throttler.clusterProbesChan: + // incoming structural update, sparse, as result of refreshInventory() + throttler.updateClusterProbes(ctx, probes) + case <-metricsAggregateTicker.C: if throttler.IsOpen() { - throttler.aggregateMySQLMetrics(ctx) + throttler.aggregateMetrics() } case <-throttledAppsTicker.C: if throttler.IsOpen() { @@ -836,35 +988,51 @@ func (throttler *Throttler) Operate(ctx context.Context, wg *sync.WaitGroup) { } case throttlerConfig := <-throttler.throttlerConfigChan: throttler.applyThrottlerConfig(ctx, throttlerConfig) + case f := <-throttler.serialFuncChan: + // Used in unit testing to serialize operations and avoid race conditions + f() } } }() } -func (throttler *Throttler) generateTabletProbeFunction(ctx context.Context, clusterName string, tmClient tmclient.TabletManagerClient, probe *mysql.Probe) (probeFunc func() *mysql.MySQLThrottleMetric) { - return func() *mysql.MySQLThrottleMetric { +func (throttler *Throttler) generateTabletProbeFunction(scope base.Scope, tmClient tmclient.TabletManagerClient, probe *base.Probe) (probeFunc func(context.Context) base.ThrottleMetrics) { + metricsWithError := func(err error) base.ThrottleMetrics { + metrics := base.ThrottleMetrics{} + for _, metricName := range base.KnownMetricNames { + metrics[metricName] = &base.ThrottleMetric{ + Name: metricName, + Scope: scope, + Alias: probe.Alias, + Err: err, + } + } + return metrics + } + return func(ctx context.Context) base.ThrottleMetrics { // Some reasonable timeout, to ensure we release connections even if they're hanging (otherwise grpc-go keeps polling those connections forever) - ctx, cancel := context.WithTimeout(ctx, 4*mysqlCollectInterval) + ctx, cancel := context.WithTimeout(ctx, 4*activeCollectInterval) defer cancel() - // Hit a tablet's `check-self` via HTTP, and convert its CheckResult JSON output into a MySQLThrottleMetric - mySQLThrottleMetric := mysql.NewMySQLThrottleMetric() - mySQLThrottleMetric.ClusterName = clusterName - mySQLThrottleMetric.Alias = probe.Alias + // Hit a tablet's `check-self` via HTTP, and convert its CheckResult JSON output into a ThrottleMetric + throttleMetric := base.NewThrottleMetric() + throttleMetric.Name = base.DefaultMetricName + throttleMetric.Scope = scope + throttleMetric.Alias = probe.Alias if probe.Tablet == nil { - mySQLThrottleMetric.Err = fmt.Errorf("found nil tablet reference for alias %v, hostname %v", probe.Alias, probe.Tablet.Hostname) - return mySQLThrottleMetric + return metricsWithError(fmt.Errorf("found nil tablet reference for alias '%v'", probe.Alias)) } - req := &tabletmanagerdatapb.CheckThrottlerRequest{} // We leave AppName empty; it will default to VitessName anyway, and we can save some proto space + metrics := make(base.ThrottleMetrics) + + req := &tabletmanagerdatapb.CheckThrottlerRequest{MultiMetricsEnabled: true} // We leave AppName empty; it will default to VitessName anyway, and we can save some proto space resp, gRPCErr := tmClient.CheckThrottler(ctx, probe.Tablet, req) if gRPCErr != nil { - mySQLThrottleMetric.Err = fmt.Errorf("gRPC error accessing tablet %v. Err=%v", probe.Alias, gRPCErr) - return mySQLThrottleMetric + return metricsWithError(fmt.Errorf("gRPC error accessing tablet %v. Err=%v", probe.Alias, gRPCErr)) } - mySQLThrottleMetric.Value = resp.Value + throttleMetric.Value = resp.Value if resp.StatusCode == http.StatusInternalServerError { - mySQLThrottleMetric.Err = fmt.Errorf("Status code: %d", resp.StatusCode) + throttleMetric.Err = fmt.Errorf("Status code: %d", resp.StatusCode) } if resp.RecentlyChecked { // We have just probed a tablet, and it reported back that someone just recently "check"ed it. @@ -872,185 +1040,280 @@ func (throttler *Throttler) generateTabletProbeFunction(ctx context.Context, clu throttler.requestHeartbeats() statsThrottlerProbeRecentlyChecked.Add(1) } - return mySQLThrottleMetric + for name, metric := range resp.Metrics { + metricName := base.MetricName(name) + metrics[metricName] = &base.ThrottleMetric{ + Name: metricName, + Scope: scope, + Alias: probe.Alias, + Value: metric.Value, + } + if metric.Error != "" { + metrics[metricName].Err = errors.New(metric.Error) + } + } + if len(resp.Metrics) == 0 { + // Backwards compatibility to v20. v20 does not report multi metrics. + throttleMetric.Name = throttler.metricNameUsedAsDefault() + metrics[throttleMetric.Name] = throttleMetric + } + + return metrics } } -func (throttler *Throttler) collectMySQLMetrics(ctx context.Context, tmClient tmclient.TabletManagerClient, includeCluster func(clusterName string) bool) error { - // synchronously, get lists of probes - for clusterName, probes := range throttler.mysqlInventory.ClustersProbes { - if !includeCluster(clusterName) { +func (throttler *Throttler) readSelfThrottleMetricsInternal(ctx context.Context) base.ThrottleMetrics { + + writeMetric := func(metricName base.MetricName, metric *base.ThrottleMetric) { + metric.Name = metricName + select { + case <-ctx.Done(): + return + case throttler.throttleMetricChan <- metric: + } + } + + go writeMetric(base.LagMetricName, throttler.readSelfMySQLThrottleMetric(ctx, sqlparser.BuildParsedQuery(defaultReplicationLagQuery, sidecar.GetIdentifier()).Query)) + go writeMetric(base.ThreadsRunningMetricName, throttler.readSelfMySQLThrottleMetric(ctx, threadsRunningQuery)) + go writeMetric(base.CustomMetricName, throttler.readSelfMySQLThrottleMetric(ctx, throttler.GetCustomMetricsQuery())) + go writeMetric(base.LoadAvgMetricName, throttler.readSelfLoadAvgPerCore(ctx)) + return nil +} + +func (throttler *Throttler) collectSelfMetrics(ctx context.Context) { + probe := throttler.inventory.ClustersProbes[throttler.tabletAlias] + if probe == nil { + // probe not created yet + return + } + go func() { + // Avoid querying the same server twice at the same time. If previous read is still there, + // we avoid re-reading it. + if !atomic.CompareAndSwapInt64(&probe.QueryInProgress, 0, 1) { + return + } + defer atomic.StoreInt64(&probe.QueryInProgress, 0) + + // Throttler is probing its own tablet's metrics: + _ = base.ReadThrottleMetrics(ctx, probe, throttler.readSelfThrottleMetrics) + }() +} + +func (throttler *Throttler) collectShardMetrics(ctx context.Context, tmClient tmclient.TabletManagerClient) { + // probes is known not to change. It can be *replaced*, but not changed. + // so it's safe to iterate it + for _, probe := range throttler.inventory.ClustersProbes { + if probe.Alias == throttler.tabletAlias { + // We skip collecting our own metrics continue } - clusterName := clusterName - // probes is known not to change. It can be *replaced*, but not changed. - // so it's safe to iterate it - for _, probe := range probes { - go func(probe *mysql.Probe) { - // Avoid querying the same server twice at the same time. If previous read is still there, - // we avoid re-reading it. - if !atomic.CompareAndSwapInt64(&probe.QueryInProgress, 0, 1) { - return - } - defer atomic.StoreInt64(&probe.QueryInProgress, 0) - - var throttleMetricFunc func() *mysql.MySQLThrottleMetric - if clusterName == selfStoreName { - // Throttler is probing its own tablet's metrics: - throttleMetricFunc = throttler.generateSelfMySQLThrottleMetricFunc(ctx, probe) - } else { - // Throttler probing other tablets: - throttleMetricFunc = throttler.generateTabletProbeFunction(ctx, clusterName, tmClient, probe) - } - throttleMetrics := mysql.ReadThrottleMetric(probe, clusterName, throttleMetricFunc) + go func(probe *base.Probe) { + // Avoid querying the same server twice at the same time. If previous read is still there, + // we avoid re-reading it. + if !atomic.CompareAndSwapInt64(&probe.QueryInProgress, 0, 1) { + return + } + defer atomic.StoreInt64(&probe.QueryInProgress, 0) + + // Throttler probing other tablets: + throttleMetricFunc := throttler.generateTabletProbeFunction(base.ShardScope, tmClient, probe) + + throttleMetrics := base.ReadThrottleMetrics(ctx, probe, throttleMetricFunc) + for _, metric := range throttleMetrics { select { case <-ctx.Done(): return - case throttler.mysqlThrottleMetricChan <- throttleMetrics: + case throttler.throttleMetricChan <- metric: } - }(probe) - } + } + }(probe) } - return nil } -// refreshMySQLInventory will re-structure the inventory based on reading config settings -func (throttler *Throttler) refreshMySQLInventory(ctx context.Context) error { +// refreshInventory will re-structure the inventory based on reading config settings +func (throttler *Throttler) refreshInventory(ctx context.Context) error { // distribute the query/threshold from the throttler down to the cluster settings and from there to the probes - metricsQuery := throttler.GetMetricsQuery() - metricsThreshold := throttler.MetricsThreshold.Load() - addProbe := func(alias string, tablet *topodatapb.Tablet, clusterName string, clusterSettings *config.MySQLClusterConfigurationSettings, probes mysql.Probes) bool { - for _, ignore := range clusterSettings.IgnoreHosts { + addProbe := func(alias string, tablet *topodatapb.Tablet, scope base.Scope, mysqlSettings *config.MySQLConfigurationSettings, probes base.Probes) bool { + for _, ignore := range mysqlSettings.IgnoreHosts { if strings.Contains(alias, ignore) { log.Infof("Throttler: tablet ignored: %+v", alias) return false } } - if clusterName != selfStoreName { + if scope != base.SelfScope { if alias == "" { - log.Errorf("Throttler: got empty alias for cluster: %+v", clusterName) + log.Errorf("Throttler: got empty alias for scope: %+v", scope) return false } if tablet == nil { - log.Errorf("Throttler: got nil tablet for alias: %v in cluster: %+v", alias, clusterName) + log.Errorf("Throttler: got nil tablet for alias: %v in scope: %+v", alias, scope) return false } } - probe := &mysql.Probe{ + probe := &base.Probe{ Alias: alias, Tablet: tablet, - MetricQuery: clusterSettings.MetricQuery, - CacheMillis: clusterSettings.CacheMillis, + CacheMillis: mysqlSettings.CacheMillis, } probes[alias] = probe return true } - attemptWriteProbes := func(clusterProbes *mysql.ClusterProbes) error { + attemptWriteProbes := func(clusterProbes *base.ClusterProbes) error { select { case <-ctx.Done(): return ctx.Err() - case throttler.mysqlClusterProbesChan <- clusterProbes: + case throttler.clusterProbesChan <- clusterProbes: return nil } } - for clusterName, clusterSettings := range throttler.configSettings.Stores.MySQL.Clusters { - clusterName := clusterName - clusterSettings.MetricQuery = metricsQuery - clusterSettings.ThrottleThreshold.Store(metricsThreshold) - - clusterSettingsCopy := *clusterSettings - // config may dynamically change, but internal structure (config.Settings().Stores.MySQL.Clusters in our case) - // is immutable and can only be _replaced_. Hence, it's safe to read in a goroutine: - collect := func() error { - throttler.mysqlClusterThresholds.Set(clusterName, math.Float64frombits(clusterSettingsCopy.ThrottleThreshold.Load()), cache.DefaultExpiration) - clusterProbes := &mysql.ClusterProbes{ - ClusterName: clusterName, - IgnoreHostsCount: clusterSettingsCopy.IgnoreHostsCount, - TabletProbes: mysql.NewProbes(), - } + metricsThreshold := throttler.MetricsThreshold.Load() + metricNameUsedAsDefault := throttler.metricNameUsedAsDefault() + mysqlSettings := &throttler.configSettings.MySQLStore + mysqlSettings.Metrics[base.DefaultMetricName].Threshold.Store(metricsThreshold) + for metricName, metricConfig := range mysqlSettings.Metrics { + threshold := metricConfig.Threshold.Load() + if metricName == metricNameUsedAsDefault && metricsThreshold != 0 { + // backwards compatibility to v20: + threshold = metricsThreshold + } - if clusterName == selfStoreName { - // special case: just looking at this tablet's MySQL server. - // We will probe this "cluster" (of one server) is a special way. - addProbe("", nil, clusterName, &clusterSettingsCopy, clusterProbes.TabletProbes) - return attemptWriteProbes(clusterProbes) - } - if !throttler.isLeader.Load() { - // This tablet may have used to be the primary, but it isn't now. It may have a recollection - // of previous clusters it used to probe. It may have recollection of specific probes for such clusters. - // This now ensures any existing cluster probes are overridden with an empty list of probes. - // `clusterProbes` was created above as empty, and identifiable via `clusterName`. This will in turn - // be used to overwrite throttler.mysqlInventory.ClustersProbes[clusterProbes.ClusterName] in - // updateMySQLClusterProbes(). - return attemptWriteProbes(clusterProbes) - // not the leader (primary tablet)? Then no more work for us. - } - // The primary tablet is also in charge of collecting the shard's metrics - ctx, cancel := context.WithTimeout(ctx, mysqlRefreshInterval) - defer cancel() + throttler.metricThresholds.Set(inventoryPrefix+metricName.String(), math.Float64frombits(threshold), cache.DefaultExpiration) + } + throttler.convergeMetricThresholds() + clusterSettingsCopy := *mysqlSettings + // config may dynamically change, but internal structure (config.Settings().MySQLStore.Clusters in our case) + // is immutable and can only be _replaced_. Hence, it's safe to read in a goroutine: + collect := func() error { + clusterProbes := &base.ClusterProbes{ + IgnoreHostsCount: clusterSettingsCopy.IgnoreHostsCount, + TabletProbes: base.NewProbes(), + } + // self tablet + addProbe(throttler.tabletAlias, nil, base.SelfScope, &clusterSettingsCopy, clusterProbes.TabletProbes) + if !throttler.isLeader.Load() { + // This tablet may have used to be the primary, but it isn't now. It may have a recollection + // of previous clusters it used to probe. It may have recollection of specific probes for such clusters. + // This now ensures any existing cluster probes are overridden with an empty list of probes. + // `clusterProbes` was created above as empty, and identifiable via `scope`. This will in turn + // be used to overwrite throttler.inventory.ClustersProbes[clusterProbes.scope] in + // updateClusterProbes(). + return attemptWriteProbes(clusterProbes) + // not the leader (primary tablet)? Then no more work for us. + } + // The primary tablet is also in charge of collecting the shard's metrics + ctx, cancel := context.WithTimeout(ctx, inventoryRefreshInterval) + defer cancel() - tabletAliases, err := throttler.ts.FindAllTabletAliasesInShard(ctx, throttler.keyspace, throttler.shard) + tabletAliases, err := throttler.ts.FindAllTabletAliasesInShard(ctx, throttler.keyspace, throttler.shard) + if err != nil { + return err + } + for _, tabletAlias := range tabletAliases { + tablet, err := throttler.ts.GetTablet(ctx, tabletAlias) if err != nil { return err } - for _, tabletAlias := range tabletAliases { - tablet, err := throttler.ts.GetTablet(ctx, tabletAlias) - if err != nil { - return err - } - if throttler.throttleTabletTypesMap[tablet.Type] { - addProbe(topoproto.TabletAliasString(tabletAlias), tablet.Tablet, clusterName, &clusterSettingsCopy, clusterProbes.TabletProbes) - } + if throttler.throttleTabletTypesMap[tablet.Type] { + addProbe(topoproto.TabletAliasString(tabletAlias), tablet.Tablet, base.ShardScope, &clusterSettingsCopy, clusterProbes.TabletProbes) } - return attemptWriteProbes(clusterProbes) } - go func() { - if err := collect(); err != nil { - log.Errorf("refreshMySQLInventory: %+v", err) - } - }() + + return attemptWriteProbes(clusterProbes) } + go func() { + if err := collect(); err != nil { + log.Errorf("refreshInventory: %+v", err) + } + }() return nil } // synchronous update of inventory -func (throttler *Throttler) updateMySQLClusterProbes(ctx context.Context, clusterProbes *mysql.ClusterProbes) error { - throttler.mysqlInventory.ClustersProbes[clusterProbes.ClusterName] = clusterProbes.TabletProbes - throttler.mysqlInventory.IgnoreHostsCount[clusterProbes.ClusterName] = clusterProbes.IgnoreHostsCount - throttler.mysqlInventory.IgnoreHostsThreshold[clusterProbes.ClusterName] = clusterProbes.IgnoreHostsThreshold +func (throttler *Throttler) updateClusterProbes(ctx context.Context, clusterProbes *base.ClusterProbes) error { + throttler.inventory.ClustersProbes = clusterProbes.TabletProbes + throttler.inventory.IgnoreHostsCount = clusterProbes.IgnoreHostsCount + throttler.inventory.IgnoreHostsThreshold = clusterProbes.IgnoreHostsThreshold return nil } +func (throttler *Throttler) metricNameUsedAsDefault() base.MetricName { + if throttler.GetCustomMetricsQuery() == "" { + return base.LagMetricName + } + return base.CustomMetricName +} + // synchronous aggregation of collected data -func (throttler *Throttler) aggregateMySQLMetrics(ctx context.Context) error { - for clusterName, probes := range throttler.mysqlInventory.ClustersProbes { - metricName := fmt.Sprintf("mysql/%s", clusterName) - ignoreHostsCount := throttler.mysqlInventory.IgnoreHostsCount[clusterName] - ignoreHostsThreshold := throttler.mysqlInventory.IgnoreHostsThreshold[clusterName] - aggregatedMetric := aggregateMySQLProbes(ctx, probes, clusterName, throttler.mysqlInventory.TabletMetrics, ignoreHostsCount, throttler.configSettings.Stores.MySQL.IgnoreDialTCPErrors, ignoreHostsThreshold) - throttler.aggregatedMetrics.Set(metricName, aggregatedMetric, cache.DefaultExpiration) +func (throttler *Throttler) aggregateMetrics() error { + metricNameUsedAsDefault := throttler.metricNameUsedAsDefault() + aggregateTabletsMetrics := func(scope base.Scope, metricName base.MetricName, tabletResultsMap base.TabletResultMap) { + ignoreHostsCount := throttler.inventory.IgnoreHostsCount + ignoreHostsThreshold := throttler.inventory.IgnoreHostsThreshold + ignoreDialTCPErrors := throttler.configSettings.MySQLStore.IgnoreDialTCPErrors + + aggregatedMetric := base.AggregateTabletMetricResults(metricName, tabletResultsMap, ignoreHostsCount, ignoreDialTCPErrors, ignoreHostsThreshold) + aggregatedMetricName := metricName.AggregatedName(scope) + throttler.aggregatedMetrics.Set(aggregatedMetricName, aggregatedMetric, cache.DefaultExpiration) + if metricName == metricNameUsedAsDefault { + throttler.aggregatedMetrics.Set(base.DefaultMetricName.AggregatedName(scope), aggregatedMetric, cache.DefaultExpiration) + } + } + for _, metricName := range base.KnownMetricNames { + if metricName == base.DefaultMetricName { + // "default metric" is for backwards compatibility with v20, which does not support multi-metrics. + // We do not measure "default metric". Instead, we aggregate _actual_ metrics, and decide which one + // is to be stored as "default" + continue + } + selfResultsMap, shardResultsMap := throttler.inventory.TabletMetrics.Split(throttler.tabletAlias) + aggregateTabletsMetrics(base.SelfScope, metricName, selfResultsMap) + aggregateTabletsMetrics(base.ShardScope, metricName, shardResultsMap) } return nil } -func (throttler *Throttler) getNamedMetric(metricName string) base.MetricResult { - if metricResultVal, found := throttler.aggregatedMetrics.Get(metricName); found { +func (throttler *Throttler) getAggregatedMetric(aggregatedName string) base.MetricResult { + if metricResultVal, found := throttler.aggregatedMetrics.Get(aggregatedName); found { return metricResultVal.(base.MetricResult) } return base.NoSuchMetric } -func (throttler *Throttler) getMySQLClusterMetrics(ctx context.Context, clusterName string) (base.MetricResult, float64) { - if thresholdVal, found := throttler.mysqlClusterThresholds.Get(clusterName); found { - threshold, _ := thresholdVal.(float64) - metricName := fmt.Sprintf("mysql/%s", clusterName) - return throttler.getNamedMetric(metricName), threshold +func (throttler *Throttler) getScopedMetric(scope base.Scope, metricName base.MetricName) (base.MetricResult, float64) { + thresholdVal, found := throttler.metricThresholds.Get(metricName.String()) + if !found { + return base.NoSuchMetric, 0 } + threshold, _ := thresholdVal.(float64) + aggregatedName := metricName.AggregatedName(scope) + return throttler.getAggregatedMetric(aggregatedName), threshold +} - return base.NoSuchMetric, 0 +func (throttler *Throttler) metricThresholdsSnapshot() map[string]float64 { + snapshot := make(map[string]float64) + for key, value := range throttler.metricThresholds.Items() { + threshold, _ := value.Object.(float64) + snapshot[key] = threshold + } + return snapshot +} + +func (throttler *Throttler) appCheckedMetricsSnapshot() map[string]string { + snapshot := make(map[string]string) + for key, item := range throttler.appCheckedMetrics.Items() { + var metricNames base.MetricNames + switch val := item.Object.(type) { + case base.MetricNames: + metricNames = val + case []base.MetricName: + metricNames = val + } + snapshot[key] = metricNames.String() + } + return snapshot } func (throttler *Throttler) aggregatedMetricsSnapshot() map[string]base.MetricResult { @@ -1066,7 +1329,7 @@ func (throttler *Throttler) expireThrottledApps() { now := time.Now() for appName, item := range throttler.throttledApps.Items() { appThrottle := item.Object.(*base.AppThrottle) - if appThrottle.ExpireAt.Before(now) { + if !appThrottle.ExpireAt.After(now) { throttler.UnthrottleApp(appName) } } @@ -1096,7 +1359,7 @@ func (throttler *Throttler) ThrottleApp(appName string, expireAt time.Time, rati } appThrottle = base.NewAppThrottle(appName, expireAt, ratio, exempt) } - if now.Before(appThrottle.ExpireAt) { + if appThrottle.ExpireAt.After(now) { throttler.throttledApps.Set(appName, appThrottle, cache.DefaultExpiration) } else { throttler.UnthrottleApp(appName) @@ -1116,6 +1379,7 @@ func (throttler *Throttler) UnthrottleApp(appName string) (appThrottle *base.App // Assuming an app is throttled to some extend, it will randomize the result based // on the throttle ratio func (throttler *Throttler) IsAppThrottled(appName string) bool { + appFound := false isSingleAppNameThrottled := func(singleAppName string) bool { object, found := throttler.throttledApps.Get(singleAppName) if !found { @@ -1123,9 +1387,12 @@ func (throttler *Throttler) IsAppThrottled(appName string) bool { } appThrottle := object.(*base.AppThrottle) if !appThrottle.ExpireAt.After(time.Now()) { - // throttling cleanup hasn't purged yet, but it is expired + // throttling cleanup hasn't purged yet, but it is expired. return false } + // From this point on, we consider that this app has some throttling configuration + // of any sort. + appFound = true if appThrottle.Exempt { return false } @@ -1138,7 +1405,7 @@ func (throttler *Throttler) IsAppThrottled(appName string) bool { if isSingleAppNameThrottled(appName) { return true } - for _, singleAppName := range strings.Split(appName, ":") { + for _, singleAppName := range throttlerapp.Name(appName).SplitStrings() { if singleAppName == "" { continue } @@ -1146,6 +1413,17 @@ func (throttler *Throttler) IsAppThrottled(appName string) bool { return true } } + // If app was found then there was some explicit throttle instruction for the app, and the app + // passed the test. + if appFound { + return false + } + // If the app was not found, ie no specific throttle instruction was found for the app, then + // the app should also consider the case where the "all" app is throttled. + if isSingleAppNameThrottled(throttlerapp.AllName.String()) { + // Means the "all" app is throttled. This is a special case, and it means "all apps are throttled" + return true + } return false } @@ -1172,7 +1450,7 @@ func (throttler *Throttler) IsAppExempted(appName string) bool { if isSingleAppNameExempted(appName) { return true } - for _, singleAppName := range strings.Split(appName, ":") { + for _, singleAppName := range throttlerapp.Name(appName).SplitStrings() { if singleAppName == "" { continue } @@ -1180,6 +1458,11 @@ func (throttler *Throttler) IsAppExempted(appName string) bool { return true } } + + if isSingleAppNameExempted(throttlerapp.AllName.String()) && !throttler.IsAppThrottled(appName) { + return true + } + return false } @@ -1195,17 +1478,17 @@ func (throttler *Throttler) ThrottledAppsMap() (result map[string](*base.AppThro } // markRecentApp takes note that an app has just asked about throttling, making it "recent" -func (throttler *Throttler) markRecentApp(appName string, remoteAddr string) { - recentAppKey := fmt.Sprintf("%s/%s", appName, remoteAddr) - throttler.recentApps.Set(recentAppKey, time.Now(), cache.DefaultExpiration) +func (throttler *Throttler) markRecentApp(appName string, statusCode int) { + recentApp := base.NewRecentApp(appName, statusCode) + throttler.recentApps.Set(appName, recentApp, cache.DefaultExpiration) } -// RecentAppsMap returns a (copy) map of apps which checked for throttling recently -func (throttler *Throttler) RecentAppsMap() (result map[string](*base.RecentApp)) { +// recentAppsSnapshot returns a (copy) map of apps which checked for throttling recently +func (throttler *Throttler) recentAppsSnapshot() (result map[string](*base.RecentApp)) { result = make(map[string](*base.RecentApp)) for recentAppKey, item := range throttler.recentApps.Items() { - recentApp := base.NewRecentApp(item.Object.(time.Time)) + recentApp := item.Object.(*base.RecentApp) result[recentAppKey] = recentApp } return result @@ -1244,8 +1527,8 @@ func (throttler *Throttler) AppRequestMetricResult(ctx context.Context, appName return metricResultFunc() } -// checkStore checks the aggregated value of given MySQL store -func (throttler *Throttler) checkStore(ctx context.Context, appName string, storeName string, remoteAddr string, flags *CheckFlags) (checkResult *CheckResult) { +// checkScope checks the aggregated value of given store +func (throttler *Throttler) checkScope(ctx context.Context, appName string, scope base.Scope, metricNames base.MetricNames, flags *CheckFlags) (checkResult *CheckResult) { if !throttler.IsRunning() { return okMetricCheckResult } @@ -1255,7 +1538,43 @@ func (throttler *Throttler) checkStore(ctx context.Context, appName string, stor return okMetricCheckResult } - checkResult = throttler.check.Check(ctx, appName, "mysql", storeName, remoteAddr, flags) + if len(metricNames) == 0 { + // No explicit metrics requested. + // Get the metric names mappd to the given app + for _, appToken := range throttlerapp.Name(appName).SplitStrings() { + if val, found := throttler.appCheckedMetrics.Get(appToken); found { + // Due to golang type system, it's possible that we put in a base.MetricNames and get back a []base.MetricName. + // We allow both forms, which are technically the same type. + switch val := val.(type) { + case base.MetricNames: + metricNames = append(metricNames, val...) + case []base.MetricName: + metricNames = append(metricNames, val...) + } + } + } + } + if len(metricNames) == 0 && !throttlerapp.AllName.Equals(appName) { + // No specific metrics mapped to this app. Are there specific metrics + // mapped to the "all" app? + if val, found := throttler.appCheckedMetrics.Get(throttlerapp.AllName.String()); found { + switch val := val.(type) { + case base.MetricNames: + metricNames = val + case []base.MetricName: + metricNames = val + } + } + } + if throttlerapp.VitessName.Equals(appName) { + // "vitess" always checks all metrics, irrespective of what is mapped. + metricNames = base.KnownMetricNames + } + if len(metricNames) == 0 { + // Nothing mapped? For backwards compatibility and as default, we use the "default" metric. + metricNames = base.MetricNames{throttler.metricNameUsedAsDefault()} + } + checkResult = throttler.check.Check(ctx, appName, scope, metricNames, flags) shouldRequestHeartbeats := !flags.SkipRequestHeartbeats if throttlerapp.VitessName.Equals(appName) { @@ -1274,7 +1593,6 @@ func (throttler *Throttler) checkStore(ctx context.Context, appName string, stor // We mark the fact that someone just made a check. If this is a REPLICA or RDONLY tables, this will be reported back // to the PRIMARY so that it knows it must renew the heartbeat lease. checkResult.RecentlyChecked = true - statsThrottlerRecentlyChecked.Add(1) } if !checkResult.RecentlyChecked { checkResult.RecentlyChecked = throttler.recentlyChecked() @@ -1283,29 +1601,34 @@ func (throttler *Throttler) checkStore(ctx context.Context, appName string, stor return checkResult } -// checkShard checks the health of the shard, and runs on the primary tablet only -func (throttler *Throttler) checkShard(ctx context.Context, appName string, remoteAddr string, flags *CheckFlags) (checkResult *CheckResult) { - return throttler.checkStore(ctx, appName, shardStoreName, remoteAddr, flags) +// Check runs a check by requested check type +func (throttler *Throttler) Check(ctx context.Context, appName string, metricNames base.MetricNames, flags *CheckFlags) (checkResult *CheckResult) { + scope := base.UndefinedScope + if flags != nil { + scope = flags.Scope + } + if scope == base.ShardScope && throttler.checkAsCheckSelf.Load() { + scope = base.SelfScope + } + return throttler.checkScope(ctx, appName, scope, metricNames, flags) } -// CheckSelf is checks the mysql/self metric, and is available on each tablet -func (throttler *Throttler) checkSelf(ctx context.Context, appName string, remoteAddr string, flags *CheckFlags) (checkResult *CheckResult) { - return throttler.checkStore(ctx, appName, selfStoreName, remoteAddr, flags) +func (throttler *Throttler) MetricName(s string) base.MetricName { + if s == "" { + return base.DefaultMetricName + } + return base.MetricName(s) } -// CheckByType runs a check by requested check type -func (throttler *Throttler) CheckByType(ctx context.Context, appName string, remoteAddr string, flags *CheckFlags, checkType ThrottleCheckType) (checkResult *CheckResult) { - switch checkType { - case ThrottleCheckSelf: - return throttler.checkSelf(ctx, appName, remoteAddr, flags) - case ThrottleCheckPrimaryWrite: - if throttler.checkAsCheckSelf.Load() { - return throttler.checkSelf(ctx, appName, remoteAddr, flags) - } - return throttler.checkShard(ctx, appName, remoteAddr, flags) - default: - return invalidCheckTypeCheckResult +func (throttler *Throttler) MetricNames(s []string) base.MetricNames { + result := make(base.MetricNames, len(s)) + for i, metricName := range s { + result[i] = throttler.MetricName(metricName) } + if len(s) == 0 { + result = append(result, base.DefaultMetricName) + } + return result } // Status exports a status breakdown @@ -1314,16 +1637,22 @@ func (throttler *Throttler) Status() *ThrottlerStatus { Keyspace: throttler.keyspace, Shard: throttler.shard, - IsLeader: throttler.isLeader.Load(), - IsOpen: throttler.isOpen.Load(), - IsEnabled: throttler.isEnabled.Load(), - IsDormant: throttler.isDormant(), - IsRecentlyChecked: throttler.recentlyChecked(), + IsLeader: throttler.isLeader.Load(), + IsOpen: throttler.isOpen.Load(), + IsEnabled: throttler.isEnabled.Load(), + IsDormant: throttler.isDormant(), + RecentlyChecked: throttler.recentlyChecked(), - Query: throttler.GetMetricsQuery(), - Threshold: throttler.GetMetricsThreshold(), + Query: throttler.GetMetricsQuery(), + CustomQuery: throttler.GetCustomMetricsQuery(), + Threshold: throttler.GetMetricsThreshold(), + MetricNameUsedAsDefault: throttler.metricNameUsedAsDefault().String(), AggregatedMetrics: throttler.aggregatedMetricsSnapshot(), + MetricsThresholds: throttler.metricThresholdsSnapshot(), MetricsHealth: throttler.metricsHealthSnapshot(), + ThrottledApps: throttler.ThrottledApps(), + AppCheckedMetrics: throttler.appCheckedMetricsSnapshot(), + RecentApps: throttler.recentAppsSnapshot(), } } diff --git a/go/vt/vttablet/tabletserver/throttle/throttler_test.go b/go/vt/vttablet/tabletserver/throttle/throttler_test.go index a745ca66fe7..6363143fd43 100644 --- a/go/vt/vttablet/tabletserver/throttle/throttler_test.go +++ b/go/vt/vttablet/tabletserver/throttle/throttler_test.go @@ -19,6 +19,7 @@ package throttle import ( "context" "fmt" + "math" "net/http" "sync" "sync/atomic" @@ -28,13 +29,15 @@ import ( "github.com/patrickmn/go-cache" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "golang.org/x/exp/maps" + "vitess.io/vitess/go/protoutil" "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/vtenv" "vitess.io/vitess/go/vt/vttablet/tabletserver/connpool" "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" + "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/config" - "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/mysql" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/throttlerapp" "vitess.io/vitess/go/vt/vttablet/tmclient" @@ -42,13 +45,62 @@ import ( topodatapb "vitess.io/vitess/go/vt/proto/topodata" ) +var ( + selfMetrics = base.ThrottleMetrics{ + base.LagMetricName: &base.ThrottleMetric{ + Scope: base.SelfScope, + Alias: "", + Value: 0.3, + Err: nil, + }, + base.ThreadsRunningMetricName: &base.ThrottleMetric{ + Scope: base.SelfScope, + Alias: "", + Value: 26, + Err: nil, + }, + base.CustomMetricName: &base.ThrottleMetric{ + Scope: base.SelfScope, + Alias: "", + Value: 17, + Err: nil, + }, + base.LoadAvgMetricName: &base.ThrottleMetric{ + Scope: base.SelfScope, + Alias: "", + Value: 2.718, + Err: nil, + }, + } + replicaMetrics = map[string]*MetricResult{ + base.LagMetricName.String(): { + StatusCode: http.StatusOK, + Value: 0.9, + }, + base.ThreadsRunningMetricName.String(): { + StatusCode: http.StatusOK, + Value: 13, + }, + base.CustomMetricName.String(): { + StatusCode: http.StatusOK, + Value: 14, + }, + base.LoadAvgMetricName.String(): { + StatusCode: http.StatusOK, + Value: 5.1, + }, + } +) + const ( waitForProbesTimeout = 30 * time.Second + testAppName = throttlerapp.TestingName ) type fakeTMClient struct { tmclient.TabletManagerClient appNames []string + v20 atomic.Bool // help validate v20 backwards compatibility mu sync.Mutex } @@ -59,10 +111,22 @@ func (c *fakeTMClient) Close() { func (c *fakeTMClient) CheckThrottler(ctx context.Context, tablet *topodatapb.Tablet, request *tabletmanagerdatapb.CheckThrottlerRequest) (*tabletmanagerdatapb.CheckThrottlerResponse, error) { resp := &tabletmanagerdatapb.CheckThrottlerResponse{ StatusCode: http.StatusOK, - Value: 0, + Value: 0.339, Threshold: 1, RecentlyChecked: false, } + if !c.v20.Load() { + resp.Metrics = make(map[string]*tabletmanagerdatapb.CheckThrottlerResponse_Metric) + for name, metric := range replicaMetrics { + resp.Metrics[name] = &tabletmanagerdatapb.CheckThrottlerResponse_Metric{ + Name: name, + StatusCode: int32(metric.StatusCode), + Value: metric.Value, + Threshold: metric.Threshold, + Message: metric.Message, + } + } + } c.mu.Lock() defer c.mu.Unlock() c.appNames = append(c.appNames, request.AppName) @@ -98,9 +162,9 @@ func (ts *FakeTopoServer) GetTablet(ctx context.Context, alias *topodatapb.Table func (ts *FakeTopoServer) FindAllTabletAliasesInShard(ctx context.Context, keyspace, shard string) ([]*topodatapb.TabletAlias, error) { aliases := []*topodatapb.TabletAlias{ - {Cell: "fakezone1", Uid: 100}, - {Cell: "fakezone2", Uid: 101}, - {Cell: "fakezone3", Uid: 103}, + {Cell: "fakezone0", Uid: 100}, + {Cell: "fakezone1", Uid: 101}, + {Cell: "fakezone2", Uid: 102}, } return aliases, nil } @@ -122,68 +186,124 @@ func (w *FakeHeartbeatWriter) Requests() int64 { return w.requests.Load() } -func newTestThrottler() *Throttler { - metricsQuery := "select 1" - configSettings := config.NewConfigurationSettings() - configSettings.Stores.MySQL.Clusters = map[string]*config.MySQLClusterConfigurationSettings{ - selfStoreName: {}, - shardStoreName: {}, +func init() { + for metricName, metric := range selfMetrics { + metric.Name = metricName } - for _, s := range configSettings.Stores.MySQL.Clusters { - s.MetricQuery = metricsQuery - s.ThrottleThreshold = &atomic.Uint64{} - s.ThrottleThreshold.Store(1) +} + +func waitForMetricsToBeCollected(t *testing.T, ctx context.Context, throttler *Throttler) { + ticker := time.NewTicker(100 * time.Millisecond) + for { + foundAll := true + aggr := throttler.aggregatedMetricsSnapshot() + for _, metric := range base.KnownMetricNames { + if _, ok := aggr[metric.AggregatedName(base.SelfScope)]; !ok { + foundAll = false + break + } + if _, ok := aggr[metric.AggregatedName(base.ShardScope)]; !ok { + foundAll = false + break + } + } + if foundAll { + return + } + select { + case <-ctx.Done(): + assert.Fail(t, "timed out waiting for metrics to be collected") + return + case <-ticker.C: + } } +} +func sleepTillThresholdApplies() { + time.Sleep(time.Second) +} + +func TestGetAggregatedMetricName(t *testing.T) { + assert.Equal(t, "self", base.DefaultMetricName.AggregatedName(base.SelfScope)) + assert.Equal(t, "self/lag", base.LagMetricName.AggregatedName(base.SelfScope)) + assert.Equal(t, "shard/loadavg", base.LoadAvgMetricName.AggregatedName(base.ShardScope)) +} + +func newTestThrottler() *Throttler { + metricsQuery := "select 1" + env := tabletenv.NewEnv(vtenv.NewTestEnv(), nil, "TabletServerTest") throttler := &Throttler{ - mysqlClusterProbesChan: make(chan *mysql.ClusterProbes), - mysqlClusterThresholds: cache.New(cache.NoExpiration, 0), - heartbeatWriter: &FakeHeartbeatWriter{}, - ts: &FakeTopoServer{}, - mysqlInventory: mysql.NewInventory(), - pool: connpool.NewPool(env, "ThrottlerPool", tabletenv.ConnPoolConfig{}), - tabletTypeFunc: func() topodatapb.TabletType { return topodatapb.TabletType_PRIMARY }, - overrideTmClient: &fakeTMClient{}, + clusterProbesChan: make(chan *base.ClusterProbes), + heartbeatWriter: &FakeHeartbeatWriter{}, + ts: &FakeTopoServer{}, + inventory: base.NewInventory(), + pool: connpool.NewPool(env, "ThrottlerPool", tabletenv.ConnPoolConfig{}), + tabletTypeFunc: func() topodatapb.TabletType { return topodatapb.TabletType_PRIMARY }, + overrideTmClient: &fakeTMClient{}, } - throttler.configSettings = configSettings - throttler.mysqlThrottleMetricChan = make(chan *mysql.MySQLThrottleMetric) - throttler.mysqlInventoryChan = make(chan *mysql.Inventory, 1) - throttler.mysqlClusterProbesChan = make(chan *mysql.ClusterProbes) + throttler.metricsQuery.Store(metricsQuery) + throttler.MetricsThreshold.Store(math.Float64bits(0.75)) + throttler.configSettings = config.NewConfigurationSettings() + throttler.initConfig() + throttler.throttleMetricChan = make(chan *base.ThrottleMetric) + throttler.clusterProbesChan = make(chan *base.ClusterProbes) throttler.throttlerConfigChan = make(chan *topodatapb.ThrottlerConfig) - throttler.mysqlInventory = mysql.NewInventory() + throttler.serialFuncChan = make(chan func()) + throttler.inventory = base.NewInventory() throttler.throttledApps = cache.New(cache.NoExpiration, 0) - throttler.mysqlClusterThresholds = cache.New(cache.NoExpiration, 0) + throttler.metricThresholds = cache.New(cache.NoExpiration, 0) throttler.aggregatedMetrics = cache.New(10*aggregatedMetricsExpiration, 0) throttler.recentApps = cache.New(recentAppsExpiration, 0) throttler.metricsHealth = cache.New(cache.NoExpiration, 0) - throttler.metricsQuery.Store(metricsQuery) + throttler.appCheckedMetrics = cache.New(cache.NoExpiration, 0) throttler.initThrottleTabletTypes() throttler.check = NewThrottlerCheck(throttler) // High contention & racy intervals: throttler.leaderCheckInterval = 10 * time.Millisecond - throttler.mysqlCollectInterval = 10 * time.Millisecond - throttler.mysqlDormantCollectInterval = 10 * time.Millisecond - throttler.mysqlRefreshInterval = 10 * time.Millisecond - throttler.mysqlAggregateInterval = 10 * time.Millisecond + throttler.activeCollectInterval = 10 * time.Millisecond + throttler.dormantCollectInterval = 10 * time.Millisecond + throttler.inventoryRefreshInterval = 10 * time.Millisecond + throttler.metricsAggregateInterval = 10 * time.Millisecond throttler.throttledAppsSnapshotInterval = 10 * time.Millisecond throttler.dormantPeriod = 5 * time.Second throttler.recentCheckDormantDiff = int64(throttler.dormantPeriod / recentCheckRateLimiterInterval) throttler.recentCheckDiff = int64(3 * time.Second / recentCheckRateLimiterInterval) - throttler.readSelfThrottleMetric = func(ctx context.Context, p *mysql.Probe) *mysql.MySQLThrottleMetric { - return &mysql.MySQLThrottleMetric{ - ClusterName: selfStoreName, - Alias: "", - Value: 1, - Err: nil, + throttler.readSelfThrottleMetrics = func(ctx context.Context) base.ThrottleMetrics { + for _, metric := range selfMetrics { + go func() { + select { + case <-ctx.Done(): + case throttler.throttleMetricChan <- metric: + } + }() } + return selfMetrics } + throttler.ThrottleApp(throttlerapp.TestingAlwaysThrottlerName.String(), time.Now().Add(time.Hour*24*365*10), DefaultThrottleRatio, false) return throttler } +// runSerialFunction runs the given function inside the throttler's serial and goroutine-safe main `select` loop. +// This function returns a channel that is populated when the input function is completed. Callers of this +// function should read from the channel if they want to block until the function is completed, or that could +// ignore the channel if they just want to fire-and-forget the function. +func runSerialFunction(t *testing.T, ctx context.Context, throttler *Throttler, f func(context.Context)) (done chan any) { + done = make(chan any, 1) + select { + case throttler.serialFuncChan <- func() { + f(ctx) + done <- true + }: + case <-ctx.Done(): + assert.FailNow(t, ctx.Err().Error(), "waiting in runSerialFunction") + } + return done +} + func TestInitThrottler(t *testing.T) { throttler := newTestThrottler() assert.Equal(t, 5*time.Second, throttler.dormantPeriod) @@ -191,33 +311,562 @@ func TestInitThrottler(t *testing.T) { assert.EqualValues(t, 3, throttler.recentCheckDiff) } +func TestApplyThrottlerConfig(t *testing.T) { + ctx := context.Background() // for development, replace with ctx := utils.LeakCheckContext(t) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + timeNow := time.Now() + throttler := newTestThrottler() + throttlerConfig := &topodatapb.ThrottlerConfig{ + Enabled: false, + Threshold: 14, + ThrottledApps: map[string]*topodatapb.ThrottledAppRule{ + throttlerapp.OnlineDDLName.String(): { + Name: throttlerapp.OnlineDDLName.String(), + Ratio: 0.5, + ExpiresAt: protoutil.TimeToProto(timeNow.Add(time.Hour)), + Exempt: false, + }, + throttlerapp.TableGCName.String(): { + Name: throttlerapp.TableGCName.String(), + ExpiresAt: protoutil.TimeToProto(timeNow.Add(time.Hour)), + Exempt: true, + }, + throttlerapp.VPlayerName.String(): { + Name: throttlerapp.VPlayerName.String(), + Ratio: DefaultThrottleRatio, + ExpiresAt: protoutil.TimeToProto(timeNow), // instantly expires + Exempt: false, + }, + }, + AppCheckedMetrics: map[string]*topodatapb.ThrottlerConfig_MetricNames{ + "app1": {Names: []string{"lag", "threads_running"}}, + throttlerapp.OnlineDDLName.String(): {Names: []string{"loadavg"}}, + }, + MetricThresholds: map[string]float64{ + "threads_running": 3.0, + }, + } + assert.Equal(t, 0.75, throttler.GetMetricsThreshold()) + throttler.appCheckedMetrics.Set("app1", base.MetricNames{base.ThreadsRunningMetricName}, cache.DefaultExpiration) + throttler.appCheckedMetrics.Set("app2", base.MetricNames{base.ThreadsRunningMetricName}, cache.DefaultExpiration) + throttler.appCheckedMetrics.Set("app3", base.MetricNames{base.ThreadsRunningMetricName}, cache.DefaultExpiration) + runThrottler(t, ctx, throttler, 10*time.Second, func(t *testing.T, ctx context.Context) { + defer cancel() // early termination + assert.True(t, throttler.IsEnabled()) + assert.Equal(t, 1, throttler.throttledApps.ItemCount(), "expecting always-throttled-app: %v", maps.Keys(throttler.throttledApps.Items())) + throttler.applyThrottlerConfig(ctx, throttlerConfig) + }) + + sleepTillThresholdApplies() + assert.Equal(t, 3, throttler.throttledApps.ItemCount(), "expecting online-ddl, tablegc, and always-throttled-app: %v", maps.Keys(throttler.throttledApps.Items())) + assert.False(t, throttler.IsEnabled()) + assert.Equal(t, float64(14), throttler.GetMetricsThreshold()) + assert.Equal(t, 2, throttler.appCheckedMetrics.ItemCount()) + t.Run("checked metrics", func(t *testing.T) { + { + value, ok := throttler.appCheckedMetrics.Get("app1") + assert.True(t, ok) + names := value.(base.MetricNames) + assert.Equal(t, base.MetricNames{base.LagMetricName, base.ThreadsRunningMetricName}, names) + } + { + value, ok := throttler.appCheckedMetrics.Get(throttlerapp.OnlineDDLName.String()) + assert.True(t, ok) + names := value.(base.MetricNames) + assert.Equal(t, base.MetricNames{base.LoadAvgMetricName}, names) + } + }) + t.Run("metric thresholds", func(t *testing.T) { + { + val, ok := throttler.metricThresholds.Get("lag") + require.True(t, ok) + assert.Equal(t, float64(0.75), val) + } + { + val, ok := throttler.metricThresholds.Get("threads_running") + require.True(t, ok) + assert.Equal(t, float64(3.0), val) + } + { + val, ok := throttler.metricThresholds.Get("loadavg") + require.True(t, ok) + assert.Equal(t, float64(1.0), val) + } + }) +} + +// TestApplyThrottlerConfigMetricThresholds applies a specific 'lag' metric threshold, +// and validates that it overrides the default threshold. +func TestApplyThrottlerConfigMetricThresholds(t *testing.T) { + ctx := context.Background() // for development, replace with ctx := utils.LeakCheckContext(t) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + throttler := newTestThrottler() + runThrottler(t, ctx, throttler, 10*time.Second, func(t *testing.T, ctx context.Context) { + defer cancel() // early termination + assert.True(t, throttler.IsEnabled()) + + flags := &CheckFlags{ + Scope: base.SelfScope, + SkipRequestHeartbeats: true, + MultiMetricsEnabled: true, + } + t.Run("check before apply", func(t *testing.T) { + checkResult := throttler.Check(ctx, testAppName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.3, checkResult.Value) // self lag value + assert.EqualValues(t, http.StatusOK, checkResult.StatusCode) + assert.Len(t, checkResult.Metrics, 1) + }) + t.Run("apply low threshold", func(t *testing.T) { + assert.Equal(t, 0.75, throttler.GetMetricsThreshold()) + throttlerConfig := &topodatapb.ThrottlerConfig{ + Enabled: true, + Threshold: 0.0033, + } + throttler.applyThrottlerConfig(ctx, throttlerConfig) + assert.Equal(t, 0.0033, throttler.GetMetricsThreshold()) + }) + t.Run("check low threshold", func(t *testing.T) { + sleepTillThresholdApplies() + { + _, ok := throttler.metricThresholds.Get("config/lag") + assert.False(t, ok) + } + assert.Equal(t, float64(0.0033), throttler.GetMetricsThreshold()) + checkResult := throttler.Check(ctx, testAppName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.3, checkResult.Value, "unexpected result: %+v", checkResult) // self lag value + assert.NotEqualValues(t, http.StatusOK, checkResult.StatusCode, "unexpected result: %+v", checkResult) + assert.Len(t, checkResult.Metrics, 1) + }) + t.Run("apply low threshold but high 'lag' override", func(t *testing.T) { + throttlerConfig := &topodatapb.ThrottlerConfig{ + Enabled: true, + Threshold: 0.0033, + MetricThresholds: map[string]float64{ + "lag": 4444.0, + }, + } + throttler.applyThrottlerConfig(ctx, throttlerConfig) + }) + t.Run("check with high 'lag' threshold", func(t *testing.T) { + sleepTillThresholdApplies() + { + val, ok := throttler.metricThresholds.Get("config/lag") + require.True(t, ok) + assert.Equal(t, float64(4444), val) + } + checkResult := throttler.Check(ctx, testAppName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.3, checkResult.Value, "unexpected result: %+v", checkResult) // self lag value + assert.EqualValues(t, http.StatusOK, checkResult.StatusCode, "unexpected result: %+v", checkResult) + assert.Len(t, checkResult.Metrics, 1) + }) + }) + + assert.False(t, throttler.IsEnabled()) + assert.Equal(t, float64(0.0033), throttler.GetMetricsThreshold()) + t.Run("metric thresholds", func(t *testing.T) { + { + val, ok := throttler.metricThresholds.Get("config/lag") + require.True(t, ok) + assert.Equal(t, float64(4444), val) + } + { + val, ok := throttler.metricThresholds.Get("inventory/lag") + require.True(t, ok) + assert.Equal(t, float64(0.0033), val) + } + { + val, ok := throttler.metricThresholds.Get("lag") + require.True(t, ok) + assert.Equal(t, float64(4444), val) + } + }) +} + +// TestApplyThrottlerConfigAppCheckedMetrics applies different metrics to the "test" app and checks the result +func TestApplyThrottlerConfigAppCheckedMetrics(t *testing.T) { + ctx := context.Background() // for development, replace with ctx := utils.LeakCheckContext(t) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + throttler := newTestThrottler() + runThrottler(t, ctx, throttler, 10*time.Second, func(t *testing.T, ctx context.Context) { + defer cancel() // early termination + + assert.True(t, throttler.IsEnabled()) + aggr := throttler.aggregatedMetricsSnapshot() + assert.Equalf(t, 2*len(base.KnownMetricNames), len(aggr), "aggregated: %+v", aggr) // "self" and "shard", per known metric + assert.Equal(t, 2*len(base.KnownMetricNames), throttler.aggregatedMetrics.ItemCount()) // flushed upon Disable() + for _, metric := range []string{"self", "shard", "self/lag", "shard/lag", "self/loadavg", "shard/loadavg"} { + _, ok := aggr[metric] + assert.True(t, ok, "missing metric: %s", metric) + } + flags := &CheckFlags{ + SkipRequestHeartbeats: true, + MultiMetricsEnabled: true, + } + throttlerConfig := &topodatapb.ThrottlerConfig{ + Enabled: true, + MetricThresholds: map[string]float64{}, + AppCheckedMetrics: map[string]*topodatapb.ThrottlerConfig_MetricNames{}, + } + + t.Run("check before apply", func(t *testing.T) { + checkResult := throttler.Check(ctx, testAppName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.9, checkResult.Value) // shard lag value + assert.NotEqualValues(t, http.StatusOK, checkResult.StatusCode) + assert.Len(t, checkResult.Metrics, 1) + }) + t.Run("apply high lag threshold", func(t *testing.T) { + throttlerConfig.Threshold = 4444.0 + throttlerConfig.MetricThresholds["lag"] = 4444.0 + throttler.applyThrottlerConfig(ctx, throttlerConfig) + + t.Run("check after apply, no impact", func(t *testing.T) { + sleepTillThresholdApplies() + // "test" not supposed to check "loadavg" + checkResult := throttler.Check(ctx, testAppName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.9, checkResult.Value) // self lag value + assert.EqualValues(t, http.StatusOK, checkResult.StatusCode) + assert.Len(t, checkResult.Metrics, 1) + }) + }) + t.Run("apply low 'loadavg' threshold", func(t *testing.T) { + throttlerConfig.MetricThresholds["loadavg"] = 0.0077 + throttler.applyThrottlerConfig(ctx, throttlerConfig) + + t.Run("check after apply, no impact", func(t *testing.T) { + sleepTillThresholdApplies() + // "test" not supposed to check "loadavg" + checkResult := throttler.Check(ctx, testAppName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.9, checkResult.Value) // shard lag value + assert.EqualValues(t, http.StatusOK, checkResult.StatusCode) + assert.Len(t, checkResult.Metrics, 1) + }) + }) + t.Run("assign 'loadavg' to test app", func(t *testing.T) { + throttlerConfig.AppCheckedMetrics[testAppName.String()] = &topodatapb.ThrottlerConfig_MetricNames{Names: []string{"loadavg"}} + throttler.applyThrottlerConfig(ctx, throttlerConfig) + + t.Run("check after assignment", func(t *testing.T) { + // "test" now checks "loadavg" + appCheckedMetrics := throttler.appCheckedMetricsSnapshot() + metrics, ok := appCheckedMetrics[testAppName.String()] + require.True(t, ok) + assert.Equal(t, "loadavg", metrics) + + checkResult := throttler.Check(ctx, testAppName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 2.718, checkResult.Value) // self loadavg value + assert.NotEqualValues(t, http.StatusOK, checkResult.StatusCode, "unexpected result: %+v", checkResult) + assert.Len(t, checkResult.Metrics, 1) + }) + }) + t.Run("assign 'shard/loadavg' to test app", func(t *testing.T) { + throttlerConfig.AppCheckedMetrics[testAppName.String()] = &topodatapb.ThrottlerConfig_MetricNames{Names: []string{"shard/loadavg"}} + throttler.applyThrottlerConfig(ctx, throttlerConfig) + + t.Run("check after assignment", func(t *testing.T) { + // "test" now checks "loadavg" + appCheckedMetrics := throttler.appCheckedMetricsSnapshot() + metrics, ok := appCheckedMetrics[testAppName.String()] + require.True(t, ok) + assert.Equal(t, "shard/loadavg", metrics) + + checkResult := throttler.Check(ctx, testAppName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 5.1, checkResult.Value) // shard loadavg value + assert.NotEqualValues(t, http.StatusOK, checkResult.StatusCode, "unexpected result: %+v", checkResult) + assert.Len(t, checkResult.Metrics, 1) + }) + }) + t.Run("assign 'lag,loadavg' to test app", func(t *testing.T) { + throttlerConfig.AppCheckedMetrics[testAppName.String()] = &topodatapb.ThrottlerConfig_MetricNames{Names: []string{"lag", "loadavg"}} + throttler.applyThrottlerConfig(ctx, throttlerConfig) + t.Run("check after assignment", func(t *testing.T) { + // "test" now checks both lag and loadavg + appCheckedMetrics := throttler.appCheckedMetricsSnapshot() + metrics, ok := appCheckedMetrics[testAppName.String()] + require.True(t, ok) + assert.Equal(t, "lag,loadavg", metrics) + + checkResult := throttler.Check(ctx, testAppName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 2.718, checkResult.Value) // self loadavg value + assert.NotEqualValues(t, http.StatusOK, checkResult.StatusCode, "unexpected result: %+v", checkResult) + assert.Equal(t, 2, len(checkResult.Metrics)) + }) + }) + t.Run("assign 'lag,shard/loadavg' to test app", func(t *testing.T) { + throttlerConfig.AppCheckedMetrics[testAppName.String()] = &topodatapb.ThrottlerConfig_MetricNames{Names: []string{"lag", "shard/loadavg"}} + throttler.applyThrottlerConfig(ctx, throttlerConfig) + t.Run("check after assignment", func(t *testing.T) { + // "test" now checks both lag and loadavg + appCheckedMetrics := throttler.appCheckedMetricsSnapshot() + metrics, ok := appCheckedMetrics[testAppName.String()] + require.True(t, ok) + assert.Equal(t, "lag,shard/loadavg", metrics) + + checkResult := throttler.Check(ctx, testAppName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 5.1, checkResult.Value) // shard loadavg value + assert.NotEqualValues(t, http.StatusOK, checkResult.StatusCode, "unexpected result: %+v", checkResult) + assert.Equal(t, 2, len(checkResult.Metrics)) + }) + }) + t.Run("clear 'loadavg' threshold", func(t *testing.T) { + throttlerConfig.AppCheckedMetrics[testAppName.String()] = &topodatapb.ThrottlerConfig_MetricNames{Names: []string{"lag"}} + throttler.applyThrottlerConfig(ctx, throttlerConfig) + t.Run("check after apply, clear", func(t *testing.T) { + sleepTillThresholdApplies() + + checkResult := throttler.Check(ctx, testAppName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.9, checkResult.Value) // shard lag value + assert.EqualValues(t, http.StatusOK, checkResult.StatusCode, "unexpected result: %+v", checkResult) + assert.Equal(t, 1, len(checkResult.Metrics), "unexpected metrics: %+v", checkResult.Metrics) + }) + }) + t.Run("assign 'lag,threads_running' to test app", func(t *testing.T) { + throttlerConfig.AppCheckedMetrics[testAppName.String()] = &topodatapb.ThrottlerConfig_MetricNames{Names: []string{"lag", "threads_running"}} + throttler.applyThrottlerConfig(ctx, throttlerConfig) + t.Run("check after assignment", func(t *testing.T) { + // "test" now checks both lag and loadavg + appCheckedMetrics := throttler.appCheckedMetricsSnapshot() + metrics, ok := appCheckedMetrics[testAppName.String()] + require.True(t, ok) + assert.Equal(t, "lag,threads_running", metrics) + + checkResult := throttler.Check(ctx, testAppName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.9, checkResult.Value) // shard lag value + assert.EqualValues(t, http.StatusOK, checkResult.StatusCode, "unexpected result: %+v", checkResult) + assert.Equal(t, 2, len(checkResult.Metrics)) + }) + }) + t.Run("assign 'custom,loadavg' to 'all' app", func(t *testing.T) { + throttlerConfig.AppCheckedMetrics[testAppName.String()] = &topodatapb.ThrottlerConfig_MetricNames{Names: []string{"lag", "threads_running"}} + throttlerConfig.AppCheckedMetrics[throttlerapp.AllName.String()] = &topodatapb.ThrottlerConfig_MetricNames{Names: []string{"custom", "loadavg"}} + throttler.applyThrottlerConfig(ctx, throttlerConfig) + t.Run("check 'all' after assignment", func(t *testing.T) { + appCheckedMetrics := throttler.appCheckedMetricsSnapshot() + metrics, ok := appCheckedMetrics[throttlerapp.AllName.String()] + require.True(t, ok) + assert.Equal(t, "custom,loadavg", metrics) + + checkResult := throttler.Check(ctx, throttlerapp.AllName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 2.718, checkResult.Value) // loadavg self value exceeds threshold + assert.NotEqualValues(t, http.StatusOK, checkResult.StatusCode, "unexpected result: %+v", checkResult) + assert.Equal(t, 2, len(checkResult.Metrics)) + }) + t.Run("check 'test' after assignment", func(t *testing.T) { + // "test" app unaffected by 'all' assignment, because it has + // explicit metrics assignment. + appCheckedMetrics := throttler.appCheckedMetricsSnapshot() + metrics, ok := appCheckedMetrics[testAppName.String()] + require.True(t, ok) + assert.Equal(t, "lag,threads_running", metrics) + + checkResult := throttler.Check(ctx, testAppName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.9, checkResult.Value) // shard lag value + assert.EqualValues(t, http.StatusOK, checkResult.StatusCode, "unexpected result: %+v", checkResult) + assert.Equal(t, 2, len(checkResult.Metrics)) + }) + t.Run("'online-ddl' app affected by 'all'", func(t *testing.T) { + // "online-ddl" app is affected by 'all' assignment, because it has + // no explicit metrics assignment. + appCheckedMetrics := throttler.appCheckedMetricsSnapshot() + _, ok := appCheckedMetrics[throttlerapp.OnlineDDLName.String()] + require.False(t, ok) + + checkResult := throttler.Check(ctx, throttlerapp.OnlineDDLName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 2.718, checkResult.Value) // loadavg self value exceeds threshold + assert.NotEqualValues(t, http.StatusOK, checkResult.StatusCode, "unexpected result: %+v", checkResult) + assert.Equal(t, 2, len(checkResult.Metrics)) + }) + }) + t.Run("'vreplication:online-ddl:12345' app affected by 'all'", func(t *testing.T) { + // "vreplication:online-ddl:12345" app is affected by 'all' assignment, because it has + // no explicit metrics assignment. + checkResult := throttler.Check(ctx, "vreplication:online-ddl:12345", nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 2.718, checkResult.Value) // loadavg self value exceeds threshold + assert.NotEqualValues(t, http.StatusOK, checkResult.StatusCode, "unexpected result: %+v", checkResult) + assert.Equal(t, 2, len(checkResult.Metrics)) + }) + t.Run("'vreplication:online-ddl:test' app affected by 'test' and not by 'all'", func(t *testing.T) { + // "vreplication:online-ddl:test" app is affected by 'test' assignment, because it has + // the split name "test" has explicit metrics assignment. + checkResult := throttler.Check(ctx, "vreplication:online-ddl:test", nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.9, checkResult.Value) // shard lag value + assert.EqualValues(t, http.StatusOK, checkResult.StatusCode, "unexpected result: %+v", checkResult) + assert.Equal(t, 2, len(checkResult.Metrics)) + }) + t.Run("deassign metrics from 'all' app", func(t *testing.T) { + delete(throttlerConfig.AppCheckedMetrics, throttlerapp.AllName.String()) + throttler.applyThrottlerConfig(ctx, throttlerConfig) + t.Run("check 'all' after assignment", func(t *testing.T) { + appCheckedMetrics := throttler.appCheckedMetricsSnapshot() + _, ok := appCheckedMetrics[throttlerapp.AllName.String()] + require.False(t, ok) + + checkResult := throttler.Check(ctx, throttlerapp.AllName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.9, checkResult.Value) // shard lag value + assert.EqualValues(t, http.StatusOK, checkResult.StatusCode, "unexpected result: %+v", checkResult) + assert.Len(t, checkResult.Metrics, 1) + }) + t.Run("check 'test' after assignment", func(t *testing.T) { + // "test" app unaffected by the entire 'all' assignment, because it has + // explicit metrics assignment. + appCheckedMetrics := throttler.appCheckedMetricsSnapshot() + metrics, ok := appCheckedMetrics[testAppName.String()] + require.True(t, ok) + assert.Equal(t, "lag,threads_running", metrics) + + checkResult := throttler.Check(ctx, testAppName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.9, checkResult.Value) // shard lag value + assert.EqualValues(t, http.StatusOK, checkResult.StatusCode, "unexpected result: %+v", checkResult) + assert.Equal(t, 2, len(checkResult.Metrics)) + }) + t.Run("'online-ddl' no longer has 'all' impact", func(t *testing.T) { + // "online-ddl" app is affected by 'all' assignment, because it has + // no explicit metrics assignment. + appCheckedMetrics := throttler.appCheckedMetricsSnapshot() + _, ok := appCheckedMetrics[throttlerapp.OnlineDDLName.String()] + require.False(t, ok) + + checkResult := throttler.Check(ctx, throttlerapp.OnlineDDLName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.9, checkResult.Value) // shard lag value + assert.EqualValues(t, http.StatusOK, checkResult.StatusCode, "unexpected result: %+v", checkResult) + assert.Len(t, checkResult.Metrics, 1) + }) + }) + + t.Run("deassign metrics from test app", func(t *testing.T) { + delete(throttlerConfig.AppCheckedMetrics, testAppName.String()) + throttler.applyThrottlerConfig(ctx, throttlerConfig) + t.Run("check after deassign, clear", func(t *testing.T) { + appCheckedMetrics := throttler.appCheckedMetricsSnapshot() + _, ok := appCheckedMetrics[testAppName.String()] + require.False(t, ok) + + checkResult := throttler.Check(ctx, testAppName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.9, checkResult.Value) // shard lag value + assert.EqualValues(t, http.StatusOK, checkResult.StatusCode) + assert.Len(t, checkResult.Metrics, 1) + }) + }) + + t.Run("Disable", func(t *testing.T) { + throttlerConfig := &topodatapb.ThrottlerConfig{ + Enabled: false, + MetricThresholds: map[string]float64{}, + AppCheckedMetrics: map[string]*topodatapb.ThrottlerConfig_MetricNames{}, + } + throttler.applyThrottlerConfig(ctx, throttlerConfig) + sleepTillThresholdApplies() + }) + }) +} + func TestIsAppThrottled(t *testing.T) { + plusOneHour := time.Now().Add(time.Hour) throttler := Throttler{ throttledApps: cache.New(cache.NoExpiration, 0), heartbeatWriter: &FakeHeartbeatWriter{}, } - assert.False(t, throttler.IsAppThrottled("app1")) - assert.False(t, throttler.IsAppThrottled("app2")) - assert.False(t, throttler.IsAppThrottled("app3")) - assert.False(t, throttler.IsAppThrottled("app4")) + t.Run("initial", func(t *testing.T) { + assert.False(t, throttler.IsAppThrottled("app1")) + assert.False(t, throttler.IsAppThrottled("app2")) + assert.False(t, throttler.IsAppThrottled("app3")) + assert.False(t, throttler.IsAppThrottled("app4")) + + assert.Equal(t, 0, throttler.throttledApps.ItemCount()) + }) // - throttler.ThrottleApp("app1", time.Now().Add(time.Hour), DefaultThrottleRatio, true) - throttler.ThrottleApp("app2", time.Now(), DefaultThrottleRatio, false) - throttler.ThrottleApp("app3", time.Now().Add(time.Hour), DefaultThrottleRatio, false) - throttler.ThrottleApp("app4", time.Now().Add(time.Hour), 0, false) - assert.False(t, throttler.IsAppThrottled("app1")) // exempted - assert.False(t, throttler.IsAppThrottled("app2")) // expired - assert.True(t, throttler.IsAppThrottled("app3")) - assert.False(t, throttler.IsAppThrottled("app4")) // ratio is zero + t.Run("set some rules", func(t *testing.T) { + throttler.ThrottleApp("app1", plusOneHour, DefaultThrottleRatio, true) + throttler.ThrottleApp("app2", time.Now(), DefaultThrottleRatio, false) // instantly expire + throttler.ThrottleApp("app3", plusOneHour, DefaultThrottleRatio, false) + throttler.ThrottleApp("app4", plusOneHour, 0, false) + assert.False(t, throttler.IsAppThrottled("app1")) // exempted + assert.False(t, throttler.IsAppThrottled("app2")) // expired + assert.True(t, throttler.IsAppThrottled("app3")) + assert.False(t, throttler.IsAppThrottled("app4")) // ratio is zero + assert.False(t, throttler.IsAppThrottled("app_other")) // not specified + + assert.Equal(t, 3, throttler.throttledApps.ItemCount()) + }) + t.Run("all", func(t *testing.T) { + // throttle "all", see how it affects app + throttler.ThrottleApp(throttlerapp.AllName.String(), plusOneHour, DefaultThrottleRatio, false) + defer throttler.UnthrottleApp(throttlerapp.AllName.String()) + assert.True(t, throttler.IsAppThrottled("all")) // + assert.False(t, throttler.IsAppThrottled("app1")) // exempted + assert.True(t, throttler.IsAppThrottled("app2")) // expired, so falls under "all" + assert.True(t, throttler.IsAppThrottled("app3")) + assert.False(t, throttler.IsAppThrottled("app4")) // ratio is zero, there is a specific instruction for this app, so it doesn't fall under "all" + assert.True(t, throttler.IsAppThrottled("app_other")) // falls under "all" + + // continuing previous test, we had 3 throttled apps. "all" is a new app being throttled. + assert.Equal(t, 4, throttler.throttledApps.ItemCount()) + }) // - throttler.UnthrottleApp("app1") - throttler.UnthrottleApp("app2") - throttler.UnthrottleApp("app3") - throttler.UnthrottleApp("app4") - assert.False(t, throttler.IsAppThrottled("app1")) - assert.False(t, throttler.IsAppThrottled("app2")) - assert.False(t, throttler.IsAppThrottled("app3")) - assert.False(t, throttler.IsAppThrottled("app4")) + t.Run("unthrottle", func(t *testing.T) { + throttler.UnthrottleApp("app1") + throttler.UnthrottleApp("app2") + throttler.UnthrottleApp("app3") + throttler.UnthrottleApp("app4") + assert.False(t, throttler.IsAppThrottled("app1")) + assert.False(t, throttler.IsAppThrottled("app2")) + assert.False(t, throttler.IsAppThrottled("app3")) + assert.False(t, throttler.IsAppThrottled("app4")) + + // we've manually unthrottled everything + assert.Equal(t, 0, throttler.throttledApps.ItemCount()) + }) + t.Run("all again", func(t *testing.T) { + // throttle "all", see how it affects app + throttler.ThrottleApp(throttlerapp.AllName.String(), plusOneHour, DefaultThrottleRatio, false) + defer throttler.UnthrottleApp(throttlerapp.AllName.String()) + assert.True(t, throttler.IsAppThrottled("all")) + assert.True(t, throttler.IsAppThrottled("app1")) + assert.True(t, throttler.IsAppThrottled("app2")) + assert.True(t, throttler.IsAppThrottled("app3")) + assert.True(t, throttler.IsAppThrottled("app4")) + assert.True(t, throttler.IsAppThrottled("app_other")) + + // one rule, for "all" app + assert.Equal(t, 1, throttler.throttledApps.ItemCount()) + }) + t.Run("exempt all", func(t *testing.T) { + // throttle "all", see how it affects app + throttler.ThrottleApp("app3", plusOneHour, DefaultThrottleRatio, false) + throttler.ThrottleApp(throttlerapp.AllName.String(), plusOneHour, DefaultThrottleRatio, true) + defer throttler.UnthrottleApp(throttlerapp.AllName.String()) + assert.False(t, throttler.IsAppThrottled("all")) + assert.False(t, throttler.IsAppThrottled("app1")) + assert.False(t, throttler.IsAppThrottled("app2")) + assert.True(t, throttler.IsAppThrottled("app3")) + assert.False(t, throttler.IsAppThrottled("app4")) + assert.False(t, throttler.IsAppThrottled("app_other")) + + assert.Equal(t, 2, throttler.throttledApps.ItemCount()) + }) } func TestIsAppExempted(t *testing.T) { @@ -248,103 +897,82 @@ func TestIsAppExempted(t *testing.T) { assert.True(t, throttler.IsAppExempted("schema-tracker")) } -// TestRefreshMySQLInventory tests the behavior of the throttler's RefreshMySQLInventory() function, which +// TestRefreshInventory tests the behavior of the throttler's RefreshInventory() function, which // is called periodically in actual throttler. For a given cluster name, it generates a list of probes // the throttler will use to check metrics. -// On a "self" cluster, that list is expect to probe the tablet itself. -// On any other cluster, the list is expected to be empty if non-leader (only leader throttler, on a -// `PRIMARY` tablet, probes other tablets). On the leader, the list is expected to be non-empty. -func TestRefreshMySQLInventory(t *testing.T) { +// On a replica tablet, that list is expect to probe the tablet itself. +// On the PRIMARY, the list includes all shard tablets, including the PRIMARY itself. +func TestRefreshInventory(t *testing.T) { + ctx := context.Background() // for development, replace with ctx := utils.LeakCheckContext(t) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + metricsQuery := "select 1" configSettings := config.NewConfigurationSettings() - clusters := map[string]*config.MySQLClusterConfigurationSettings{ - selfStoreName: {}, - "ks1": {}, - "ks2": {}, - } - for _, s := range clusters { - s.MetricQuery = metricsQuery - s.ThrottleThreshold = &atomic.Uint64{} - s.ThrottleThreshold.Store(1) - } - configSettings.Stores.MySQL.Clusters = clusters throttler := &Throttler{ - mysqlClusterProbesChan: make(chan *mysql.ClusterProbes), - mysqlClusterThresholds: cache.New(cache.NoExpiration, 0), - ts: &FakeTopoServer{}, - mysqlInventory: mysql.NewInventory(), + clusterProbesChan: make(chan *base.ClusterProbes), + metricThresholds: cache.New(cache.NoExpiration, 0), + ts: &FakeTopoServer{}, + inventory: base.NewInventory(), } - throttler.configSettings = configSettings throttler.metricsQuery.Store(metricsQuery) + throttler.configSettings = configSettings + throttler.initConfig() throttler.initThrottleTabletTypes() validateClusterProbes := func(t *testing.T, ctx context.Context) { testName := fmt.Sprintf("leader=%t", throttler.isLeader.Load()) t.Run(testName, func(t *testing.T) { // validateProbesCount expects number of probes according to cluster name and throttler's leadership status - validateProbesCount := func(t *testing.T, clusterName string, probes mysql.Probes) { - if clusterName == selfStoreName { - assert.Equal(t, 1, len(probes)) - } else if throttler.isLeader.Load() { - assert.NotZero(t, len(probes)) + validateProbesCount := func(t *testing.T, probes base.Probes) { + if throttler.isLeader.Load() { + assert.Equal(t, 3, len(probes)) } else { - assert.Empty(t, probes) + assert.Equal(t, 1, len(probes)) } } t.Run("waiting for probes", func(t *testing.T) { ctx, cancel := context.WithTimeout(ctx, waitForProbesTimeout) defer cancel() - numClusterProbesResults := 0 for { select { - case probes := <-throttler.mysqlClusterProbesChan: + case probes := <-throttler.clusterProbesChan: // Worth noting that in this unit test, the throttler is _closed_ and _disabled_. Its own Operate() function does - // not run, and therefore there is none but us to both populate `mysqlClusterProbesChan` as well as + // not run, and therefore there is none but us to both populate `clusterProbesChan` as well as // read from it. We do not compete here with any other goroutine. assert.NotNil(t, probes) - - throttler.updateMySQLClusterProbes(ctx, probes) - - numClusterProbesResults++ - validateProbesCount(t, probes.ClusterName, probes.TabletProbes) - - if numClusterProbesResults == len(clusters) { - // Achieved our goal - return - } + throttler.updateClusterProbes(ctx, probes) + validateProbesCount(t, probes.TabletProbes) + // Achieved our goal + return case <-ctx.Done(): - assert.FailNowf(t, ctx.Err().Error(), "waiting for %d cluster probes", len(clusters)) + assert.FailNowf(t, ctx.Err().Error(), "waiting for cluster probes") } } }) t.Run("validating probes", func(t *testing.T) { - for clusterName := range clusters { - probes, ok := throttler.mysqlInventory.ClustersProbes[clusterName] - require.True(t, ok) - validateProbesCount(t, clusterName, probes) - } + probes := throttler.inventory.ClustersProbes + validateProbesCount(t, probes) }) }) } - // - ctx := context.Background() t.Run("initial, not leader", func(t *testing.T) { throttler.isLeader.Store(false) - throttler.refreshMySQLInventory(ctx) + throttler.refreshInventory(ctx) validateClusterProbes(t, ctx) }) t.Run("promote", func(t *testing.T) { throttler.isLeader.Store(true) - throttler.refreshMySQLInventory(ctx) + throttler.refreshInventory(ctx) validateClusterProbes(t, ctx) }) t.Run("demote, expect cleanup", func(t *testing.T) { throttler.isLeader.Store(false) - throttler.refreshMySQLInventory(ctx) + throttler.refreshInventory(ctx) validateClusterProbes(t, ctx) }) } @@ -382,6 +1010,7 @@ func runThrottler(t *testing.T, ctx context.Context, throttler *Throttler, timeo case <-ctx.Done(): return case <-time.After(sleepTime): + waitForMetricsToBeCollected(t, ctx, throttler) f(t, ctx) } } @@ -390,44 +1019,80 @@ func runThrottler(t *testing.T, ctx context.Context, throttler *Throttler, timeo assert.Error(t, ctx.Err()) throttler.Disable() + wg.Wait() assert.False(t, throttler.IsEnabled()) } // TestRace merely lets the throttler run with aggressive intervals for a few seconds, so as to detect race conditions. // This is relevant to `go test -race` func TestRace(t *testing.T) { + ctx := context.Background() // for development, replace with ctx := utils.LeakCheckContext(t) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + throttler := newTestThrottler() - runThrottler(t, context.Background(), throttler, 5*time.Second, nil) + runThrottler(t, ctx, throttler, 5*time.Second, nil) } // TestProbes enables a throttler for a few seconds, and afterwards expects to find probes and metrics. func TestProbesWhileOperating(t *testing.T) { + ctx := context.Background() // for development, replace with ctx := utils.LeakCheckContext(t) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + throttler := newTestThrottler() tmClient, ok := throttler.overrideTmClient.(*fakeTMClient) require.True(t, ok) assert.Empty(t, tmClient.AppNames()) - t.Run("aggregated", func(t *testing.T) { + t.Run("aggregated initial", func(t *testing.T) { assert.Equal(t, 0, throttler.aggregatedMetrics.ItemCount()) }) - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() runThrottler(t, ctx, throttler, time.Minute, func(t *testing.T, ctx context.Context) { + defer cancel() // early termination t.Run("aggregated", func(t *testing.T) { - assert.Equal(t, 2, throttler.aggregatedMetrics.ItemCount()) // flushed upon Disable() + assert.Equal(t, base.LagMetricName, throttler.metricNameUsedAsDefault()) aggr := throttler.aggregatedMetricsSnapshot() - assert.Equal(t, 2, len(aggr)) // "self" and "shard" clusters - for clusterName, metricResult := range aggr { + assert.Equalf(t, 2*len(base.KnownMetricNames), len(aggr), "aggregated: %+v", aggr) // "self" and "shard", per known metric + assert.Equal(t, 2*len(base.KnownMetricNames), throttler.aggregatedMetrics.ItemCount()) // flushed upon Disable() + for aggregatedMetricName, metricResult := range aggr { val, err := metricResult.Get() - assert.NoError(t, err) - switch clusterName { - case "mysql/self": - assert.Equal(t, float64(1), val) - case "mysql/shard": - assert.Equal(t, float64(0), val) + assert.NoErrorf(t, err, "aggregatedMetricName: %v", aggregatedMetricName) + assert.NotEmpty(t, aggregatedMetricName) + scope, metricName, err := base.DisaggregateMetricName(aggregatedMetricName) + assert.NotEmpty(t, metricName) + require.NoError(t, err) + + switch scope { + case base.UndefinedScope, base.SelfScope: + switch metricName { + case base.DefaultMetricName: + assert.Equalf(t, float64(0.3), val, "scope=%v, metricName=%v", scope, metricName) // same value as "lag" + case base.LagMetricName: + assert.Equalf(t, float64(0.3), val, "scope=%v, metricName=%v", scope, metricName) + case base.ThreadsRunningMetricName: + assert.Equalf(t, float64(26), val, "scope=%v, metricName=%v", scope, metricName) + case base.CustomMetricName: + assert.Equalf(t, float64(17), val, "scope=%v, metricName=%v", scope, metricName) + case base.LoadAvgMetricName: + assert.Equalf(t, float64(2.718), val, "scope=%v, metricName=%v", scope, metricName) + } + case base.ShardScope: + switch metricName { + case base.DefaultMetricName: + assert.Equalf(t, float64(0.9), val, "scope=%v, metricName=%v", scope, metricName) // same value as "lag" + case base.LagMetricName: + assert.Equalf(t, float64(0.9), val, "scope=%v, metricName=%v", scope, metricName) + case base.ThreadsRunningMetricName: + assert.Equalf(t, float64(26), val, "scope=%v, metricName=%v", scope, metricName) + case base.CustomMetricName: + assert.Equalf(t, float64(17), val, "scope=%v, metricName=%v", scope, metricName) + case base.LoadAvgMetricName: + assert.Equalf(t, float64(5.1), val, "scope=%v, metricName=%v", scope, metricName) + } default: - assert.Failf(t, "unknown clusterName", "%v", clusterName) + assert.Failf(t, "unknown scope", "scope=%v", scope) } } assert.NotEmpty(t, tmClient.AppNames()) @@ -444,48 +1109,267 @@ func TestProbesWhileOperating(t *testing.T) { // And that's the only app we expect to see. assert.Equalf(t, 1, len(uniqueNames), "%+v", uniqueNames) - cancel() // end test early + t.Run("client, shard", func(t *testing.T) { + client := NewBackgroundClient(throttler, testAppName, base.UndefinedScope) + t.Run("threshold exceeded", func(t *testing.T) { + <-runSerialFunction(t, ctx, throttler, func(ctx context.Context) { + throttler.refreshInventory(ctx) + }) + { + checkOK := client.ThrottleCheckOK(ctx, "") + assert.False(t, checkOK) // we expect threshold exceeded + } + }) + + savedThreshold := throttler.MetricsThreshold.Load() + t.Run("adjust threshold", func(t *testing.T) { + throttler.MetricsThreshold.Store(math.Float64bits(0.95)) + <-runSerialFunction(t, ctx, throttler, func(ctx context.Context) { + throttler.refreshInventory(ctx) + }) + { + checkOK := client.ThrottleCheckOK(ctx, "") + assert.True(t, checkOK) + } + }) + t.Run("restore threshold", func(t *testing.T) { + throttler.MetricsThreshold.Store(savedThreshold) + <-runSerialFunction(t, ctx, throttler, func(ctx context.Context) { + throttler.refreshInventory(ctx) + }) + client.clearSuccessfulResultsCache() // ensure we don't read the successful result from the test above + { + checkOK := client.ThrottleCheckOK(ctx, "") + assert.False(t, checkOK) + } + }) + }) + }) + + t.Run("aggregated with custom query", func(t *testing.T) { + // The query itself isn't important here, since we're emulating. What's important is that it's not empty. + // Hence, the throttler will choose to set the "custom" metric results in the aggregated "default" metrics, + // as opposed to choosing the "lag" metric results. + throttler.customMetricsQuery.Store("select non_empty") + <-runSerialFunction(t, ctx, throttler, func(ctx context.Context) { + throttler.aggregateMetrics() + }) + assert.Equal(t, base.CustomMetricName, throttler.metricNameUsedAsDefault()) + aggr := throttler.aggregatedMetricsSnapshot() + assert.Equalf(t, 2*len(base.KnownMetricNames), len(aggr), "aggregated: %+v", aggr) // "self" and "shard", per known metric + assert.Equal(t, 2*len(base.KnownMetricNames), throttler.aggregatedMetrics.ItemCount()) // flushed upon Disable() + for aggregatedMetricName, metricResult := range aggr { + val, err := metricResult.Get() + assert.NoErrorf(t, err, "aggregatedMetricName: %v", aggregatedMetricName) + assert.NotEmpty(t, aggregatedMetricName) + scope, metricName, err := base.DisaggregateMetricName(aggregatedMetricName) + assert.NotEmpty(t, metricName) + require.NoError(t, err) + + switch scope { + case base.UndefinedScope, base.SelfScope: + switch metricName { + case base.DefaultMetricName: + assert.Equalf(t, float64(17), val, "scope=%v, metricName=%v", scope, metricName) // same value as "custom" + case base.LagMetricName: + assert.Equalf(t, float64(0.3), val, "scope=%v, metricName=%v", scope, metricName) + case base.ThreadsRunningMetricName: + assert.Equalf(t, float64(26), val, "scope=%v, metricName=%v", scope, metricName) + case base.CustomMetricName: + assert.Equalf(t, float64(17), val, "scope=%v, metricName=%v", scope, metricName) + case base.LoadAvgMetricName: + assert.Equalf(t, float64(2.718), val, "scope=%v, metricName=%v", scope, metricName) + } + case base.ShardScope: + switch metricName { + case base.DefaultMetricName: + assert.Equalf(t, float64(17), val, "scope=%v, metricName=%v", scope, metricName) // same value as "custom" + case base.LagMetricName: + assert.Equalf(t, float64(0.9), val, "scope=%v, metricName=%v", scope, metricName) + case base.ThreadsRunningMetricName: + assert.Equalf(t, float64(26), val, "scope=%v, metricName=%v", scope, metricName) + case base.CustomMetricName: + assert.Equalf(t, float64(17), val, "scope=%v, metricName=%v", scope, metricName) + case base.LoadAvgMetricName: + assert.Equalf(t, float64(5.1), val, "scope=%v, metricName=%v", scope, metricName) + } + default: + assert.Failf(t, "unknown scope", "scope=%v", scope) + } + } + + t.Run("client, shard", func(t *testing.T) { + client := NewBackgroundClient(throttler, testAppName, base.UndefinedScope) + t.Run("threshold exceeded", func(t *testing.T) { + <-runSerialFunction(t, ctx, throttler, func(ctx context.Context) { + throttler.refreshInventory(ctx) + }) + { + checkOK := client.ThrottleCheckOK(ctx, "") + assert.False(t, checkOK) // we expect threshold exceeded + } + }) + + savedThreshold := throttler.MetricsThreshold.Load() + t.Run("adjust threshold, too low", func(t *testing.T) { + throttler.MetricsThreshold.Store(math.Float64bits(0.95)) + <-runSerialFunction(t, ctx, throttler, func(ctx context.Context) { + throttler.refreshInventory(ctx) + }) + { + checkOK := client.ThrottleCheckOK(ctx, "") + assert.False(t, checkOK) // 0.95 still too low for custom query + } + }) + t.Run("adjust threshold, still too low", func(t *testing.T) { + throttler.MetricsThreshold.Store(math.Float64bits(15)) + <-runSerialFunction(t, ctx, throttler, func(ctx context.Context) { + throttler.refreshInventory(ctx) + }) + { + checkOK := client.ThrottleCheckOK(ctx, "") + assert.False(t, checkOK) // 15 still too low for custom query because primary has 17 + } + }) + t.Run("adjust threshold", func(t *testing.T) { + throttler.MetricsThreshold.Store(math.Float64bits(18)) + <-runSerialFunction(t, ctx, throttler, func(ctx context.Context) { + throttler.refreshInventory(ctx) + }) + { + checkOK := client.ThrottleCheckOK(ctx, "") + assert.True(t, checkOK) + } + }) + t.Run("restore threshold", func(t *testing.T) { + throttler.MetricsThreshold.Store(savedThreshold) + <-runSerialFunction(t, ctx, throttler, func(ctx context.Context) { + throttler.refreshInventory(ctx) + }) + client.clearSuccessfulResultsCache() // ensure we don't read the successful result from the test above + { + checkOK := client.ThrottleCheckOK(ctx, "") + assert.False(t, checkOK) + } + }) + }) + }) + }) +} + +// TestProbesWithV20Replicas is similar to TestProbesWhileOperating, but assumes a v20 replica, which does not report any of the named metrics. +func TestProbesWithV20Replicas(t *testing.T) { + ctx := context.Background() // for development, replace with ctx := utils.LeakCheckContext(t) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + throttler := newTestThrottler() + + tmClient, ok := throttler.overrideTmClient.(*fakeTMClient) + require.True(t, ok) + assert.Empty(t, tmClient.AppNames()) + tmClient.v20.Store(true) + + t.Run("aggregated initial", func(t *testing.T) { + assert.Equal(t, 0, throttler.aggregatedMetrics.ItemCount()) + }) + + runThrottler(t, ctx, throttler, time.Minute, func(t *testing.T, ctx context.Context) { + defer cancel() // early termination + t.Run("aggregated", func(t *testing.T) { + aggr := throttler.aggregatedMetricsSnapshot() + assert.Equalf(t, 2*len(base.KnownMetricNames), len(aggr), "aggregated: %+v", aggr) // "self" and "shard", per known metric + assert.Equal(t, 2*len(base.KnownMetricNames), throttler.aggregatedMetrics.ItemCount()) // flushed upon Disable() + for aggregatedMetricName, metricResult := range aggr { + assert.NotEmpty(t, aggregatedMetricName) + scope, metricName, err := base.DisaggregateMetricName(aggregatedMetricName) + assert.NotEmpty(t, metricName) + require.NoError(t, err) + + val, metricResultErr := metricResult.Get() + expectMetricNotCollectedYet := false + switch base.Scope(scope) { + case base.SelfScope: + switch metricName { + case base.DefaultMetricName: + assert.Equalf(t, float64(0.3), val, "scope=%v, metricName=%v", scope, metricName) // same value as "lag" + case base.LagMetricName: + assert.Equalf(t, float64(0.3), val, "scope=%v, metricName=%v", scope, metricName) + case base.ThreadsRunningMetricName: + assert.Equalf(t, float64(26), val, "scope=%v, metricName=%v", scope, metricName) + case base.CustomMetricName: + assert.Equalf(t, float64(17), val, "scope=%v, metricName=%v", scope, metricName) + case base.LoadAvgMetricName: + assert.Equalf(t, float64(2.718), val, "scope=%v, metricName=%v", scope, metricName) + } + case base.ShardScope: + // Replicas will nto report named metrics, since they now assume v20 behavior. They will only + // produce the single v20 metric (which we call "default", though they don't advertise it under the name "base.DefaultMetricName") + switch metricName { + case base.DefaultMetricName: + assert.Equalf(t, float64(0.339), val, "scope=%v, metricName=%v", scope, metricName) // same value as "lag" + case base.LagMetricName: + assert.Equalf(t, float64(0.339), val, "scope=%v, metricName=%v", scope, metricName) // + default: + assert.Zero(t, val, "scope=%v, metricName=%v", scope, metricName) + expectMetricNotCollectedYet = true + } + default: + assert.Failf(t, "unknown scope", "scope=%v", scope) + } + if expectMetricNotCollectedYet { + assert.ErrorIs(t, metricResultErr, base.ErrNoResultYet) + } else { + assert.NoErrorf(t, metricResultErr, "aggregatedMetricName: %v", aggregatedMetricName) + } + } + assert.NotEmpty(t, tmClient.AppNames()) + // The throttler here emulates a PRIMARY tablet, and therefore should probe the replicas using + // the "vitess" app name. + uniqueNames := map[string]int{} + for _, appName := range tmClient.AppNames() { + uniqueNames[appName]++ + } + // PRIMARY throttler probes replicas with empty app name, which is then + // interpreted as "vitess" name. + _, ok := uniqueNames[""] + assert.Truef(t, ok, "%+v", uniqueNames) + // And that's the only app we expect to see. + assert.Equalf(t, 1, len(uniqueNames), "%+v", uniqueNames) }) }) } // TestProbesPostDisable runs the throttler for some time, and then investigates the internal throttler maps and values. func TestProbesPostDisable(t *testing.T) { + ctx := context.Background() // for development, replace with ctx := utils.LeakCheckContext(t) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + throttler := newTestThrottler() - runThrottler(t, context.Background(), throttler, 2*time.Second, nil) - - probes := throttler.mysqlInventory.ClustersProbes - assert.NotEmpty(t, probes) - - selfProbes := probes[selfStoreName] - t.Run("self", func(t *testing.T) { - assert.NotEmpty(t, selfProbes) - require.Equal(t, 1, len(selfProbes)) // should always be true once refreshMySQLInventory() runs - probe, ok := selfProbes[""] - assert.True(t, ok) - assert.NotNil(t, probe) - - assert.Equal(t, "", probe.Alias) - assert.Nil(t, probe.Tablet) - assert.Equal(t, "select 1", probe.MetricQuery) - assert.Zero(t, atomic.LoadInt64(&probe.QueryInProgress)) - }) + runThrottler(t, ctx, throttler, 2*time.Second, nil) - shardProbes := probes[shardStoreName] - t.Run("shard", func(t *testing.T) { - assert.NotEmpty(t, shardProbes) - assert.Equal(t, 2, len(shardProbes)) // see fake FindAllTabletAliasesInShard above - for _, probe := range shardProbes { + probes := throttler.inventory.ClustersProbes + + <-time.After(1 * time.Second) // throttler's context was cancelled, but still some functionality needs to complete + t.Run("probes", func(t *testing.T) { + assert.Equal(t, 3, len(probes)) // see fake FindAllTabletAliasesInShard above + localTabletFound := 0 + for _, probe := range probes { require.NotNil(t, probe) - assert.NotEmpty(t, probe.Alias) - assert.NotNil(t, probe.Tablet) - assert.Equal(t, "select 1", probe.MetricQuery) - assert.Zero(t, atomic.LoadInt64(&probe.QueryInProgress)) + if probe.Alias == throttler.tabletAlias { + localTabletFound++ + } else { + assert.NotEmpty(t, probe.Alias) + assert.NotNil(t, probe.Tablet) + } + assert.Zero(t, atomic.LoadInt64(&probe.QueryInProgress), "alias=%s", probe.Alias) } + assert.Equal(t, 1, localTabletFound) }) t.Run("metrics", func(t *testing.T) { - assert.Equal(t, 3, len(throttler.mysqlInventory.TabletMetrics)) // 1 self tablet + 2 shard tablets + assert.Equal(t, 3, len(throttler.inventory.TabletMetrics)) // 1 self tablet + 2 shard tablets }) t.Run("aggregated", func(t *testing.T) { @@ -496,7 +1380,8 @@ func TestProbesPostDisable(t *testing.T) { } func TestDormant(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) + ctx := context.Background() // for development, replace with ctx := utils.LeakCheckContext(t) + ctx, cancel := context.WithCancel(ctx) defer cancel() throttler := newTestThrottler() @@ -508,9 +1393,14 @@ func TestDormant(t *testing.T) { runThrottler(t, ctx, throttler, time.Minute, func(t *testing.T, ctx context.Context) { assert.True(t, throttler.isDormant()) assert.EqualValues(t, 1, heartbeatWriter.Requests()) // once upon Enable() - flags := &CheckFlags{} - throttler.CheckByType(ctx, throttlerapp.VitessName.String(), "", flags, ThrottleCheckSelf) + flags := &CheckFlags{ + Scope: base.SelfScope, + MultiMetricsEnabled: true, + } + throttler.Check(ctx, throttlerapp.VitessName.String(), nil, flags) go func() { + defer cancel() // early termination + select { case <-ctx.Done(): require.FailNow(t, "context expired before testing completed") @@ -518,7 +1408,7 @@ func TestDormant(t *testing.T) { assert.True(t, throttler.isDormant()) assert.EqualValues(t, 1, heartbeatWriter.Requests()) // "vitess" name does not cause heartbeat requests } - throttler.CheckByType(ctx, throttlerapp.ThrottlerStimulatorName.String(), "", flags, ThrottleCheckSelf) + throttler.Check(ctx, throttlerapp.ThrottlerStimulatorName.String(), nil, flags) select { case <-ctx.Done(): require.FailNow(t, "context expired before testing completed") @@ -526,7 +1416,7 @@ func TestDormant(t *testing.T) { assert.False(t, throttler.isDormant()) assert.Greater(t, heartbeatWriter.Requests(), int64(1)) } - throttler.CheckByType(ctx, throttlerapp.OnlineDDLName.String(), "", flags, ThrottleCheckSelf) + throttler.Check(ctx, throttlerapp.OnlineDDLName.String(), nil, flags) select { case <-ctx.Done(): require.FailNow(t, "context expired before testing completed") @@ -542,13 +1432,247 @@ func TestDormant(t *testing.T) { case <-time.After(throttler.dormantPeriod): assert.True(t, throttler.isDormant()) } - cancel() // end test early }() }) } +func TestChecks(t *testing.T) { + ctx := context.Background() // for development, replace with ctx := utils.LeakCheckContext(t) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + throttler := newTestThrottler() + throttler.dormantPeriod = time.Minute + + tmClient, ok := throttler.overrideTmClient.(*fakeTMClient) + require.True(t, ok) + assert.Empty(t, tmClient.AppNames()) + + validateAppNames := func(t *testing.T) { + t.Run("app names", func(t *testing.T) { + assert.NotEmpty(t, tmClient.AppNames()) + // The throttler here emulates a PRIMARY tablet, and therefore should probe the replicas using + // the "vitess" app name. + uniqueNames := map[string]int{} + for _, appName := range tmClient.AppNames() { + uniqueNames[appName]++ + } + // PRIMARY throttler probes replicas with empty app name, which is then + // interpreted as "vitess" name. + _, ok := uniqueNames[""] + assert.Truef(t, ok, "%+v", uniqueNames) + assert.Equalf(t, 1, len(uniqueNames), "%+v", uniqueNames) + }) + } + + runThrottler(t, ctx, throttler, time.Minute, func(t *testing.T, ctx context.Context) { + defer cancel() + throttlerConfig := &topodatapb.ThrottlerConfig{ + Enabled: true, + MetricThresholds: map[string]float64{}, + AppCheckedMetrics: map[string]*topodatapb.ThrottlerConfig_MetricNames{}, + } + + t.Run("apply high thresholds", func(t *testing.T) { + // We apply high thresholds because if a value exceeds a threshold, as is the case + // designed in the original values (load average 2.718 > 1) then the check result is + // an error and indicates the errored value. Which is something we already test in + // TestApplyThrottlerConfigAppCheckedMetrics. + // In this test, we specifically look for how "lag" is used as the default metric. + // We this mute other metrics by setting their thresholds to be high. + throttlerConfig.MetricThresholds["loadavg"] = 7777 + throttlerConfig.MetricThresholds["custom"] = 7778 + throttler.applyThrottlerConfig(ctx, throttlerConfig) + }) + sleepTillThresholdApplies() + + assert.Equal(t, base.LagMetricName, throttler.metricNameUsedAsDefault()) + aggr := throttler.aggregatedMetricsSnapshot() + assert.Equalf(t, 2*len(base.KnownMetricNames), len(aggr), "aggregated: %+v", aggr) // "self" and "shard", per known metric + assert.Equal(t, 2*len(base.KnownMetricNames), throttler.aggregatedMetrics.ItemCount()) // flushed upon Disable() + + validateAppNames(t) + t.Run("checks, self scope", func(t *testing.T) { + flags := &CheckFlags{ + Scope: base.SelfScope, + MultiMetricsEnabled: true, + } + t.Run("implicit names", func(t *testing.T) { + checkResult := throttler.Check(ctx, testAppName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.3, checkResult.Value) // self lag value + assert.EqualValues(t, http.StatusOK, checkResult.StatusCode) + assert.Len(t, checkResult.Metrics, 1) + }) + t.Run("explicit names", func(t *testing.T) { + checkResult := throttler.Check(ctx, testAppName.String(), base.KnownMetricNames, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.3, checkResult.Value, "unexpected result: %+v", checkResult) // self lag value + if !assert.EqualValues(t, http.StatusOK, checkResult.StatusCode, "unexpected result: %+v", checkResult) { + for k, v := range checkResult.Metrics { + t.Logf("%s: %+v", k, v) + } + } + assert.Equal(t, len(base.KnownMetricNames), len(checkResult.Metrics)) + + assert.EqualValues(t, 0.3, checkResult.Metrics[base.LagMetricName.String()].Value) // self lag value, because flags.Scope is set + assert.EqualValues(t, 26, checkResult.Metrics[base.ThreadsRunningMetricName.String()].Value) // self value, because flags.Scope is set + assert.EqualValues(t, 17, checkResult.Metrics[base.CustomMetricName.String()].Value) // self value, because flags.Scope is set + assert.EqualValues(t, 2.718, checkResult.Metrics[base.LoadAvgMetricName.String()].Value) // self value, because flags.Scope is set + for _, metric := range checkResult.Metrics { + assert.EqualValues(t, base.SelfScope.String(), metric.Scope) + } + }) + }) + t.Run("checks, self scope, vitess app", func(t *testing.T) { + // "vitess" app always checks all known metrics. + flags := &CheckFlags{ + // scope not important for this test + MultiMetricsEnabled: true, + } + t.Run("implicit names, always all known", func(t *testing.T) { + checkResult := throttler.Check(ctx, throttlerapp.VitessName.String(), nil, flags) + // "vitess" app always checks all known metrics: + assert.Equal(t, len(base.KnownMetricNames), len(checkResult.Metrics)) + }) + t.Run("explicit names, irrelevant, always all known", func(t *testing.T) { + metricNames := base.MetricNames{ + base.MetricName("self/threads_running"), + base.MetricName("custom"), + } + + checkResult := throttler.Check(ctx, throttlerapp.VitessName.String(), metricNames, flags) + require.NotNil(t, checkResult) + assert.Equal(t, len(base.KnownMetricNames), len(checkResult.Metrics)) + }) + }) + + t.Run("checks, shard scope", func(t *testing.T) { + flags := &CheckFlags{ + Scope: base.ShardScope, + MultiMetricsEnabled: true, + } + t.Run("implicit names", func(t *testing.T) { + checkResult := throttler.Check(ctx, testAppName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.9, checkResult.Value) // shard lag value + assert.NotEqualValues(t, http.StatusOK, checkResult.StatusCode) + assert.ErrorIs(t, checkResult.Error, base.ErrThresholdExceeded) + assert.Len(t, checkResult.Metrics, 1) + }) + t.Run("explicit names", func(t *testing.T) { + checkResult := throttler.Check(ctx, testAppName.String(), base.KnownMetricNames, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.9, checkResult.Value) // shard lag value + assert.NotEqualValues(t, http.StatusOK, checkResult.StatusCode) + assert.ErrorIs(t, checkResult.Error, base.ErrThresholdExceeded) + assert.Equal(t, len(base.KnownMetricNames), len(checkResult.Metrics)) + + assert.EqualValues(t, 0.9, checkResult.Metrics[base.LagMetricName.String()].Value) // shard lag value, because flags.Scope is set + assert.EqualValues(t, 26, checkResult.Metrics[base.ThreadsRunningMetricName.String()].Value) // shard value, because flags.Scope is set + assert.EqualValues(t, 17, checkResult.Metrics[base.CustomMetricName.String()].Value) // shard value, because flags.Scope is set + assert.EqualValues(t, 5.1, checkResult.Metrics[base.LoadAvgMetricName.String()].Value) // shard value, because flags.Scope is set + for _, metric := range checkResult.Metrics { + assert.EqualValues(t, base.ShardScope.String(), metric.Scope) + } + }) + }) + t.Run("checks, undefined scope", func(t *testing.T) { + flags := &CheckFlags{ + // Leaving scope undefined, so that each metrics picks its own scope + MultiMetricsEnabled: true, + } + t.Run("implicit names", func(t *testing.T) { + checkResult := throttler.Check(ctx, testAppName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.9, checkResult.Value) // shard lag value + assert.NotEqualValues(t, http.StatusOK, checkResult.StatusCode) + assert.ErrorIs(t, checkResult.Error, base.ErrThresholdExceeded) + assert.Len(t, checkResult.Metrics, 1) + }) + t.Run("explicit names", func(t *testing.T) { + checkResult := throttler.Check(ctx, testAppName.String(), base.KnownMetricNames, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.9, checkResult.Value) // shard lag value + assert.NotEqualValues(t, http.StatusOK, checkResult.StatusCode) + assert.ErrorIs(t, checkResult.Error, base.ErrThresholdExceeded) + assert.Equal(t, len(base.KnownMetricNames), len(checkResult.Metrics)) + + assert.EqualValues(t, 0.9, checkResult.Metrics[base.LagMetricName.String()].Value) // shard lag value, because "shard" is the default scope for lag + assert.EqualValues(t, 26, checkResult.Metrics[base.ThreadsRunningMetricName.String()].Value) // self value, because "self" is the default scope for threads_running + assert.EqualValues(t, 17, checkResult.Metrics[base.CustomMetricName.String()].Value) // self value, because "self" is the default scope for custom + assert.EqualValues(t, 2.718, checkResult.Metrics[base.LoadAvgMetricName.String()].Value) // self value, because "self" is the default scope for loadavg + assert.EqualValues(t, base.ShardScope.String(), checkResult.Metrics[base.LagMetricName.String()].Scope) + assert.EqualValues(t, base.SelfScope.String(), checkResult.Metrics[base.ThreadsRunningMetricName.String()].Scope) + assert.EqualValues(t, base.SelfScope.String(), checkResult.Metrics[base.CustomMetricName.String()].Scope) + assert.EqualValues(t, base.SelfScope.String(), checkResult.Metrics[base.LoadAvgMetricName.String()].Scope) + }) + }) + t.Run("checks, defined scope masks explicit scope metrics", func(t *testing.T) { + flags := &CheckFlags{ + Scope: base.ShardScope, + MultiMetricsEnabled: true, + } + t.Run("explicit names", func(t *testing.T) { + metricNames := base.MetricNames{ + base.MetricName("self/lag"), + base.MetricName("self/threads_running"), + base.MetricName("custom"), + base.MetricName("shard/loadavg"), + base.MetricName("default"), + } + checkResult := throttler.Check(ctx, testAppName.String(), metricNames, flags) + + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.9, checkResult.Value) // shard lag value + assert.NotEqualValues(t, http.StatusOK, checkResult.StatusCode) + assert.ErrorIs(t, checkResult.Error, base.ErrThresholdExceeded) + assert.Equal(t, len(metricNames), len(checkResult.Metrics)) + + assert.EqualValues(t, 0.9, checkResult.Metrics[base.LagMetricName.String()].Value) // shard lag value, even though scope name is in metric name + assert.EqualValues(t, 26, checkResult.Metrics[base.ThreadsRunningMetricName.String()].Value) // shard value, even though scope name is in metric name + assert.EqualValues(t, 17, checkResult.Metrics[base.CustomMetricName.String()].Value) // shard value because flags.Scope is set + assert.EqualValues(t, 5.1, checkResult.Metrics[base.LoadAvgMetricName.String()].Value) // shard value, not because scope name is in metric name but because flags.Scope is set + for _, metric := range checkResult.Metrics { + assert.EqualValues(t, base.ShardScope.String(), metric.Scope) + } + }) + }) + t.Run("checks, undefined scope and explicit scope metrics", func(t *testing.T) { + flags := &CheckFlags{ + // Leaving scope undefined + MultiMetricsEnabled: true, + } + t.Run("explicit names", func(t *testing.T) { + metricNames := base.MetricNames{ + base.MetricName("self/lag"), + base.MetricName("self/threads_running"), + base.MetricName("custom"), + base.MetricName("shard/loadavg"), + } + checkResult := throttler.Check(ctx, testAppName.String(), metricNames, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.3, checkResult.Value) // explicitly set self lag value + assert.EqualValues(t, http.StatusOK, checkResult.StatusCode) + assert.Equal(t, len(metricNames), len(checkResult.Metrics)) + + assert.EqualValues(t, 0.3, checkResult.Metrics[base.LagMetricName.String()].Value) // self lag value, because scope name is in metric name + assert.EqualValues(t, 26, checkResult.Metrics[base.ThreadsRunningMetricName.String()].Value) // self value, because scope name is in metric name + assert.EqualValues(t, 17, checkResult.Metrics[base.CustomMetricName.String()].Value) // self value, because that's the default... + assert.EqualValues(t, 5.1, checkResult.Metrics[base.LoadAvgMetricName.String()].Value) // shard value, because scope name is in metric name + assert.EqualValues(t, base.SelfScope.String(), checkResult.Metrics[base.LagMetricName.String()].Scope) + assert.EqualValues(t, base.SelfScope.String(), checkResult.Metrics[base.ThreadsRunningMetricName.String()].Scope) + assert.EqualValues(t, base.SelfScope.String(), checkResult.Metrics[base.CustomMetricName.String()].Scope) + assert.EqualValues(t, base.ShardScope.String(), checkResult.Metrics[base.LoadAvgMetricName.String()].Scope) + }) + }) + // done + }) +} + func TestReplica(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) + ctx := context.Background() // for development, replace with ctx := utils.LeakCheckContext(t) + ctx, cancel := context.WithCancel(ctx) defer cancel() throttler := newTestThrottler() @@ -558,52 +1682,227 @@ func TestReplica(t *testing.T) { tmClient, ok := throttler.overrideTmClient.(*fakeTMClient) require.True(t, ok) assert.Empty(t, tmClient.AppNames()) - + { + _, ok := throttler.recentApps.Get(throttlerapp.VitessName.String()) + assert.False(t, ok) + } runThrottler(t, ctx, throttler, time.Minute, func(t *testing.T, ctx context.Context) { assert.Empty(t, tmClient.AppNames()) - flags := &CheckFlags{} + flags := &CheckFlags{ + Scope: base.SelfScope, + MultiMetricsEnabled: true, + } { - checkResult := throttler.CheckByType(ctx, throttlerapp.VitessName.String(), "", flags, ThrottleCheckSelf) + checkResult := throttler.Check(ctx, throttlerapp.VitessName.String(), nil, flags) + assert.NotNil(t, checkResult) assert.False(t, checkResult.RecentlyChecked) // "vitess" app does not mark the throttler as recently checked assert.False(t, throttler.recentlyChecked()) // "vitess" app does not mark the throttler as recently checked - } - go func() { - select { - case <-ctx.Done(): - require.FailNow(t, "context expired before testing completed") - case <-time.After(time.Second): - assert.Empty(t, tmClient.AppNames()) - } - throttler.CheckByType(ctx, throttlerapp.OnlineDDLName.String(), "", flags, ThrottleCheckSelf) - select { - case <-ctx.Done(): - require.FailNow(t, "context expired before testing completed") - case <-time.After(time.Second): - appNames := tmClient.AppNames() - assert.NotEmpty(t, appNames) - assert.Containsf(t, appNames, throttlerapp.ThrottlerStimulatorName.String(), "%+v", appNames) - assert.Equalf(t, 1, len(appNames), "%+v", appNames) - } - { - checkResult := throttler.CheckByType(ctx, throttlerapp.OnlineDDLName.String(), "", flags, ThrottleCheckSelf) - assert.True(t, checkResult.RecentlyChecked) - assert.True(t, throttler.recentlyChecked()) - } { - checkResult := throttler.CheckByType(ctx, throttlerapp.VitessName.String(), "", flags, ThrottleCheckSelf) - assert.True(t, checkResult.RecentlyChecked) // due to previous "online-ddl" check - assert.True(t, throttler.recentlyChecked()) // due to previous "online-ddl" check + _, ok := throttler.recentApps.Get(throttlerapp.VitessName.String()) + assert.True(t, ok) } + } + go func() { + defer cancel() // early termination + t.Run("checks", func(t *testing.T) { + select { + case <-ctx.Done(): + require.FailNow(t, "context expired before testing completed") + case <-time.After(time.Second): + assert.Empty(t, tmClient.AppNames()) + } + t.Run("validate stimulator", func(t *testing.T) { + checkResult := throttler.Check(ctx, throttlerapp.OnlineDDLName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.3, checkResult.Value) // self lag value + assert.EqualValues(t, http.StatusOK, checkResult.StatusCode) + assert.Len(t, checkResult.Metrics, 1) + select { + case <-ctx.Done(): + require.FailNow(t, "context expired before testing completed") + case <-time.After(time.Second): + appNames := tmClient.AppNames() + // The replica reports to the primary that it had been checked, by issuing a CheckThrottler + // on the primary using the ThrottlerStimulatorName app. + assert.Equal(t, []string{throttlerapp.ThrottlerStimulatorName.String()}, appNames) + } + }) + t.Run("validate stimulator", func(t *testing.T) { + { + checkResult := throttler.Check(ctx, throttlerapp.OnlineDDLName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.EqualValues(t, 0.3, checkResult.Value) // self lag value + assert.EqualValues(t, http.StatusOK, checkResult.StatusCode) + assert.Len(t, checkResult.Metrics, 1) + assert.True(t, checkResult.RecentlyChecked) + assert.True(t, throttler.recentlyChecked()) + { + recentApp, ok := throttler.recentAppsSnapshot()[throttlerapp.OnlineDDLName.String()] + require.True(t, ok) + assert.EqualValues(t, http.StatusOK, recentApp.StatusCode) + } + } + { + { + _, ok := throttler.recentApps.Get(throttlerapp.VitessName.String()) + assert.True(t, ok) + } + checkResult := throttler.Check(ctx, throttlerapp.VitessName.String(), nil, flags) + assert.True(t, checkResult.RecentlyChecked) // due to previous "online-ddl" check + assert.True(t, throttler.recentlyChecked()) // due to previous "online-ddl" check + { + _, ok := throttler.recentAppsSnapshot()[throttlerapp.VitessName.String()] + assert.True(t, ok) + } + } + select { + case <-ctx.Done(): + require.FailNow(t, "context expired before testing completed") + case <-time.After(time.Second): + // Due to stimulation rate limiting, we shouldn't see a 2nd CheckThrottler request. + appNames := tmClient.AppNames() + assert.Equal(t, []string{throttlerapp.ThrottlerStimulatorName.String()}, appNames) + } + }) + t.Run("validate multi-metric results", func(t *testing.T) { + checkResult := throttler.Check(ctx, throttlerapp.VitessName.String(), nil, flags) + require.NotNil(t, checkResult) + // loadavg value exceeds threshold. This will show up in the check result as an error. + assert.EqualValues(t, 2.718, checkResult.Value, "unexpected result: %+v", checkResult) // self lag value + assert.NotEqualValues(t, http.StatusOK, checkResult.StatusCode, "unexpected result: %+v", checkResult) + assert.Equal(t, len(base.KnownMetricNames), len(checkResult.Metrics)) + }) + t.Run("validate v20 non-multi-metric results", func(t *testing.T) { + flags := &CheckFlags{ + Scope: base.SelfScope, + MultiMetricsEnabled: false, + } + checkResult := throttler.Check(ctx, throttlerapp.VitessName.String(), nil, flags) + require.NotNil(t, checkResult) + // loadavg value exceeds threshold. But since "MultiMetricsEnabled: false", the + // throttler, acting as a replica, assumes it's being probed by a v20 primary, and + // therefore does not report any of the multi-metric errors back. It only ever + // reports the default metric. + assert.EqualValues(t, 0.3, checkResult.Value) // self lag value + assert.EqualValues(t, http.StatusOK, checkResult.StatusCode) + assert.EqualValues(t, 0.75, checkResult.Threshold) + // The replica will still report the multi-metrics, and that's fine. As long + // as it does not reflect any of their values in the checkResult.Value/StatusCode/Threshold/Error/Message. + assert.Equal(t, len(base.KnownMetricNames), len(checkResult.Metrics)) + }) + }) - select { - case <-ctx.Done(): - require.FailNow(t, "context expired before testing completed") - case <-time.After(time.Second): - // Due to stimulation rate limiting, we shouldn't see a 2nd CheckThrottler request. - appNames := tmClient.AppNames() - assert.Equalf(t, 1, len(appNames), "%+v", appNames) - } - cancel() // end test early + t.Run("metrics", func(t *testing.T) { + // See which metrics are available + checkResult := throttler.Check(ctx, throttlerapp.VitessName.String(), base.KnownMetricNames, flags) + require.NotNil(t, checkResult) + assert.Equal(t, len(base.KnownMetricNames), len(checkResult.Metrics)) + + for metricName, metricResult := range checkResult.Metrics { + val := metricResult.Value + threshold := metricResult.Threshold + scope := base.SelfScope + switch base.MetricName(metricName) { + case base.DefaultMetricName: + assert.NoError(t, metricResult.Error, "metricName=%v, value=%v, threshold=%v", metricName, metricResult.Value, metricResult.Threshold) + assert.Equalf(t, float64(0.3), val, "scope=%v, metricName=%v", scope, metricName) // same value as "lag" + assert.Equalf(t, float64(0.75), threshold, "scope=%v, metricName=%v", scope, metricName) + case base.LagMetricName: + assert.NoError(t, metricResult.Error, "metricName=%v, value=%v, threshold=%v", metricName, metricResult.Value, metricResult.Threshold) + assert.Equalf(t, float64(0.3), val, "scope=%v, metricName=%v", scope, metricName) + assert.Equalf(t, float64(0.75), threshold, "scope=%v, metricName=%v", scope, metricName) // default threshold + case base.ThreadsRunningMetricName: + assert.NoError(t, metricResult.Error, "metricName=%v, value=%v, threshold=%v", metricName, metricResult.Value, metricResult.Threshold) + assert.Equalf(t, float64(26), val, "scope=%v, metricName=%v", scope, metricName) + assert.Equalf(t, float64(100), threshold, "scope=%v, metricName=%v", scope, metricName) + case base.CustomMetricName: + assert.ErrorIs(t, metricResult.Error, base.ErrThresholdExceeded) + assert.Equalf(t, float64(0), threshold, "scope=%v, metricName=%v", scope, metricName) + case base.LoadAvgMetricName: + assert.ErrorIs(t, metricResult.Error, base.ErrThresholdExceeded) + assert.Equalf(t, float64(1), threshold, "scope=%v, metricName=%v", scope, metricName) + } + } + }) + t.Run("metrics not named", func(t *testing.T) { + checkResult := throttler.Check(ctx, testAppName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.Len(t, checkResult.Metrics, 1) + for metricName, metricResult := range checkResult.Metrics { + assert.Equal(t, base.LagMetricName, throttler.metricNameUsedAsDefault()) + assert.Equal(t, base.LagMetricName.String(), metricName) + val := metricResult.Value + threshold := metricResult.Threshold + scope := base.SelfScope + + assert.NoError(t, metricResult.Error, "metricName=%v, value=%v, threshold=%v", metricName, metricResult.Value, metricResult.Threshold) + assert.Equalf(t, float64(0.3), val, "scope=%v, metricName=%v", scope, metricName) + assert.Equalf(t, float64(0.75), threshold, "scope=%v, metricName=%v", scope, metricName) // default threshold + } + }) + t.Run("metrics names mapped", func(t *testing.T) { + throttler.appCheckedMetrics.Set(testAppName.String(), base.MetricNames{base.LoadAvgMetricName, base.LagMetricName, base.ThreadsRunningMetricName}, cache.DefaultExpiration) + defer throttler.appCheckedMetrics.Delete(testAppName.String()) + checkResult := throttler.Check(ctx, testAppName.String(), nil, flags) + require.NotNil(t, checkResult) + assert.Equal(t, 3, len(checkResult.Metrics)) + }) + t.Run("client, OK", func(t *testing.T) { + client := NewBackgroundClient(throttler, throttlerapp.TestingName, base.UndefinedScope) + checkOK := client.ThrottleCheckOK(ctx, "") + assert.True(t, checkOK) + }) + t.Run("client, metrics names mapped, OK", func(t *testing.T) { + // Specified metrics do not exceed threshold, therefore overall result should be OK. + throttler.appCheckedMetrics.Set(throttlerapp.TestingName.String(), base.MetricNames{base.LagMetricName, base.ThreadsRunningMetricName}, cache.DefaultExpiration) + defer throttler.appCheckedMetrics.Delete(throttlerapp.TestingName.String()) + client := NewBackgroundClient(throttler, throttlerapp.TestingName, base.UndefinedScope) + checkOK := client.ThrottleCheckOK(ctx, "") + assert.True(t, checkOK) + }) + t.Run("client, metrics names mapped, not OK", func(t *testing.T) { + // LoadAvgMetricName metric exceeds threshold, therefore overall check should be in error. + throttler.appCheckedMetrics.Set(throttlerapp.TestingName.String(), base.MetricNames{base.LagMetricName, base.LoadAvgMetricName, base.ThreadsRunningMetricName}, cache.DefaultExpiration) + defer throttler.appCheckedMetrics.Delete(throttlerapp.TestingName.String()) + client := NewBackgroundClient(throttler, throttlerapp.TestingName, base.UndefinedScope) + checkOK := client.ThrottleCheckOK(ctx, "") + assert.False(t, checkOK) + }) + + t.Run("custom query, metrics", func(t *testing.T) { + // For v20 backwards compatibility, we also report the standard metric/value in CheckResult: + checkResult := throttler.Check(ctx, testAppName.String(), nil, flags) + assert.NoError(t, checkResult.Error, "value=%v, threshold=%v", checkResult.Value, checkResult.Threshold) + assert.Equal(t, float64(0.3), checkResult.Value) + // Change custom threshold + throttler.MetricsThreshold.Store(math.Float64bits(0.1)) + <-runSerialFunction(t, ctx, throttler, func(ctx context.Context) { + throttler.refreshInventory(ctx) + }) + checkResult = throttler.Check(ctx, testAppName.String(), base.KnownMetricNames, flags) + require.NotNil(t, checkResult) + assert.Equal(t, len(base.KnownMetricNames), len(checkResult.Metrics)) + + assert.Equal(t, base.LagMetricName, throttler.metricNameUsedAsDefault()) + + for metricName, metricResult := range checkResult.Metrics { + switch base.MetricName(metricName) { + case base.CustomMetricName, + base.LagMetricName, // Lag metrics affected by the new low threshold + base.LoadAvgMetricName, + base.DefaultMetricName: + assert.Error(t, metricResult.Error, "metricName=%v, value=%v, threshold=%v", metricName, metricResult.Value, metricResult.Threshold) + assert.ErrorIs(t, metricResult.Error, base.ErrThresholdExceeded) + case base.ThreadsRunningMetricName: + assert.NoError(t, metricResult.Error, "metricName=%v, value=%v, threshold=%v", metricName, metricResult.Value, metricResult.Threshold) + } + } + }) + t.Run("client, not OK", func(t *testing.T) { + client := NewBackgroundClient(throttler, throttlerapp.TestingName, base.SelfScope) + checkOK := client.ThrottleCheckOK(ctx, "") + assert.False(t, checkOK) + }) }() }) } diff --git a/go/vt/vttablet/tabletserver/throttle/throttlerapp/app.go b/go/vt/vttablet/tabletserver/throttle/throttlerapp/app.go index 7594df6c1b2..6fef3db453a 100644 --- a/go/vt/vttablet/tabletserver/throttle/throttlerapp/app.go +++ b/go/vt/vttablet/tabletserver/throttle/throttlerapp/app.go @@ -39,11 +39,18 @@ func (n Name) ConcatenateString(s string) string { func (n Name) Concatenate(other Name) Name { return Name(n.ConcatenateString(other.String())) } +func (n Name) SplitStrings() []string { + return strings.Split(n.String(), ":") +} const ( - // DefaultName is the app name used by vitess when app doesn't indicate its name - DefaultName Name = "default" - VitessName Name = "vitess" + // AllName is a special catch-all name for all apps + AllName Name = "all" + // VitessName is used by vitess tablets when communicating between themselves, + // as well as for self checks. + // It is also the name used by checks that do not identify by any app name. + VitessName Name = "vitess" + // ThrottlerStimulatorName is used by a replica tablet to stimulate the throttler on the Primary tablet ThrottlerStimulatorName Name = "throttler-stimulator" TableGCName Name = "tablegc" @@ -63,6 +70,9 @@ const ( BinlogWatcherName Name = "binlog-watcher" MessagerName Name = "messager" SchemaTrackerName Name = "schema-tracker" + + TestingName Name = "test" + TestingAlwaysThrottlerName Name = "always-throttled-app" ) var ( diff --git a/go/vt/vttablet/tabletserver/throttle/throttlerapp/app_test.go b/go/vt/vttablet/tabletserver/throttle/throttlerapp/app_test.go index c468009c793..0a5969dd7de 100644 --- a/go/vt/vttablet/tabletserver/throttle/throttlerapp/app_test.go +++ b/go/vt/vttablet/tabletserver/throttle/throttlerapp/app_test.go @@ -51,3 +51,21 @@ func TestConcatenate(t *testing.T) { assert.Equal(t, Name("vreplication:rowstreamer"), rowstreamerName) assert.Equal(t, "vreplication:rowstreamer", rowstreamerName.String()) } + +func TestSplit(t *testing.T) { + { + n := Name("vreplication:vcopier") + parts := n.SplitStrings() + assert.Equal(t, []string{"vreplication", "vcopier"}, parts) + } + { + n := VReplicationName + parts := n.SplitStrings() + assert.Equal(t, []string{"vreplication"}, parts) + } + { + n := Name("") + parts := n.SplitStrings() + assert.Equal(t, []string{""}, parts) + } +} diff --git a/go/vt/vttablet/tabletserver/twopc.go b/go/vt/vttablet/tabletserver/twopc.go index e53dd40ca8a..0bdf4ac0c91 100644 --- a/go/vt/vttablet/tabletserver/twopc.go +++ b/go/vt/vttablet/tabletserver/twopc.go @@ -22,19 +22,17 @@ import ( "time" "vitess.io/vitess/go/constants/sidecar" - "vitess.io/vitess/go/vt/vttablet/tabletserver/tx" - "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/dbconfigs" "vitess.io/vitess/go/vt/dbconnpool" "vitess.io/vitess/go/vt/log" - "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/vterrors" - "vitess.io/vitess/go/vt/vttablet/tabletserver/connpool" - querypb "vitess.io/vitess/go/vt/proto/query" topodatapb "vitess.io/vitess/go/vt/proto/topodata" vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" + "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/vt/vttablet/tabletserver/connpool" + "vitess.io/vitess/go/vt/vttablet/tabletserver/tx" ) const ( @@ -49,15 +47,27 @@ const ( // DTStateRollback represents the ROLLBACK state for dt_state. DTStateRollback = querypb.TransactionState_ROLLBACK - sqlReadAllRedo = `select t.dtid, t.state, t.time_created, s.statement + readAllRedo = `select t.dtid, t.state, t.time_created, s.statement from %s.redo_state t - join %s.redo_statement s on t.dtid = s.dtid + join %s.redo_statement s on t.dtid = s.dtid order by t.dtid, s.id` - sqlReadAllTransactions = `select t.dtid, t.state, t.time_created, p.keyspace, p.shard + readAllTransactions = `select t.dtid, t.state, t.time_created, p.keyspace, p.shard from %s.dt_state t - join %s.dt_participant p on t.dtid = p.dtid + join %s.dt_participant p on t.dtid = p.dtid order by t.dtid, p.id` + + // Ordering by state in descending order to retrieve COMMIT, ROLLBACK, PREPARE in that sequence. + // Resolving COMMIT first is crucial because we need to address transactions where a commit decision has already been made but remains unresolved. + // For transactions with a commit decision, applications are already aware of the outcome and are waiting for the resolution. + // By addressing these first, we ensure atomic commits and improve user experience. For other transactions, the decision is typically to rollback. + readUnresolvedTransactions = `select t.dtid, t.state, p.keyspace, p.shard + from %s.dt_state t + join %s.dt_participant p on t.dtid = p.dtid + where time_created < %a + order by t.state desc, t.dtid` + + countUnresolvedTransactions = `select count(*) from %s.dt_state where time_created < %a` ) // TwoPC performs 2PC metadata management (MM) functions. @@ -72,15 +82,16 @@ type TwoPC struct { readAllRedo string countUnresolvedRedo *sqlparser.ParsedQuery - insertTransaction *sqlparser.ParsedQuery - insertParticipants *sqlparser.ParsedQuery - transition *sqlparser.ParsedQuery - deleteTransaction *sqlparser.ParsedQuery - deleteParticipants *sqlparser.ParsedQuery - readTransaction *sqlparser.ParsedQuery - readParticipants *sqlparser.ParsedQuery - readAbandoned *sqlparser.ParsedQuery - readAllTransactions string + insertTransaction *sqlparser.ParsedQuery + insertParticipants *sqlparser.ParsedQuery + transition *sqlparser.ParsedQuery + deleteTransaction *sqlparser.ParsedQuery + deleteParticipants *sqlparser.ParsedQuery + readTransaction *sqlparser.ParsedQuery + readParticipants *sqlparser.ParsedQuery + readUnresolvedTransactions *sqlparser.ParsedQuery + readAllTransactions string + countUnresolvedTransaction *sqlparser.ParsedQuery } // NewTwoPC creates a TwoPC variable. @@ -106,7 +117,7 @@ func (tpc *TwoPC) initializeQueries() { tpc.deleteRedoStmt = sqlparser.BuildParsedQuery( "delete from %s.redo_statement where dtid = %a", dbname, ":dtid") - tpc.readAllRedo = fmt.Sprintf(sqlReadAllRedo, dbname, dbname) + tpc.readAllRedo = fmt.Sprintf(readAllRedo, dbname, dbname) tpc.countUnresolvedRedo = sqlparser.BuildParsedQuery( "select count(*) from %s.redo_state where time_created < %a", dbname, ":time_created") @@ -132,10 +143,11 @@ func (tpc *TwoPC) initializeQueries() { tpc.readParticipants = sqlparser.BuildParsedQuery( "select keyspace, shard from %s.dt_participant where dtid = %a", dbname, ":dtid") - tpc.readAbandoned = sqlparser.BuildParsedQuery( - "select dtid, time_created from %s.dt_state where time_created < %a", + tpc.readAllTransactions = fmt.Sprintf(readAllTransactions, dbname, dbname) + tpc.readUnresolvedTransactions = sqlparser.BuildParsedQuery(readUnresolvedTransactions, + dbname, dbname, ":time_created") + tpc.countUnresolvedTransaction = sqlparser.BuildParsedQuery(countUnresolvedTransactions, dbname, ":time_created") - tpc.readAllTransactions = fmt.Sprintf(sqlReadAllTransactions, dbname, dbname) } // Open starts the TwoPC service. @@ -254,7 +266,7 @@ func (tpc *TwoPC) ReadAllRedo(ctx context.Context) (prepared, failed []*tx.Prepa return prepared, failed, nil } -// CountUnresolvedRedo returns the number of prepared transactions that are still unresolved. +// CountUnresolvedRedo returns the number of prepared transaction recovery log that are older than the supplied time. func (tpc *TwoPC) CountUnresolvedRedo(ctx context.Context, unresolvedTime time.Time) (int64, error) { conn, err := tpc.readPool.Get(ctx, nil) if err != nil { @@ -269,9 +281,7 @@ func (tpc *TwoPC) CountUnresolvedRedo(ctx context.Context, unresolvedTime time.T if err != nil { return 0, err } - if len(qr.Rows) < 1 { - return 0, nil - } + // executed query is a scalar aggregation, so we can safely assume that the result is a single row. v, _ := qr.Rows[0][0].ToCastInt64() return v, nil } @@ -364,7 +374,7 @@ func (tpc *TwoPC) ReadTransaction(ctx context.Context, dtid string) (*querypb.Tr return nil, vterrors.Wrapf(err, "error parsing state for dtid %s", dtid) } result.State = querypb.TransactionState(st) - if result.State < querypb.TransactionState_PREPARE || result.State > querypb.TransactionState_ROLLBACK { + if result.State < querypb.TransactionState_PREPARE || result.State > querypb.TransactionState_COMMIT { return nil, fmt.Errorf("unexpected state for dtid %s: %v", dtid, result.State) } // A failure in time parsing will show up as a very old time, @@ -388,33 +398,6 @@ func (tpc *TwoPC) ReadTransaction(ctx context.Context, dtid string) (*querypb.Tr return result, nil } -// ReadAbandoned returns the list of abandoned transactions -// and their associated start time. -func (tpc *TwoPC) ReadAbandoned(ctx context.Context, abandonTime time.Time) (map[string]time.Time, error) { - conn, err := tpc.readPool.Get(ctx, nil) - if err != nil { - return nil, err - } - defer conn.Recycle() - - bindVars := map[string]*querypb.BindVariable{ - "time_created": sqltypes.Int64BindVariable(abandonTime.UnixNano()), - } - qr, err := tpc.read(ctx, conn.Conn, tpc.readAbandoned, bindVars) - if err != nil { - return nil, err - } - txs := make(map[string]time.Time, len(qr.Rows)) - for _, row := range qr.Rows { - t, err := row[1].ToCastInt64() - if err != nil { - return nil, err - } - txs[row[0].ToString()] = time.Unix(0, t) - } - return txs, nil -} - // ReadAllTransactions returns info about all distributed transactions. func (tpc *TwoPC) ReadAllTransactions(ctx context.Context) ([]*tx.DistributedTx, error) { conn, err := tpc.readPool.Get(ctx, nil) @@ -444,7 +427,7 @@ func (tpc *TwoPC) ReadAllTransactions(ctx context.Context) ([]*tx.DistributedTx, log.Errorf("Error parsing state for dtid %s: %v.", dtid, err) } protostate := querypb.TransactionState(st) - if protostate < querypb.TransactionState_UNKNOWN || protostate > querypb.TransactionState_ROLLBACK { + if protostate < querypb.TransactionState_PREPARE || protostate > querypb.TransactionState_COMMIT { log.Errorf("Unexpected state for dtid %s: %v.", dtid, protostate) } curTx = &tx.DistributedTx{ @@ -475,5 +458,91 @@ func (tpc *TwoPC) read(ctx context.Context, conn *connpool.Conn, pq *sqlparser.P if err != nil { return nil, err } + // TODO: check back for limit, 10k is too high already to have unresolved transactions. return conn.Exec(ctx, q, 10000, false) } + +// UnresolvedTransactions returns the list of unresolved transactions +// the list from database is retrieved as +// dtid | state | keyspace | shard +// 1 | PREPARE | ks | 40-80 +// 1 | PREPARE | ks | 80-c0 +// 2 | COMMIT | ks | -40 +// Here there are 2 dtids with 2 participants for dtid:1 and 1 participant for dtid:2. +func (tpc *TwoPC) UnresolvedTransactions(ctx context.Context, abandonTime time.Time) ([]*querypb.TransactionMetadata, error) { + conn, err := tpc.readPool.Get(ctx, nil) + if err != nil { + return nil, err + } + defer conn.Recycle() + + bindVars := map[string]*querypb.BindVariable{ + "time_created": sqltypes.Int64BindVariable(abandonTime.UnixNano()), + } + qr, err := tpc.read(ctx, conn.Conn, tpc.readUnresolvedTransactions, bindVars) + if err != nil { + return nil, err + } + + var ( + txs []*querypb.TransactionMetadata + currentTx *querypb.TransactionMetadata + ) + + appendCurrentTx := func() { + if currentTx != nil { + txs = append(txs, currentTx) + } + } + + for _, row := range qr.Rows { + // Extract the distributed transaction ID from the row + dtid := row[0].ToString() + + // Check if we are starting a new transaction + if currentTx == nil || currentTx.Dtid != dtid { + // If we have an existing transaction, append it to the list + appendCurrentTx() + + // Extract the transaction state and initialize a new TransactionMetadata + stateID, _ := row[1].ToInt() + currentTx = &querypb.TransactionMetadata{ + Dtid: dtid, + State: querypb.TransactionState(stateID), + Participants: []*querypb.Target{}, + } + } + + // Add the current participant (keyspace and shard) to the transaction + currentTx.Participants = append(currentTx.Participants, &querypb.Target{ + Keyspace: row[2].ToString(), + Shard: row[3].ToString(), + TabletType: topodatapb.TabletType_PRIMARY, + }) + } + + // Append the last transaction if it exists + appendCurrentTx() + + return txs, nil +} + +// CountUnresolvedTransaction returns the number of transaction record that are older than the given time. +func (tpc *TwoPC) CountUnresolvedTransaction(ctx context.Context, unresolvedTime time.Time) (int64, error) { + conn, err := tpc.readPool.Get(ctx, nil) + if err != nil { + return 0, err + } + defer conn.Recycle() + + bindVars := map[string]*querypb.BindVariable{ + "time_created": sqltypes.Int64BindVariable(unresolvedTime.UnixNano()), + } + qr, err := tpc.read(ctx, conn.Conn, tpc.countUnresolvedTransaction, bindVars) + if err != nil { + return 0, err + } + // executed query is a scalar aggregation, so we can safely assume that the result is a single row. + v, _ := qr.Rows[0][0].ToCastInt64() + return v, nil +} diff --git a/go/vt/vttablet/tabletserver/twopc_test.go b/go/vt/vttablet/tabletserver/twopc_test.go index 2ef5e05b7c7..cc9e987664c 100644 --- a/go/vt/vttablet/tabletserver/twopc_test.go +++ b/go/vt/vttablet/tabletserver/twopc_test.go @@ -23,11 +23,13 @@ import ( "testing" "time" - "vitess.io/vitess/go/vt/vttablet/tabletserver/tx" + "github.com/stretchr/testify/require" "vitess.io/vitess/go/sqltypes" - + "vitess.io/vitess/go/test/utils" querypb "vitess.io/vitess/go/vt/proto/query" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" + "vitess.io/vitess/go/vt/vttablet/tabletserver/tx" ) func TestReadAllRedo(t *testing.T) { @@ -396,3 +398,74 @@ func jsonStr(v any) string { out, _ := json.Marshal(v) return string(out) } + +// TestUnresolvedTransactions tests the retrieval of unresolved transactions from the database and +// providing the output in proto format. +func TestUnresolvedTransactions(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + _, tsv, db := newTestTxExecutor(t, ctx) + defer db.Close() + defer tsv.StopService() + + conn, err := tsv.qe.conns.Get(ctx, nil) + require.NoError(t, err) + defer conn.Recycle() + + tcases := []struct { + name string + unresolvedTx *sqltypes.Result + expectedTx []*querypb.TransactionMetadata + }{{ + name: "no unresolved transactions", + unresolvedTx: &sqltypes.Result{}, + }, { + name: "one unresolved transaction", + unresolvedTx: sqltypes.MakeTestResult( + sqltypes.MakeTestFields("dtid|state|keyspace|shard", + "VARBINARY|INT64|VARCHAR|VARCHAR"), + "dtid0|1|ks01|shard01", + "dtid0|1|ks01|shard02"), + expectedTx: []*querypb.TransactionMetadata{{ + Dtid: "dtid0", + State: querypb.TransactionState_PREPARE, + Participants: []*querypb.Target{ + {Keyspace: "ks01", Shard: "shard01", TabletType: topodatapb.TabletType_PRIMARY}, + {Keyspace: "ks01", Shard: "shard02", TabletType: topodatapb.TabletType_PRIMARY}, + }}}, + }, { + name: "two unresolved transaction", + unresolvedTx: sqltypes.MakeTestResult( + sqltypes.MakeTestFields("dtid|state|keyspace|shard", + "VARBINARY|INT64|VARCHAR|VARCHAR"), + "dtid0|3|ks01|shard01", + "dtid0|3|ks01|shard02", + "dtid1|2|ks02|shard03", + "dtid1|2|ks01|shard02"), + expectedTx: []*querypb.TransactionMetadata{{ + Dtid: "dtid0", + State: querypb.TransactionState_COMMIT, + Participants: []*querypb.Target{ + {Keyspace: "ks01", Shard: "shard01", TabletType: topodatapb.TabletType_PRIMARY}, + {Keyspace: "ks01", Shard: "shard02", TabletType: topodatapb.TabletType_PRIMARY}, + }}, { + Dtid: "dtid1", + State: querypb.TransactionState_ROLLBACK, + Participants: []*querypb.Target{ + {Keyspace: "ks02", Shard: "shard03", TabletType: topodatapb.TabletType_PRIMARY}, + {Keyspace: "ks01", Shard: "shard02", TabletType: topodatapb.TabletType_PRIMARY}, + }}, + }, + }} + + tpc := tsv.te.twoPC + txQueryPattern := `.*time_created < 1000.*` + for _, tcase := range tcases { + t.Run(tcase.name, func(t *testing.T) { + db.AddQueryPattern(txQueryPattern, tcase.unresolvedTx) + distributed, err := tpc.UnresolvedTransactions(ctx, time.UnixMicro(1)) + require.NoError(t, err) + utils.MustMatch(t, tcase.expectedTx, distributed) + }) + } +} diff --git a/go/vt/vttablet/tabletserver/twopcz.go b/go/vt/vttablet/tabletserver/twopcz.go index e9547c311bd..51ed457c679 100644 --- a/go/vt/vttablet/tabletserver/twopcz.go +++ b/go/vt/vttablet/tabletserver/twopcz.go @@ -130,7 +130,7 @@ var ( `)) ) -func twopczHandler(txe *TxExecutor, w http.ResponseWriter, r *http.Request) { +func twopczHandler(txe *DTExecutor, w http.ResponseWriter, r *http.Request) { if err := acl.CheckAccessHTTP(r, acl.DEBUGGING); err != nil { acl.SendError(w, err) return diff --git a/go/vt/vttablet/tabletserver/tx_engine.go b/go/vt/vttablet/tabletserver/tx_engine.go index 7e8ecc06a75..57c6ff1fd64 100644 --- a/go/vt/vttablet/tabletserver/tx_engine.go +++ b/go/vt/vttablet/tabletserver/tx_engine.go @@ -28,16 +28,14 @@ import ( "vitess.io/vitess/go/vt/concurrency" "vitess.io/vitess/go/vt/dtids" "vitess.io/vitess/go/vt/log" + querypb "vitess.io/vitess/go/vt/proto/query" + vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" "vitess.io/vitess/go/vt/servenv" "vitess.io/vitess/go/vt/vterrors" - "vitess.io/vitess/go/vt/vtgate/vtgateconn" "vitess.io/vitess/go/vt/vttablet/tabletserver/connpool" "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" "vitess.io/vitess/go/vt/vttablet/tabletserver/tx" "vitess.io/vitess/go/vt/vttablet/tabletserver/txlimiter" - - querypb "vitess.io/vitess/go/vt/proto/query" - vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" ) type txEngineState int @@ -90,10 +88,11 @@ type TxEngine struct { preparedPool *TxPreparedPool twoPC *TwoPC twoPCReady sync.WaitGroup + dxNotify func() } // NewTxEngine creates a new TxEngine. -func NewTxEngine(env tabletenv.Env) *TxEngine { +func NewTxEngine(env tabletenv.Env, dxNotifier func()) *TxEngine { config := env.Config() te := &TxEngine{ env: env, @@ -104,16 +103,11 @@ func NewTxEngine(env tabletenv.Env) *TxEngine { te.txPool = NewTxPool(env, limiter) te.twopcEnabled = config.TwoPCEnable if te.twopcEnabled { - if config.TwoPCCoordinatorAddress == "" { - log.Error("Coordinator address not specified: Disabling 2PC") - te.twopcEnabled = false - } if config.TwoPCAbandonAge <= 0 { log.Error("2PC abandon age not specified: Disabling 2PC") te.twopcEnabled = false } } - te.coordinatorAddress = config.TwoPCCoordinatorAddress te.abandonAge = config.TwoPCAbandonAge.Get() te.ticks = timer.NewTimer(te.abandonAge / 2) @@ -128,6 +122,7 @@ func NewTxEngine(env tabletenv.Env) *TxEngine { IdleTimeout: env.Config().TxPool.IdleTimeout, }) te.twoPC = NewTwoPC(readPool) + te.dxNotify = dxNotifier te.state = NotServing return te } @@ -181,7 +176,7 @@ func (te *TxEngine) transition(state txEngineState) { te.env.Stats().InternalErrors.Add("TwopcResurrection", 1) log.Errorf("Could not prepare transactions: %v", err) } - te.startWatchdog() + te.startTransactionWatcher() }() } } @@ -312,7 +307,7 @@ func (te *TxEngine) shutdownLocked() { // Shut down functions are idempotent. // No need to check if 2pc is enabled. log.Infof("TxEngine - stop watchdog") - te.stopWatchdog() + te.stopTransactionWatcher() poolEmpty := make(chan bool) rollbackDone := make(chan bool) @@ -453,58 +448,37 @@ func (te *TxEngine) rollbackPrepared() { } } -// startWatchdog starts the watchdog goroutine, which looks for abandoned +// startTransactionWatcher starts the watchdog goroutine, which looks for abandoned // transactions and calls the notifier on them. -func (te *TxEngine) startWatchdog() { +func (te *TxEngine) startTransactionWatcher() { te.ticks.Start(func() { ctx, cancel := context.WithTimeout(tabletenv.LocalContext(), te.abandonAge/4) defer cancel() // Raise alerts on prepares that have been unresolved for too long. - // Use 5x abandonAge to give opportunity for watchdog to resolve these. + // Use 5x abandonAge to give opportunity for transaction coordinator to resolve these redo logs. count, err := te.twoPC.CountUnresolvedRedo(ctx, time.Now().Add(-te.abandonAge*5)) if err != nil { - te.env.Stats().InternalErrors.Add("WatchdogFail", 1) - log.Errorf("Error reading unresolved prepares: '%v': %v", te.coordinatorAddress, err) + te.env.Stats().InternalErrors.Add("RedoWatcherFail", 1) + log.Errorf("Error reading prepared transactions: %v", err) } te.env.Stats().Unresolved.Set("Prepares", count) - // Resolve lingering distributed transactions. - txs, err := te.twoPC.ReadAbandoned(ctx, time.Now().Add(-te.abandonAge)) - if err != nil { - te.env.Stats().InternalErrors.Add("WatchdogFail", 1) - log.Errorf("Error reading transactions for 2pc watchdog: %v", err) - return - } - if len(txs) == 0 { - return - } - - coordConn, err := vtgateconn.Dial(ctx, te.coordinatorAddress) + // Notify lingering distributed transactions. + count, err = te.twoPC.CountUnresolvedTransaction(ctx, time.Now().Add(-te.abandonAge)) if err != nil { - te.env.Stats().InternalErrors.Add("WatchdogFail", 1) - log.Errorf("Error connecting to coordinator '%v': %v", te.coordinatorAddress, err) + te.env.Stats().InternalErrors.Add("TransactionWatcherFail", 1) + log.Errorf("Error reading unresolved transactions: %v", err) return } - defer coordConn.Close() - - var wg sync.WaitGroup - for tx := range txs { - wg.Add(1) - go func(dtid string) { - defer wg.Done() - if err := coordConn.ResolveTransaction(ctx, dtid); err != nil { - te.env.Stats().InternalErrors.Add("WatchdogFail", 1) - log.Errorf("Error notifying for dtid %s: %v", dtid, err) - } - }(tx) + if count > 0 { + te.dxNotify() } - wg.Wait() }) } -// stopWatchdog stops the watchdog goroutine. -func (te *TxEngine) stopWatchdog() { +// stopTransactionWatcher stops the watchdog goroutine. +func (te *TxEngine) stopTransactionWatcher() { te.ticks.Stop() } diff --git a/go/vt/vttablet/tabletserver/tx_engine_test.go b/go/vt/vttablet/tabletserver/tx_engine_test.go index 3c3a8a4eb4f..95057d754fb 100644 --- a/go/vt/vttablet/tabletserver/tx_engine_test.go +++ b/go/vt/vttablet/tabletserver/tx_engine_test.go @@ -49,7 +49,7 @@ func TestTxEngineClose(t *testing.T) { cfg.TxPool.Size = 10 cfg.Oltp.TxTimeout = 100 * time.Millisecond cfg.GracePeriods.Shutdown = 0 - te := NewTxEngine(tabletenv.NewEnv(vtenv.NewTestEnv(), cfg, "TabletServerTest")) + te := NewTxEngine(tabletenv.NewEnv(vtenv.NewTestEnv(), cfg, "TabletServerTest"), nil) // Normal close. te.AcceptReadWrite() @@ -152,7 +152,7 @@ func TestTxEngineBegin(t *testing.T) { db.AddQueryPattern(".*", &sqltypes.Result{}) cfg := tabletenv.NewDefaultConfig() cfg.DB = newDBConfigs(db) - te := NewTxEngine(tabletenv.NewEnv(vtenv.NewTestEnv(), cfg, "TabletServerTest")) + te := NewTxEngine(tabletenv.NewEnv(vtenv.NewTestEnv(), cfg, "TabletServerTest"), nil) for _, exec := range []func() (int64, string, error){ func() (int64, string, error) { @@ -198,7 +198,7 @@ func TestTxEngineRenewFails(t *testing.T) { db.AddQueryPattern(".*", &sqltypes.Result{}) cfg := tabletenv.NewDefaultConfig() cfg.DB = newDBConfigs(db) - te := NewTxEngine(tabletenv.NewEnv(vtenv.NewTestEnv(), cfg, "TabletServerTest")) + te := NewTxEngine(tabletenv.NewEnv(vtenv.NewTestEnv(), cfg, "TabletServerTest"), nil) te.AcceptReadOnly() options := &querypb.ExecuteOptions{} connID, _, err := te.ReserveBegin(ctx, options, nil, nil) @@ -536,7 +536,7 @@ func setupTxEngine(db *fakesqldb.DB) *TxEngine { cfg.TxPool.Size = 10 cfg.Oltp.TxTimeout = 100 * time.Millisecond cfg.GracePeriods.Shutdown = 0 - te := NewTxEngine(tabletenv.NewEnv(vtenv.NewTestEnv(), cfg, "TabletServerTest")) + te := NewTxEngine(tabletenv.NewEnv(vtenv.NewTestEnv(), cfg, "TabletServerTest"), nil) return te } @@ -568,7 +568,7 @@ func TestTxEngineFailReserve(t *testing.T) { db.AddQueryPattern(".*", &sqltypes.Result{}) cfg := tabletenv.NewDefaultConfig() cfg.DB = newDBConfigs(db) - te := NewTxEngine(tabletenv.NewEnv(vtenv.NewTestEnv(), cfg, "TabletServerTest")) + te := NewTxEngine(tabletenv.NewEnv(vtenv.NewTestEnv(), cfg, "TabletServerTest"), nil) options := &querypb.ExecuteOptions{} _, err := te.Reserve(ctx, options, 0, nil) diff --git a/go/vt/vttablet/tabletserver/txthrottler/mock_throttler_test.go b/go/vt/vttablet/tabletserver/txthrottler/mock_throttler_test.go index aeb75d258a3..327a37dc43f 100644 --- a/go/vt/vttablet/tabletserver/txthrottler/mock_throttler_test.go +++ b/go/vt/vttablet/tabletserver/txthrottler/mock_throttler_test.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: vitess.io/vitess/go/vt/vttablet/tabletserver/txthrottler (interfaces: ThrottlerInterface) +// Source: vitess.io/vitess/go/vt/throttler (interfaces: Throttler) // Package txthrottler is a generated GoMock package. package txthrottler @@ -13,45 +13,46 @@ import ( discovery "vitess.io/vitess/go/vt/discovery" throttlerdata "vitess.io/vitess/go/vt/proto/throttlerdata" topodata "vitess.io/vitess/go/vt/proto/topodata" + throttler "vitess.io/vitess/go/vt/throttler" ) -// MockThrottlerInterface is a mock of ThrottlerInterface interface. -type MockThrottlerInterface struct { +// MockThrottler is a mock of Throttler interface. +type MockThrottler struct { ctrl *gomock.Controller - recorder *MockThrottlerInterfaceMockRecorder + recorder *MockThrottlerMockRecorder } -// MockThrottlerInterfaceMockRecorder is the mock recorder for MockThrottlerInterface. -type MockThrottlerInterfaceMockRecorder struct { - mock *MockThrottlerInterface +// MockThrottlerMockRecorder is the mock recorder for MockThrottler. +type MockThrottlerMockRecorder struct { + mock *MockThrottler } -// NewMockThrottlerInterface creates a new mock instance. -func NewMockThrottlerInterface(ctrl *gomock.Controller) *MockThrottlerInterface { - mock := &MockThrottlerInterface{ctrl: ctrl} - mock.recorder = &MockThrottlerInterfaceMockRecorder{mock} +// NewMockThrottler creates a new mock instance. +func NewMockThrottler(ctrl *gomock.Controller) *MockThrottler { + mock := &MockThrottler{ctrl: ctrl} + mock.recorder = &MockThrottlerMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockThrottlerInterface) EXPECT() *MockThrottlerInterfaceMockRecorder { +func (m *MockThrottler) EXPECT() *MockThrottlerMockRecorder { return m.recorder } // Close mocks base method. -func (m *MockThrottlerInterface) Close() { +func (m *MockThrottler) Close() { m.ctrl.T.Helper() m.ctrl.Call(m, "Close") } // Close indicates an expected call of Close. -func (mr *MockThrottlerInterfaceMockRecorder) Close() *gomock.Call { +func (mr *MockThrottlerMockRecorder) Close() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockThrottlerInterface)(nil).Close)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockThrottler)(nil).Close)) } // GetConfiguration mocks base method. -func (m *MockThrottlerInterface) GetConfiguration() *throttlerdata.Configuration { +func (m *MockThrottler) GetConfiguration() *throttlerdata.Configuration { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetConfiguration") ret0, _ := ret[0].(*throttlerdata.Configuration) @@ -59,27 +60,41 @@ func (m *MockThrottlerInterface) GetConfiguration() *throttlerdata.Configuration } // GetConfiguration indicates an expected call of GetConfiguration. -func (mr *MockThrottlerInterfaceMockRecorder) GetConfiguration() *gomock.Call { +func (mr *MockThrottlerMockRecorder) GetConfiguration() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetConfiguration", reflect.TypeOf((*MockThrottlerInterface)(nil).GetConfiguration)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetConfiguration", reflect.TypeOf((*MockThrottler)(nil).GetConfiguration)) +} + +// Log mocks base method. +func (m *MockThrottler) Log() []throttler.Result { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Log") + ret0, _ := ret[0].([]throttler.Result) + return ret0 +} + +// Log indicates an expected call of Log. +func (mr *MockThrottlerMockRecorder) Log() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Log", reflect.TypeOf((*MockThrottler)(nil).Log)) } // MaxLag mocks base method. -func (m *MockThrottlerInterface) MaxLag(tabletType topodata.TabletType) uint32 { +func (m *MockThrottler) MaxLag(arg0 topodata.TabletType) uint32 { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "MaxLag", tabletType) + ret := m.ctrl.Call(m, "MaxLag", arg0) ret0, _ := ret[0].(uint32) return ret0 } -// MaxLag indicates an expected call of LastMaxLagNotIgnoredForTabletType. -func (mr *MockThrottlerInterfaceMockRecorder) MaxLag(tabletType interface{}) *gomock.Call { +// MaxLag indicates an expected call of MaxLag. +func (mr *MockThrottlerMockRecorder) MaxLag(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MaxLag", reflect.TypeOf((*MockThrottlerInterface)(nil).MaxLag), tabletType) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MaxLag", reflect.TypeOf((*MockThrottler)(nil).MaxLag), arg0) } // MaxRate mocks base method. -func (m *MockThrottlerInterface) MaxRate() int64 { +func (m *MockThrottler) MaxRate() int64 { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "MaxRate") ret0, _ := ret[0].(int64) @@ -87,61 +102,61 @@ func (m *MockThrottlerInterface) MaxRate() int64 { } // MaxRate indicates an expected call of MaxRate. -func (mr *MockThrottlerInterfaceMockRecorder) MaxRate() *gomock.Call { +func (mr *MockThrottlerMockRecorder) MaxRate() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MaxRate", reflect.TypeOf((*MockThrottlerInterface)(nil).MaxRate)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MaxRate", reflect.TypeOf((*MockThrottler)(nil).MaxRate)) } // RecordReplicationLag mocks base method. -func (m *MockThrottlerInterface) RecordReplicationLag(arg0 time.Time, arg1 *discovery.TabletHealth) { +func (m *MockThrottler) RecordReplicationLag(arg0 time.Time, arg1 *discovery.TabletHealth) { m.ctrl.T.Helper() m.ctrl.Call(m, "RecordReplicationLag", arg0, arg1) } // RecordReplicationLag indicates an expected call of RecordReplicationLag. -func (mr *MockThrottlerInterfaceMockRecorder) RecordReplicationLag(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockThrottlerMockRecorder) RecordReplicationLag(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordReplicationLag", reflect.TypeOf((*MockThrottlerInterface)(nil).RecordReplicationLag), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordReplicationLag", reflect.TypeOf((*MockThrottler)(nil).RecordReplicationLag), arg0, arg1) } // ResetConfiguration mocks base method. -func (m *MockThrottlerInterface) ResetConfiguration() { +func (m *MockThrottler) ResetConfiguration() { m.ctrl.T.Helper() m.ctrl.Call(m, "ResetConfiguration") } // ResetConfiguration indicates an expected call of ResetConfiguration. -func (mr *MockThrottlerInterfaceMockRecorder) ResetConfiguration() *gomock.Call { +func (mr *MockThrottlerMockRecorder) ResetConfiguration() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResetConfiguration", reflect.TypeOf((*MockThrottlerInterface)(nil).ResetConfiguration)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResetConfiguration", reflect.TypeOf((*MockThrottler)(nil).ResetConfiguration)) } // SetMaxRate mocks base method. -func (m *MockThrottlerInterface) SetMaxRate(arg0 int64) { +func (m *MockThrottler) SetMaxRate(arg0 int64) { m.ctrl.T.Helper() m.ctrl.Call(m, "SetMaxRate", arg0) } // SetMaxRate indicates an expected call of SetMaxRate. -func (mr *MockThrottlerInterfaceMockRecorder) SetMaxRate(arg0 interface{}) *gomock.Call { +func (mr *MockThrottlerMockRecorder) SetMaxRate(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetMaxRate", reflect.TypeOf((*MockThrottlerInterface)(nil).SetMaxRate), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetMaxRate", reflect.TypeOf((*MockThrottler)(nil).SetMaxRate), arg0) } // ThreadFinished mocks base method. -func (m *MockThrottlerInterface) ThreadFinished(arg0 int) { +func (m *MockThrottler) ThreadFinished(arg0 int) { m.ctrl.T.Helper() m.ctrl.Call(m, "ThreadFinished", arg0) } // ThreadFinished indicates an expected call of ThreadFinished. -func (mr *MockThrottlerInterfaceMockRecorder) ThreadFinished(arg0 interface{}) *gomock.Call { +func (mr *MockThrottlerMockRecorder) ThreadFinished(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ThreadFinished", reflect.TypeOf((*MockThrottlerInterface)(nil).ThreadFinished), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ThreadFinished", reflect.TypeOf((*MockThrottler)(nil).ThreadFinished), arg0) } // Throttle mocks base method. -func (m *MockThrottlerInterface) Throttle(arg0 int) time.Duration { +func (m *MockThrottler) Throttle(arg0 int) time.Duration { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Throttle", arg0) ret0, _ := ret[0].(time.Duration) @@ -149,13 +164,13 @@ func (m *MockThrottlerInterface) Throttle(arg0 int) time.Duration { } // Throttle indicates an expected call of Throttle. -func (mr *MockThrottlerInterfaceMockRecorder) Throttle(arg0 interface{}) *gomock.Call { +func (mr *MockThrottlerMockRecorder) Throttle(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Throttle", reflect.TypeOf((*MockThrottlerInterface)(nil).Throttle), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Throttle", reflect.TypeOf((*MockThrottler)(nil).Throttle), arg0) } // UpdateConfiguration mocks base method. -func (m *MockThrottlerInterface) UpdateConfiguration(arg0 *throttlerdata.Configuration, arg1 bool) error { +func (m *MockThrottler) UpdateConfiguration(arg0 *throttlerdata.Configuration, arg1 bool) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "UpdateConfiguration", arg0, arg1) ret0, _ := ret[0].(error) @@ -163,7 +178,7 @@ func (m *MockThrottlerInterface) UpdateConfiguration(arg0 *throttlerdata.Configu } // UpdateConfiguration indicates an expected call of UpdateConfiguration. -func (mr *MockThrottlerInterfaceMockRecorder) UpdateConfiguration(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockThrottlerMockRecorder) UpdateConfiguration(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateConfiguration", reflect.TypeOf((*MockThrottlerInterface)(nil).UpdateConfiguration), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateConfiguration", reflect.TypeOf((*MockThrottler)(nil).UpdateConfiguration), arg0, arg1) } diff --git a/go/vt/vttablet/tabletserver/txthrottler/tx_throttler.go b/go/vt/vttablet/tabletserver/txthrottler/tx_throttler.go index 11615d52af5..41f075e3802 100644 --- a/go/vt/vttablet/tabletserver/txthrottler/tx_throttler.go +++ b/go/vt/vttablet/tabletserver/txthrottler/tx_throttler.go @@ -19,7 +19,7 @@ package txthrottler import ( "context" "math/rand/v2" - "reflect" + "slices" "strings" "sync" "sync/atomic" @@ -34,7 +34,6 @@ import ( "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" querypb "vitess.io/vitess/go/vt/proto/query" - throttlerdatapb "vitess.io/vitess/go/vt/proto/throttlerdata" topodatapb "vitess.io/vitess/go/vt/proto/topodata" ) @@ -42,7 +41,7 @@ import ( // and go/vt/throttler. These are provided here so that they can be overridden // in tests to generate mocks. type healthCheckFactoryFunc func(topoServer *topo.Server, cell string, cellsToWatch []string) discovery.HealthCheck -type throttlerFactoryFunc func(name, unit string, threadCount int, maxRate int64, maxReplicationLagConfig throttler.MaxReplicationLagModuleConfig) (ThrottlerInterface, error) +type throttlerFactoryFunc func(name, unit string, threadCount int, maxRate int64, maxReplicationLagConfig throttler.MaxReplicationLagModuleConfig) (throttler.Throttler, error) var ( healthCheckFactory healthCheckFactoryFunc @@ -53,7 +52,7 @@ func resetTxThrottlerFactories() { healthCheckFactory = func(topoServer *topo.Server, cell string, cellsToWatch []string) discovery.HealthCheck { return discovery.NewHealthCheck(context.Background(), discovery.DefaultHealthCheckRetryDelay, discovery.DefaultHealthCheckTimeout, topoServer, cell, strings.Join(cellsToWatch, ",")) } - throttlerFactory = func(name, unit string, threadCount int, maxRate int64, maxReplicationLagConfig throttler.MaxReplicationLagModuleConfig) (ThrottlerInterface, error) { + throttlerFactory = func(name, unit string, threadCount int, maxRate int64, maxReplicationLagConfig throttler.MaxReplicationLagModuleConfig) (throttler.Throttler, error) { return throttler.NewThrottlerFromConfig(name, unit, threadCount, maxRate, maxReplicationLagConfig, time.Now) } } @@ -72,21 +71,6 @@ type TxThrottler interface { Throttle(priority int, workload string) (result bool) } -// ThrottlerInterface defines the public interface that is implemented by go/vt/throttler.Throttler -// It is only used here to allow mocking out a throttler object. -type ThrottlerInterface interface { - Throttle(threadID int) time.Duration - ThreadFinished(threadID int) - Close() - MaxRate() int64 - SetMaxRate(rate int64) - RecordReplicationLag(time time.Time, th *discovery.TabletHealth) - GetConfiguration() *throttlerdatapb.Configuration - UpdateConfiguration(configuration *throttlerdatapb.Configuration, copyZeroValues bool) error - ResetConfiguration() - MaxLag(tabletType topodatapb.TabletType) uint32 -} - // TxThrottlerName is the name the wrapped go/vt/throttler object will be registered with // go/vt/throttler.GlobalManager. const TxThrottlerName = "TransactionThrottler" @@ -164,7 +148,7 @@ type txThrottlerStateImpl struct { // throttleMu serializes calls to throttler.Throttler.Throttle(threadId). // That method is required to be called in serial for each threadId. throttleMu sync.Mutex - throttler ThrottlerInterface + throttler throttler.Throttler cellsFromTopo bool healthCheck discovery.HealthCheck @@ -327,6 +311,7 @@ func newTxThrottlerState(txThrottler *txThrottler, config *tabletenv.TabletConfi func (ts *txThrottlerStateImpl) initHealthCheck() { ts.healthCheck = healthCheckFactory(ts.txThrottler.topoServer, ts.target.Cell, ts.healthCheckCells) ts.healthCheckChan = ts.healthCheck.Subscribe() + ts.healthCheck.RegisterStats() } func (ts *txThrottlerStateImpl) closeHealthCheck() { @@ -345,7 +330,7 @@ func (ts *txThrottlerStateImpl) updateHealthCheckCells(ctx context.Context) { defer cancel() knownCells := fetchKnownCells(fetchCtx, ts.txThrottler.topoServer, ts.target) - if !reflect.DeepEqual(knownCells, ts.healthCheckCells) { + if !slices.Equal(knownCells, ts.healthCheckCells) { log.Info("txThrottler: restarting healthcheck stream due to topology cells update") ts.healthCheckCells = knownCells ts.closeHealthCheck() diff --git a/go/vt/vttablet/tabletserver/txthrottler/tx_throttler_test.go b/go/vt/vttablet/tabletserver/txthrottler/tx_throttler_test.go index da761855c38..3e46e79c70b 100644 --- a/go/vt/vttablet/tabletserver/txthrottler/tx_throttler_test.go +++ b/go/vt/vttablet/tabletserver/txthrottler/tx_throttler_test.go @@ -18,7 +18,7 @@ package txthrottler // Commands to generate the mocks for this test. //go:generate mockgen -destination mock_healthcheck_test.go -package txthrottler -mock_names "HealthCheck=MockHealthCheck" vitess.io/vitess/go/vt/discovery HealthCheck -//go:generate mockgen -destination mock_throttler_test.go -package txthrottler vitess.io/vitess/go/vt/vttablet/tabletserver/txthrottler ThrottlerInterface +//go:generate mockgen -destination mock_throttler_test.go -package txthrottler vitess.io/vitess/go/vt/throttler Throttler import ( "context" @@ -70,14 +70,17 @@ func TestEnabledThrottler(t *testing.T) { mockHealthCheck := NewMockHealthCheck(mockCtrl) hcCall1 := mockHealthCheck.EXPECT().Subscribe() hcCall1.Do(func() {}) - hcCall2 := mockHealthCheck.EXPECT().Close() + hcCall2 := mockHealthCheck.EXPECT().RegisterStats() + hcCall2.Do(func() {}) hcCall2.After(hcCall1) + hcCall3 := mockHealthCheck.EXPECT().Close() + hcCall3.After(hcCall2) healthCheckFactory = func(topoServer *topo.Server, cell string, cellsToWatch []string) discovery.HealthCheck { return mockHealthCheck } - mockThrottler := NewMockThrottlerInterface(mockCtrl) - throttlerFactory = func(name, unit string, threadCount int, maxRate int64, maxReplicationLagConfig throttler.MaxReplicationLagModuleConfig) (ThrottlerInterface, error) { + mockThrottler := NewMockThrottler(mockCtrl) + throttlerFactory = func(name, unit string, threadCount int, maxRate int64, maxReplicationLagConfig throttler.MaxReplicationLagModuleConfig) (throttler.Throttler, error) { assert.Equal(t, 1, threadCount) return mockThrottler, nil } diff --git a/go/vt/vttablet/tabletserver/vstreamer/engine.go b/go/vt/vttablet/tabletserver/vstreamer/engine.go index 501b3708eed..3dc1f5f9a92 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/engine.go +++ b/go/vt/vttablet/tabletserver/vstreamer/engine.go @@ -42,6 +42,7 @@ import ( "vitess.io/vitess/go/vt/vttablet/tabletserver/schema" "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle" + "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base" "vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/throttlerapp" binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" @@ -115,7 +116,7 @@ func NewEngine(env tabletenv.Env, ts srvtopo.Server, se *schema.Engine, lagThrot ts: ts, se: se, cell: cell, - throttlerClient: throttle.NewBackgroundClient(lagThrottler, throttlerapp.VStreamerName, throttle.ThrottleCheckSelf), + throttlerClient: throttle.NewBackgroundClient(lagThrottler, throttlerapp.VStreamerName, base.UndefinedScope), streamers: make(map[int]*uvstreamer), rowStreamers: make(map[int]*rowStreamer), diff --git a/go/vt/vttablet/tabletserver/vstreamer/helper_event_test.go b/go/vt/vttablet/tabletserver/vstreamer/helper_event_test.go index 49dabae3973..81f4d3f7975 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/helper_event_test.go +++ b/go/vt/vttablet/tabletserver/vstreamer/helper_event_test.go @@ -780,6 +780,8 @@ func getQueryType(strType string) query.Type { return query.Type_SET case "JSON": return query.Type_JSON + case "VECTOR": + return query.Type_VECTOR default: panic("unknown type " + strType) } diff --git a/go/vt/vttablet/tabletserver/vstreamer/planbuilder_test.go b/go/vt/vttablet/tabletserver/vstreamer/planbuilder_test.go index e9721daa693..ba345b2a00b 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/planbuilder_test.go +++ b/go/vt/vttablet/tabletserver/vstreamer/planbuilder_test.go @@ -77,7 +77,7 @@ func init() { } }` var kspb vschemapb.Keyspace - if err := json2.Unmarshal([]byte(input), &kspb); err != nil { + if err := json2.UnmarshalPB([]byte(input), &kspb); err != nil { panic(fmt.Errorf("Unmarshal failed: %v", err)) } srvVSchema := &vschemapb.SrvVSchema{ diff --git a/go/vt/vttablet/tabletserver/vstreamer/snapshot_conn.go b/go/vt/vttablet/tabletserver/vstreamer/snapshot_conn.go index bf49ca46618..f3eda83bd45 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/snapshot_conn.go +++ b/go/vt/vttablet/tabletserver/vstreamer/snapshot_conn.go @@ -88,14 +88,7 @@ func (conn *snapshotConn) streamWithSnapshot(ctx context.Context, table, query s query, err) } - _, err = conn.ExecuteFetch("set session session_track_gtids = START_GTID", 1, false) - if err != nil { - // session_track_gtids = START_GTID unsupported or cannot execute. Resort to LOCK-based snapshot - gtid, err = conn.startSnapshot(ctx, table) - } else { - // session_track_gtids = START_GTID supported. Get a transaction with consistent GTID without LOCKing tables. - gtid, err = conn.startSnapshotWithConsistentGTID(ctx) - } + gtid, err = conn.startSnapshot(ctx, table) if err != nil { return "", rotatedLog, err } diff --git a/go/vt/vttablet/tabletserver/vstreamer/tablestreamer.go b/go/vt/vttablet/tabletserver/vstreamer/tablestreamer.go index 80f850dae2e..d3bbd136f12 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/tablestreamer.go +++ b/go/vt/vttablet/tabletserver/vstreamer/tablestreamer.go @@ -95,14 +95,7 @@ func (ts *tableStreamer) Stream() error { defer conn.Close() ts.snapshotConn = conn - _, err = conn.ExecuteFetch("set session session_track_gtids = START_GTID", 1, false) - if err != nil { - // session_track_gtids = START_GTID unsupported or cannot execute. Resort to LOCK-based snapshot - ts.gtid, err = conn.startSnapshotAllTables(ts.ctx) - } else { - // session_track_gtids = START_GTID supported. Get a transaction with consistent GTID without LOCKing tables. - ts.gtid, err = conn.startSnapshotWithConsistentGTID(ts.ctx) - } + ts.gtid, err = conn.startSnapshotAllTables(ts.ctx) if err != nil { return err } diff --git a/go/vt/vttablet/tabletserver/vstreamer/testenv/testenv.go b/go/vt/vttablet/tabletserver/vstreamer/testenv/testenv.go index 1d49db8c503..632579551c0 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/testenv/testenv.go +++ b/go/vt/vttablet/tabletserver/vstreamer/testenv/testenv.go @@ -202,7 +202,7 @@ func (te *Env) Close() { func (te *Env) SetVSchema(vs string) error { ctx := context.Background() var kspb vschemapb.Keyspace - if err := json2.Unmarshal([]byte(vs), &kspb); err != nil { + if err := json2.UnmarshalPB([]byte(vs), &kspb); err != nil { return err } if err := te.TopoServ.SaveVSchema(ctx, te.KeyspaceName, &kspb); err != nil { diff --git a/go/vt/vttablet/tabletserver/vstreamer/vstreamer.go b/go/vt/vttablet/tabletserver/vstreamer/vstreamer.go index bf41111bbc8..3413c53d811 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/vstreamer.go +++ b/go/vt/vttablet/tabletserver/vstreamer/vstreamer.go @@ -642,15 +642,23 @@ func (vs *vstreamer) parseEvent(ev mysql.BinlogEvent) ([]*binlogdatapb.VEvent, e return nil, fmt.Errorf("compressed transaction payload events are not supported with database flavor %s", vs.vse.env.Config().DB.Flavor) } - tpevents, err := ev.TransactionPayload(vs.format) + tp, err := ev.TransactionPayload(vs.format) if err != nil { return nil, err } + defer tp.Close() // Events inside the payload don't have their own checksum. ogca := vs.format.ChecksumAlgorithm defer func() { vs.format.ChecksumAlgorithm = ogca }() vs.format.ChecksumAlgorithm = mysql.BinlogChecksumAlgOff - for _, tpevent := range tpevents { + for { + tpevent, err := tp.GetNextEvent() + if err != nil { + if err == io.EOF { + break + } + return nil, err + } tpvevents, err := vs.parseEvent(tpevent) if err != nil { return nil, vterrors.Wrap(err, "failed to parse transaction payload's internal event") diff --git a/go/vt/vttablet/tabletservermock/controller.go b/go/vt/vttablet/tabletservermock/controller.go index 33a6b94d327..7c7055b3e15 100644 --- a/go/vt/vttablet/tabletservermock/controller.go +++ b/go/vt/vttablet/tabletservermock/controller.go @@ -221,6 +221,11 @@ func (tqsc *Controller) CheckThrottler(ctx context.Context, appName string, flag return nil } +// GetThrottlerStatus is part of the tabletserver.Controller interface +func (tqsc *Controller) GetThrottlerStatus(ctx context.Context) *throttle.ThrottlerStatus { + return nil +} + // EnterLameduck implements tabletserver.Controller. func (tqsc *Controller) EnterLameduck() { tqsc.mu.Lock() diff --git a/go/vt/vttablet/tmclient/rpc_client_api.go b/go/vt/vttablet/tmclient/rpc_client_api.go index f55d33c2e54..7da1a6196dd 100644 --- a/go/vt/vttablet/tmclient/rpc_client_api.go +++ b/go/vt/vttablet/tmclient/rpc_client_api.go @@ -261,6 +261,7 @@ type TabletManagerClient interface { // Throttler CheckThrottler(ctx context.Context, tablet *topodatapb.Tablet, request *tabletmanagerdatapb.CheckThrottlerRequest) (*tabletmanagerdatapb.CheckThrottlerResponse, error) + GetThrottlerStatus(ctx context.Context, tablet *topodatapb.Tablet, request *tabletmanagerdatapb.GetThrottlerStatusRequest) (*tabletmanagerdatapb.GetThrottlerStatusResponse, error) // // Management methods diff --git a/go/vt/vttablet/tmrpctest/test_tm_rpc.go b/go/vt/vttablet/tmrpctest/test_tm_rpc.go index 531841b1d16..9ba01b13d5a 100644 --- a/go/vt/vttablet/tmrpctest/test_tm_rpc.go +++ b/go/vt/vttablet/tmrpctest/test_tm_rpc.go @@ -1352,6 +1352,15 @@ func (fra *fakeRPCTM) CheckThrottler(ctx context.Context, req *tabletmanagerdata panic("implement me") } +func (fra *fakeRPCTM) GetThrottlerStatus(ctx context.Context, req *tabletmanagerdatapb.GetThrottlerStatusRequest) (*tabletmanagerdatapb.GetThrottlerStatusResponse, error) { + if fra.panics { + panic(fmt.Errorf("test-triggered panic")) + } + + //TODO implement me + panic("implement me") +} + func tmRPCTestRestoreFromBackup(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet, req *tabletmanagerdatapb.RestoreFromBackupRequest) { stream, err := client.RestoreFromBackup(ctx, tablet, req) if err != nil { diff --git a/go/vt/vttest/local_cluster.go b/go/vt/vttest/local_cluster.go index 3c65f7de1eb..406269ef749 100644 --- a/go/vt/vttest/local_cluster.go +++ b/go/vt/vttest/local_cluster.go @@ -128,7 +128,7 @@ type Config struct { // TransactionMode is SINGLE, MULTI or TWOPC TransactionMode string - TransactionTimeout float64 + TransactionTimeout time.Duration // The host name to use for the table otherwise it will be resolved from the local hostname TabletHostName string diff --git a/go/vt/vttest/vtprocess.go b/go/vt/vttest/vtprocess.go index 2d2c9116c6d..3f34994bb75 100644 --- a/go/vt/vttest/vtprocess.go +++ b/go/vt/vttest/vtprocess.go @@ -188,7 +188,6 @@ var QueryServerArgs = []string{ "--queryserver-config-schema-reload-time", "60s", "--queryserver-config-stream-pool-size", "4", "--queryserver-config-transaction-cap", "4", - "--queryserver-config-transaction-timeout", "300s", "--queryserver-config-txpool-timeout", "300s", } @@ -260,7 +259,7 @@ func VtcomboProcess(environment Environment, args *Config, mysql MySQLManager) ( vt.ExtraArgs = append(vt.ExtraArgs, []string{"--transaction_mode", args.TransactionMode}...) } if args.TransactionTimeout != 0 { - vt.ExtraArgs = append(vt.ExtraArgs, "--queryserver-config-transaction-timeout", fmt.Sprintf("%f", args.TransactionTimeout)) + vt.ExtraArgs = append(vt.ExtraArgs, "--queryserver-config-transaction-timeout", fmt.Sprintf("%v", args.TransactionTimeout)) } if args.TabletHostName != "" { vt.ExtraArgs = append(vt.ExtraArgs, []string{"--tablet_hostname", args.TabletHostName}...) diff --git a/go/vt/wrangler/fake_dbclient_test.go b/go/vt/wrangler/fake_dbclient_test.go index 7fce5ce9afc..14ef0913383 100644 --- a/go/vt/wrangler/fake_dbclient_test.go +++ b/go/vt/wrangler/fake_dbclient_test.go @@ -25,10 +25,10 @@ import ( "github.com/stretchr/testify/assert" + "vitess.io/vitess/go/mysql/capabilities" + "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/sqlparser" - - "vitess.io/vitess/go/sqltypes" ) func verifyQueries(t *testing.T, dcs []*fakeDBClient) { @@ -177,6 +177,10 @@ func (dc *fakeDBClient) ExecuteFetchMulti(query string, maxrows int) ([]*sqltype return results, nil } +func (dc *fakeDBClient) SupportsCapability(capability capabilities.FlavorCapability) (bool, error) { + return false, nil +} + // ExecuteFetch is part of the DBClient interface func (dc *fakeDBClient) executeFetch(query string, maxrows int) (*sqltypes.Result, error) { if dbrs := dc.queries[query]; dbrs != nil { diff --git a/go/vt/wrangler/materializer.go b/go/vt/wrangler/materializer.go index bd3f7b232ef..9367c43c310 100644 --- a/go/vt/wrangler/materializer.go +++ b/go/vt/wrangler/materializer.go @@ -162,7 +162,7 @@ func (wr *Wrangler) MoveTables(ctx context.Context, workflow, sourceKeyspace, ta } wrap := fmt.Sprintf(`{"tables": %s}`, tableSpecs) ks := &vschemapb.Keyspace{} - if err := json2.Unmarshal([]byte(wrap), ks); err != nil { + if err := json2.UnmarshalPB([]byte(wrap), ks); err != nil { return err } for table, vtab := range ks.Tables { diff --git a/go/vt/wrangler/materializer_test.go b/go/vt/wrangler/materializer_test.go index 23cae954b83..1728ba6efc2 100644 --- a/go/vt/wrangler/materializer_test.go +++ b/go/vt/wrangler/materializer_test.go @@ -952,15 +952,15 @@ func TestCreateLookupVindexTargetVSchema(t *testing.T) { out: &vschemapb.Keyspace{ Sharded: true, Vindexes: map[string]*vschemapb.Vindex{ - "unicode_loose_md5": { - Type: "unicode_loose_md5", + "unicode_loose_xxhash": { + Type: "unicode_loose_xxhash", }, }, Tables: map[string]*vschemapb.Table{ "lkp": { ColumnVindexes: []*vschemapb.ColumnVindex{{ Column: "c1", - Name: "unicode_loose_md5", + Name: "unicode_loose_xxhash", }}, }, }, @@ -1002,7 +1002,7 @@ func TestCreateLookupVindexTargetVSchema(t *testing.T) { Vindexes: map[string]*vschemapb.Vindex{ // Create a misleading vindex name. "xxhash": { - Type: "unicode_loose_md5", + Type: "unicode_loose_xxhash", }, }, }, @@ -1929,11 +1929,11 @@ func TestMaterializerOneToOne(t *testing.T) { insertPrefix+ `\(`+ `'workflow', `+ - (`'keyspace:\\"sourceks\\" shard:\\"0\\" `+ + (`'keyspace:"sourceks" shard:"0" `+ `filter:{`+ - `rules:{match:\\"t1\\" filter:\\"select.*t1\\"} `+ - `rules:{match:\\"t2\\" filter:\\"select.*t3\\"} `+ - `rules:{match:\\"t4\\"}`+ + `rules:{match:"t1" filter:"select.*t1"} `+ + `rules:{match:"t2" filter:"select.*t3"} `+ + `rules:{match:"t4"}`+ `}', `)+ `'', [0-9]*, [0-9]*, 'zone1', 'primary,rdonly', [0-9]*, 0, 'Stopped', 'vt_targetks', 0, 0, false, '{}'`+ `\)`+eol, @@ -1968,9 +1968,9 @@ func TestMaterializerManyToOne(t *testing.T) { env.tmc.expectVRQuery( 200, insertPrefix+ - `\('workflow', 'keyspace:\\"sourceks\\" shard:\\"-80\\" filter:{rules:{match:\\"t1\\" filter:\\"select.*t1\\"} rules:{match:\\"t2\\" filter:\\"select.*t3\\"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_targetks', 0, 0, false, '{}'\)`+ + `\('workflow', 'keyspace:"sourceks" shard:"-80" filter:{rules:{match:"t1" filter:"select.*t1"} rules:{match:"t2" filter:"select.*t3"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_targetks', 0, 0, false, '{}'\)`+ `, `+ - `\('workflow', 'keyspace:\\"sourceks\\" shard:\\"80-\\" filter:{rules:{match:\\"t1\\" filter:\\"select.*t1\\"} rules:{match:\\"t2\\" filter:\\"select.*t3\\"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_targetks', 0, 0, false, '{}'\)`+ + `\('workflow', 'keyspace:"sourceks" shard:"80-" filter:{rules:{match:"t1" filter:"select.*t1"} rules:{match:"t2" filter:"select.*t3"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_targetks', 0, 0, false, '{}'\)`+ eol, &sqltypes.Result{}, ) @@ -2021,13 +2021,13 @@ func TestMaterializerOneToMany(t *testing.T) { env.tmc.expectVRQuery( 200, insertPrefix+ - `.*shard:\\"0\\" filter:{rules:{match:\\"t1\\" filter:\\"select.*t1 where in_keyrange\(c1.*targetks\.xxhash.*-80.*`, + `.*shard:"0" filter:{rules:{match:"t1" filter:"select.*t1 where in_keyrange\(c1.*targetks\.xxhash.*-80.*`, &sqltypes.Result{}, ) env.tmc.expectVRQuery( 210, insertPrefix+ - `.*shard:\\"0\\" filter:{rules:{match:\\"t1\\" filter:\\"select.*t1 where in_keyrange\(c1.*targetks\.xxhash.*80-.*`, + `.*shard:"0" filter:{rules:{match:"t1" filter:"select.*t1 where in_keyrange\(c1.*targetks\.xxhash.*80-.*`, &sqltypes.Result{}, ) env.tmc.expectVRQuery(200, mzUpdateQuery, &sqltypes.Result{}) @@ -2078,15 +2078,15 @@ func TestMaterializerManyToMany(t *testing.T) { env.tmc.expectVRQuery( 200, insertPrefix+ - `.*shard:\\"-40\\" filter:{rules:{match:\\"t1\\" filter:\\"select.*t1 where in_keyrange\(c1.*targetks\.xxhash.*-80.*`+ - `.*shard:\\"40-\\" filter:{rules:{match:\\"t1\\" filter:\\"select.*t1 where in_keyrange\(c1.*targetks\.xxhash.*-80.*`, + `.*shard:"-40" filter:{rules:{match:"t1" filter:"select.*t1 where in_keyrange\(c1.*targetks\.xxhash.*-80.*`+ + `.*shard:"40-" filter:{rules:{match:"t1" filter:"select.*t1 where in_keyrange\(c1.*targetks\.xxhash.*-80.*`, &sqltypes.Result{}, ) env.tmc.expectVRQuery( 210, insertPrefix+ - `.*shard:\\"-40\\" filter:{rules:{match:\\"t1\\" filter:\\"select.*t1 where in_keyrange\(c1.*targetks\.xxhash.*80-.*`+ - `.*shard:\\"40-\\" filter:{rules:{match:\\"t1\\" filter:\\"select.*t1 where in_keyrange\(c1.*targetks\.xxhash.*80-.*`, + `.*shard:"-40" filter:{rules:{match:"t1" filter:"select.*t1 where in_keyrange\(c1.*targetks\.xxhash.*80-.*`+ + `.*shard:"40-" filter:{rules:{match:"t1" filter:"select.*t1 where in_keyrange\(c1.*targetks\.xxhash.*80-.*`, &sqltypes.Result{}, ) env.tmc.expectVRQuery(200, mzUpdateQuery, &sqltypes.Result{}) @@ -2139,13 +2139,13 @@ func TestMaterializerMulticolumnVindex(t *testing.T) { env.tmc.expectVRQuery( 200, insertPrefix+ - `.*shard:\\"0\\" filter:{rules:{match:\\"t1\\" filter:\\"select.*t1 where in_keyrange\(c1, c2.*targetks\.region.*-80.*`, + `.*shard:"0" filter:{rules:{match:"t1" filter:"select.*t1 where in_keyrange\(c1, c2.*targetks\.region.*-80.*`, &sqltypes.Result{}, ) env.tmc.expectVRQuery( 210, insertPrefix+ - `.*shard:\\"0\\" filter:{rules:{match:\\"t1\\" filter:\\"select.*t1 where in_keyrange\(c1, c2.*targetks\.region.*80-.*`, + `.*shard:"0" filter:{rules:{match:"t1" filter:"select.*t1 where in_keyrange\(c1, c2.*targetks\.region.*80-.*`, &sqltypes.Result{}, ) env.tmc.expectVRQuery(200, mzUpdateQuery, &sqltypes.Result{}) @@ -2181,7 +2181,7 @@ func TestMaterializerDeploySchema(t *testing.T) { env.tmc.expectVRQuery( 200, insertPrefix+ - `\('workflow', 'keyspace:\\"sourceks\\" shard:\\"0\\" filter:{rules:{match:\\"t1\\" filter:\\"select.*t1\\"} rules:{match:\\"t2\\" filter:\\"select.*t3\\"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_targetks', 0, 0, false, '{}'\)`+ + `\('workflow', 'keyspace:"sourceks" shard:"0" filter:{rules:{match:"t1" filter:"select.*t1"} rules:{match:"t2" filter:"select.*t3"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_targetks', 0, 0, false, '{}'\)`+ eol, &sqltypes.Result{}, ) @@ -2219,7 +2219,7 @@ func TestMaterializerCopySchema(t *testing.T) { env.tmc.expectVRQuery( 200, insertPrefix+ - `\('workflow', 'keyspace:\\"sourceks\\" shard:\\"0\\" filter:{rules:{match:\\"t1\\" filter:\\"select.*t1\\"} rules:{match:\\"t2\\" filter:\\"select.*t3\\"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_targetks', 0, 0, false, '{}'\)`+ + `\('workflow', 'keyspace:"sourceks" shard:"0" filter:{rules:{match:"t1" filter:"select.*t1"} rules:{match:"t2" filter:"select.*t3"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_targetks', 0, 0, false, '{}'\)`+ eol, &sqltypes.Result{}, ) @@ -2276,13 +2276,13 @@ func TestMaterializerExplicitColumns(t *testing.T) { env.tmc.expectVRQuery( 200, insertPrefix+ - `.*shard:\\"0\\" filter:{rules:{match:\\"t1\\" filter:\\"select.*t1 where in_keyrange\(c1, c2.*targetks\.region.*-80.*`, + `.*shard:"0" filter:{rules:{match:"t1" filter:"select.*t1 where in_keyrange\(c1, c2.*targetks\.region.*-80.*`, &sqltypes.Result{}, ) env.tmc.expectVRQuery( 210, insertPrefix+ - `.*shard:\\"0\\" filter:{rules:{match:\\"t1\\" filter:\\"select.*t1 where in_keyrange\(c1, c2.*targetks\.region.*80-.*`, + `.*shard:"0" filter:{rules:{match:"t1" filter:"select.*t1 where in_keyrange\(c1, c2.*targetks\.region.*80-.*`, &sqltypes.Result{}, ) env.tmc.expectVRQuery(200, mzUpdateQuery, &sqltypes.Result{}) @@ -2336,13 +2336,13 @@ func TestMaterializerRenamedColumns(t *testing.T) { env.tmc.expectVRQuery( 200, insertPrefix+ - `.*shard:\\"0\\" filter:{rules:{match:\\"t1\\" filter:\\"select.*t1 where in_keyrange\(c3, c4.*targetks\.region.*-80.*`, + `.*shard:"0" filter:{rules:{match:"t1" filter:"select.*t1 where in_keyrange\(c3, c4.*targetks\.region.*-80.*`, &sqltypes.Result{}, ) env.tmc.expectVRQuery( 210, insertPrefix+ - `.*shard:\\"0\\" filter:{rules:{match:\\"t1\\" filter:\\"select.*t1 where in_keyrange\(c3, c4.*targetks\.region.*80-.*`, + `.*shard:"0" filter:{rules:{match:"t1" filter:"select.*t1 where in_keyrange\(c3, c4.*targetks\.region.*80-.*`, &sqltypes.Result{}, ) env.tmc.expectVRQuery(200, mzUpdateQuery, &sqltypes.Result{}) @@ -2863,7 +2863,7 @@ func TestMaterializerSourceShardSelection(t *testing.T) { } getStreamInsert := func(sourceShard, sourceColumn, targetVindex, targetShard string) string { - return fmt.Sprintf(`.*shard:\\"%s\\" filter:{rules:{match:\\"t1\\" filter:\\"select.*t1 where in_keyrange\(%s.*targetks\.%s.*%s.*`, sourceShard, sourceColumn, targetVindex, targetShard) + return fmt.Sprintf(`.*shard:"%s" filter:{rules:{match:"t1" filter:"select.*t1 where in_keyrange\(%s.*targetks\.%s.*%s.*`, sourceShard, sourceColumn, targetVindex, targetShard) } targetVSchema := &vschemapb.Keyspace{ @@ -3056,7 +3056,7 @@ func TestMaterializerSourceShardSelection(t *testing.T) { // The single target shard streams all data from each source shard // without any keyrange filtering. getStreamInsert: func(sourceShard, _, _, targetShard string) string { - return fmt.Sprintf(`.*shard:\\"%s\\" filter:{rules:{match:\\"t1\\" filter:\\"select.*t1`, sourceShard) + return fmt.Sprintf(`.*shard:"%s" filter:{rules:{match:"t1" filter:"select.*t1`, sourceShard) }, }, { @@ -3611,10 +3611,8 @@ func TestKeyRangesEqualOptimization(t *testing.T) { } blsBytes, err := prototext.Marshal(bls) require.NoError(t, err, "failed to marshal binlog source: %v", err) - // This is also escaped in the SQL statement. - blsStr := strings.ReplaceAll(string(blsBytes), `"`, `\"`) // Escape the string for the regexp comparison. - blsStr = regexp.QuoteMeta(blsStr) + blsStr := regexp.QuoteMeta(string(blsBytes)) // For some reason we end up with an extra slash added by QuoteMeta for the // escaped single quotes in the filter. blsStr = strings.ReplaceAll(blsStr, `\\\\`, `\\\`) diff --git a/go/vt/wrangler/resharder_test.go b/go/vt/wrangler/resharder_test.go index b4a939775ca..4c47b3ebf14 100644 --- a/go/vt/wrangler/resharder_test.go +++ b/go/vt/wrangler/resharder_test.go @@ -93,14 +93,14 @@ func TestResharderOneToMany(t *testing.T) { env.tmc.expectVRQuery( 200, insertPrefix+ - `\('resharderTest', 'keyspace:\\"ks\\" shard:\\"0\\" filter:{rules:{match:\\"/.*\\" filter:\\"-80\\"}}', '', [0-9]*, [0-9]*, '`+ + `\('resharderTest', 'keyspace:"ks" shard:"0" filter:{rules:{match:"/.*" filter:"-80"}}', '', [0-9]*, [0-9]*, '`+ tc.cells+`', '`+tc.tabletTypes+`', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+eol, &sqltypes.Result{}, ) env.tmc.expectVRQuery( 210, insertPrefix+ - `\('resharderTest', 'keyspace:\\"ks\\" shard:\\"0\\" filter:{rules:{match:\\"/.*\\" filter:\\"80-\\"}}', '', [0-9]*, [0-9]*, '`+ + `\('resharderTest', 'keyspace:"ks" shard:"0" filter:{rules:{match:"/.*" filter:"80-"}}', '', [0-9]*, [0-9]*, '`+ tc.cells+`', '`+tc.tabletTypes+`', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+eol, &sqltypes.Result{}, ) @@ -137,8 +137,8 @@ func TestResharderManyToOne(t *testing.T) { env.tmc.expectVRQuery( 200, insertPrefix+ - `\('resharderTest', 'keyspace:\\"ks\\" shard:\\"-80\\" filter:{rules:{match:\\"/.*\\" filter:\\"-\\"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\).*`+ - `\('resharderTest', 'keyspace:\\"ks\\" shard:\\"80-\\" filter:{rules:{match:\\"/.*\\" filter:\\"-\\"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+ + `\('resharderTest', 'keyspace:"ks" shard:"-80" filter:{rules:{match:"/.*" filter:"-"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\).*`+ + `\('resharderTest', 'keyspace:"ks" shard:"80-" filter:{rules:{match:"/.*" filter:"-"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+ eol, &sqltypes.Result{}, ) @@ -172,15 +172,15 @@ func TestResharderManyToMany(t *testing.T) { env.tmc.expectVRQuery( 200, insertPrefix+ - `\('resharderTest', 'keyspace:\\"ks\\" shard:\\"-40\\" filter:{rules:{match:\\"/.*\\" filter:\\"-80\\"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\).*`+ - `\('resharderTest', 'keyspace:\\"ks\\" shard:\\"40-\\" filter:{rules:{match:\\"/.*\\" filter:\\"-80\\"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+ + `\('resharderTest', 'keyspace:"ks" shard:"-40" filter:{rules:{match:"/.*" filter:"-80"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\).*`+ + `\('resharderTest', 'keyspace:"ks" shard:"40-" filter:{rules:{match:"/.*" filter:"-80"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+ eol, &sqltypes.Result{}, ) env.tmc.expectVRQuery( 210, insertPrefix+ - `\('resharderTest', 'keyspace:\\"ks\\" shard:\\"40-\\" filter:{rules:{match:\\"/.*\\" filter:\\"80-\\"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+ + `\('resharderTest', 'keyspace:"ks" shard:"40-" filter:{rules:{match:"/.*" filter:"80-"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+ eol, &sqltypes.Result{}, ) @@ -228,14 +228,14 @@ func TestResharderOneRefTable(t *testing.T) { env.tmc.expectVRQuery( 200, insertPrefix+ - `\('resharderTest', 'keyspace:\\"ks\\" shard:\\"0\\" filter:{rules:{match:\\"t1\\" filter:\\"exclude\\"} rules:{match:\\"/.*\\" filter:\\"-80\\"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+ + `\('resharderTest', 'keyspace:"ks" shard:"0" filter:{rules:{match:"t1" filter:"exclude"} rules:{match:"/.*" filter:"-80"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+ eol, &sqltypes.Result{}, ) env.tmc.expectVRQuery( 210, insertPrefix+ - `\('resharderTest', 'keyspace:\\"ks\\" shard:\\"0\\" filter:{rules:{match:\\"t1\\" filter:\\"exclude\\"} rules:{match:\\"/.*\\" filter:\\"80-\\"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+ + `\('resharderTest', 'keyspace:"ks" shard:"0" filter:{rules:{match:"t1" filter:"exclude"} rules:{match:"/.*" filter:"80-"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+ eol, &sqltypes.Result{}, ) @@ -283,14 +283,14 @@ func TestReshardStopFlags(t *testing.T) { env.tmc.expectVRQuery( 200, insertPrefix+ - `\('resharderTest', 'keyspace:\\"ks\\" shard:\\"0\\" filter:{rules:{match:\\"t1\\" filter:\\"exclude\\"} rules:{match:\\"/.*\\" filter:\\"-80\\"}} stop_after_copy:true', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+ + `\('resharderTest', 'keyspace:"ks" shard:"0" filter:{rules:{match:"t1" filter:"exclude"} rules:{match:"/.*" filter:"-80"}} stop_after_copy:true', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+ eol, &sqltypes.Result{}, ) env.tmc.expectVRQuery( 210, insertPrefix+ - `\('resharderTest', 'keyspace:\\"ks\\" shard:\\"0\\" filter:{rules:{match:\\"t1\\" filter:\\"exclude\\"} rules:{match:\\"/.*\\" filter:\\"80-\\"}} stop_after_copy:true', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+ + `\('resharderTest', 'keyspace:"ks" shard:"0" filter:{rules:{match:"t1" filter:"exclude"} rules:{match:"/.*" filter:"80-"}} stop_after_copy:true', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+ eol, &sqltypes.Result{}, ) @@ -347,18 +347,18 @@ func TestResharderOneRefStream(t *testing.T) { ) env.tmc.expectVRQuery(100, fmt.Sprintf("select workflow, source, cell, tablet_types from _vt.vreplication where db_name='vt_%s' and message != 'FROZEN'", env.keyspace), result) - refRow := `\('t1', 'keyspace:\\"ks1\\" shard:\\"0\\" filter:{rules:{match:\\"t1\\"}}', '', [0-9]*, [0-9]*, 'cell1', 'primary,replica', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)` + refRow := `\('t1', 'keyspace:"ks1" shard:"0" filter:{rules:{match:"t1"}}', '', [0-9]*, [0-9]*, 'cell1', 'primary,replica', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)` env.tmc.expectVRQuery( 200, insertPrefix+ - `\('resharderTest', 'keyspace:\\"ks\\" shard:\\"0\\" filter:{rules:{match:\\"t1\\" filter:\\"exclude\\"} rules:{match:\\"/.*\\" filter:\\"-80\\"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\).*`+ + `\('resharderTest', 'keyspace:"ks" shard:"0" filter:{rules:{match:"t1" filter:"exclude"} rules:{match:"/.*" filter:"-80"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\).*`+ refRow+eol, &sqltypes.Result{}, ) env.tmc.expectVRQuery( 210, insertPrefix+ - `\('resharderTest', 'keyspace:\\"ks\\" shard:\\"0\\" filter:{rules:{match:\\"t1\\" filter:\\"exclude\\"} rules:{match:\\"/.*\\" filter:\\"80-\\"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\).*`+ + `\('resharderTest', 'keyspace:"ks" shard:"0" filter:{rules:{match:"t1" filter:"exclude"} rules:{match:"/.*" filter:"80-"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\).*`+ refRow+eol, &sqltypes.Result{}, ) @@ -430,14 +430,14 @@ func TestResharderNoRefStream(t *testing.T) { env.tmc.expectVRQuery( 200, insertPrefix+ - `\('resharderTest', 'keyspace:\\"ks\\" shard:\\"0\\" filter:{rules:{match:\\"/.*\\" filter:\\"-80\\"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+ + `\('resharderTest', 'keyspace:"ks" shard:"0" filter:{rules:{match:"/.*" filter:"-80"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+ eol, &sqltypes.Result{}, ) env.tmc.expectVRQuery( 210, insertPrefix+ - `\('resharderTest', 'keyspace:\\"ks\\" shard:\\"0\\" filter:{rules:{match:\\"/.*\\" filter:\\"80-\\"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+ + `\('resharderTest', 'keyspace:"ks" shard:"0" filter:{rules:{match:"/.*" filter:"80-"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+ eol, &sqltypes.Result{}, ) @@ -472,14 +472,14 @@ func TestResharderCopySchema(t *testing.T) { env.tmc.expectVRQuery( 200, insertPrefix+ - `\('resharderTest', 'keyspace:\\"ks\\" shard:\\"0\\" filter:{rules:{match:\\"/.*\\" filter:\\"-80\\"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+ + `\('resharderTest', 'keyspace:"ks" shard:"0" filter:{rules:{match:"/.*" filter:"-80"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+ eol, &sqltypes.Result{}, ) env.tmc.expectVRQuery( 210, insertPrefix+ - `\('resharderTest', 'keyspace:\\"ks\\" shard:\\"0\\" filter:{rules:{match:\\"/.*\\" filter:\\"80-\\"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+ + `\('resharderTest', 'keyspace:"ks" shard:"0" filter:{rules:{match:"/.*" filter:"80-"}}', '', [0-9]*, [0-9]*, '', '', [0-9]*, 0, 'Stopped', 'vt_ks', 4, 0, false, '{}'\)`+ eol, &sqltypes.Result{}, ) diff --git a/go/vt/wrangler/traffic_switcher.go b/go/vt/wrangler/traffic_switcher.go index fb76b8e8f21..448f4f99734 100644 --- a/go/vt/wrangler/traffic_switcher.go +++ b/go/vt/wrangler/traffic_switcher.go @@ -1743,7 +1743,7 @@ func doValidateWorkflowHasCompleted(ctx context.Context, ts *trafficSwitcher) er wg.Wait() if !ts.keepRoutingRules { - //check if table is routable + // check if table is routable if ts.MigrationType() == binlogdatapb.MigrationType_TABLES { rules, err := topotools.GetRoutingRules(ctx, ts.TopoServer()) if err != nil { @@ -1981,7 +1981,7 @@ func (ts *trafficSwitcher) addParticipatingTablesToKeyspace(ctx context.Context, if strings.HasPrefix(tableSpecs, "{") { // user defined the vschema snippet, typically for a sharded target wrap := fmt.Sprintf(`{"tables": %s}`, tableSpecs) ks := &vschemapb.Keyspace{} - if err := json2.Unmarshal([]byte(wrap), ks); err != nil { + if err := json2.UnmarshalPB([]byte(wrap), ks); err != nil { return err } for table, vtab := range ks.Tables { diff --git a/go/vt/wrangler/traffic_switcher_test.go b/go/vt/wrangler/traffic_switcher_test.go index e1ae1ce908f..5bc336f634e 100644 --- a/go/vt/wrangler/traffic_switcher_test.go +++ b/go/vt/wrangler/traffic_switcher_test.go @@ -838,8 +838,8 @@ func testTableMigrateOneToMany(t *testing.T, keepData, keepRoutingRules bool) { createReverseVReplication := func() { deleteReverseReplication() - tme.dbSourceClients[0].addQueryRE(`insert into _vt.vreplication.*test_reverse.*ks2.*-80.*t1.*from `+"`"+"t1`"+`\\".*t2.*from `+"`"+"t2`"+`\\"`, &sqltypes.Result{InsertID: 1}, nil) - tme.dbSourceClients[0].addQueryRE(`insert into _vt.vreplication.*test_reverse.*ks2.*80-.*t1.*from `+"`"+"t1`"+`\\".*t2.*from `+"`"+"t2`"+`\\"`, &sqltypes.Result{InsertID: 2}, nil) + tme.dbSourceClients[0].addQueryRE(`insert into _vt.vreplication.*test_reverse.*ks2.*-80.*t1.*from `+"`"+"t1`"+`".*t2.*from `+"`"+"t2`"+`"`, &sqltypes.Result{InsertID: 1}, nil) + tme.dbSourceClients[0].addQueryRE(`insert into _vt.vreplication.*test_reverse.*ks2.*80-.*t1.*from `+"`"+"t1`"+`".*t2.*from `+"`"+"t2`"+`"`, &sqltypes.Result{InsertID: 2}, nil) tme.dbSourceClients[0].addQuery("select * from _vt.vreplication where id = 1", stoppedResult(1), nil) tme.dbSourceClients[0].addQuery("select * from _vt.vreplication where id = 2", stoppedResult(2), nil) } @@ -1072,8 +1072,8 @@ func TestTableMigrateOneToManyDryRun(t *testing.T) { createReverseVReplication := func() { deleteReverseReplicaion() - tme.dbSourceClients[0].addQueryRE(`insert into _vt.vreplication.*test_reverse.*ks2.*-80.*t1.*from t1\\".*t2.*from t2\\"`, &sqltypes.Result{InsertID: 1}, nil) - tme.dbSourceClients[0].addQueryRE(`insert into _vt.vreplication.*test_reverse.*ks2.*80-.*t1.*from t1\\".*t2.*from t2\\"`, &sqltypes.Result{InsertID: 2}, nil) + tme.dbSourceClients[0].addQueryRE(`insert into _vt.vreplication.*test_reverse.*ks2.*-80.*t1.*from t1".*t2.*from t2"`, &sqltypes.Result{InsertID: 1}, nil) + tme.dbSourceClients[0].addQueryRE(`insert into _vt.vreplication.*test_reverse.*ks2.*80-.*t1.*from t1".*t2.*from t2"`, &sqltypes.Result{InsertID: 2}, nil) tme.dbSourceClients[0].addQuery("select * from _vt.vreplication where id = 1", stoppedResult(1), nil) tme.dbSourceClients[0].addQuery("select * from _vt.vreplication where id = 2", stoppedResult(2), nil) } diff --git a/java/jdbc/src/main/java/io/vitess/util/MysqlDefs.java b/java/jdbc/src/main/java/io/vitess/util/MysqlDefs.java index 6edd18353e3..add98e470c7 100644 --- a/java/jdbc/src/main/java/io/vitess/util/MysqlDefs.java +++ b/java/jdbc/src/main/java/io/vitess/util/MysqlDefs.java @@ -87,6 +87,7 @@ public final class MysqlDefs { static final int FIELD_TYPE_VARCHAR = 15; // Newer data types static final int FIELD_TYPE_YEAR = 13; + static final int FIELD_TYPE_VECTOR = 242; static final int FIELD_TYPE_JSON = 245; static final int INIT_DB = 2; @@ -166,6 +167,7 @@ public final class MysqlDefs { mysqlToJdbcTypesMap.put("SET", mysqlToJavaType(FIELD_TYPE_SET)); mysqlToJdbcTypesMap.put("GEOMETRY", mysqlToJavaType(FIELD_TYPE_GEOMETRY)); mysqlToJdbcTypesMap.put("JSON", mysqlToJavaType(FIELD_TYPE_JSON)); + mysqlToJdbcTypesMap.put("VECTOR", mysqlToJavaType(FIELD_TYPE_VECTOR)); } static { @@ -200,6 +202,7 @@ public final class MysqlDefs { vitesstoMySqlType.put(Query.Type.TUPLE, Types.OTHER); vitesstoMySqlType.put(Query.Type.GEOMETRY, Types.BINARY); vitesstoMySqlType.put(Query.Type.JSON, Types.CHAR); + vitesstoMySqlType.put(Query.Type.VECTOR, Types.BINARY); } static { @@ -337,6 +340,7 @@ public static int mysqlToJavaType(int mysqlType) { break; case MysqlDefs.FIELD_TYPE_GEOMETRY: + case MysqlDefs.FIELD_TYPE_VECTOR: jdbcType = Types.BINARY; break; @@ -423,6 +427,8 @@ public static int mysqlToJavaType(String mysqlType) { return mysqlToJavaType(FIELD_TYPE_BIT); } else if (mysqlType.equalsIgnoreCase("JSON")) { return mysqlToJavaType(FIELD_TYPE_JSON); + } else if (mysqlType.equalsIgnoreCase("VECTOR")) { + return mysqlToJavaType(FIELD_TYPE_VECTOR); } // Punt @@ -509,6 +515,9 @@ public static String typeToName(int mysqlType) { case MysqlDefs.FIELD_TYPE_GEOMETRY: return "FIELD_TYPE_GEOMETRY"; + case MysqlDefs.FIELD_TYPE_VECTOR: + return "FIELD_TYPE_VECTOR"; + case MysqlDefs.FIELD_TYPE_JSON: return "FIELD_TYPE_JSON"; diff --git a/proto/query.proto b/proto/query.proto index d4e99af7c7d..1332de76ab2 100644 --- a/proto/query.proto +++ b/proto/query.proto @@ -215,6 +215,9 @@ enum Type { // BITNUM specifies a base 2 binary type (unquoted varbinary). // Properties: 34, IsText. BITNUM = 4130; + // VECTOR specifies a VECTOR type + // Properties: 35, IsQuoted. + VECTOR = 2083; } // Value represents a typed value. @@ -638,6 +641,18 @@ message ReadTransactionResponse { TransactionMetadata metadata = 1; } +// UnresolvedTransactionsRequest is the payload to UnresolvedTransactions +message UnresolvedTransactionsRequest { + vtrpc.CallerID effective_caller_id = 1; + VTGateCallerID immediate_caller_id = 2; + Target target = 3; +} + +// UnresolvedTransactionsResponse is the returned value from UnresolvedTransactions +message UnresolvedTransactionsResponse { + repeated TransactionMetadata transactions = 1; +} + // BeginExecuteRequest is the payload to BeginExecute message BeginExecuteRequest { vtrpc.CallerID effective_caller_id = 1; @@ -886,6 +901,8 @@ message RealtimeStats { // udfs_changed is used to signal that the UDFs have changed on the tablet. bool udfs_changed = 9; + + bool tx_unresolved = 10; } // AggregateStats contains information about the health of a group of @@ -974,8 +991,8 @@ message StreamHealthResponse { enum TransactionState { UNKNOWN = 0; PREPARE = 1; - COMMIT = 2; - ROLLBACK = 3; + ROLLBACK = 2; + COMMIT = 3; } // TransactionMetadata contains the metadata for a distributed transaction. diff --git a/proto/queryservice.proto b/proto/queryservice.proto index e2de692532c..b987f692289 100644 --- a/proto/queryservice.proto +++ b/proto/queryservice.proto @@ -69,6 +69,9 @@ service Query { // ReadTransaction returns the 2pc transaction info. rpc ReadTransaction(query.ReadTransactionRequest) returns (query.ReadTransactionResponse) {}; + // UnresolvedTransactions returns the 2pc transaction info. + rpc UnresolvedTransactions(query.UnresolvedTransactionsRequest) returns (query.UnresolvedTransactionsResponse) {}; + // BeginExecute executes a begin and the specified SQL query. rpc BeginExecute(query.BeginExecuteRequest) returns (query.BeginExecuteResponse) {}; diff --git a/proto/vschema.proto b/proto/vschema.proto index dd327f863dc..f0d12278fcd 100644 --- a/proto/vschema.proto +++ b/proto/vschema.proto @@ -153,6 +153,7 @@ message SrvVSchema { RoutingRules routing_rules = 2; // table routing rules ShardRoutingRules shard_routing_rules = 3; KeyspaceRoutingRules keyspace_routing_rules = 4; + MirrorRules mirror_rules = 5; // mirror rules } // ShardRoutingRules specify the shard routing rules for the VSchema. @@ -176,3 +177,17 @@ message KeyspaceRoutingRule { string to_keyspace = 2; } +// MirrorRules specify the high level mirror rules for the VSchema. +message MirrorRules { + // rules should ideally be a map. However protos dont't allow + // repeated fields as elements of a map. So, we use a list + // instead. + repeated MirrorRule rules = 1; +} + +// MirrorRule specifies a mirror rule. +message MirrorRule { + string from_table = 1; + string to_table = 2; + float percent = 3; +} diff --git a/proto/vtctldata.proto b/proto/vtctldata.proto index 0d2f2d1441e..317e8706584 100644 --- a/proto/vtctldata.proto +++ b/proto/vtctldata.proto @@ -506,39 +506,9 @@ message CheckThrottlerRequest { } message CheckThrottlerResponse { - // StatusCode is HTTP compliant response code (e.g. 200 for OK) - int32 status_code = 1; - // Value is the metric value collected by the tablet - double value = 2; - // Threshold is the throttling threshold the table was comparing the value with - double threshold = 3; - // Error indicates an error retrieving the value - string error = 4; - // Message - string message = 5; - // RecentlyChecked indicates that the tablet has been hit with a user-facing check, which can then imply - // that heartbeats lease should be renwed. - bool recently_checked = 6; - - message Metric { - // Name of the metric - string name = 1; - // StatusCode is HTTP compliant response code (e.g. 200 for OK) - int32 status_code = 2; - // Value is the metric value collected by the tablet - double value = 3; - // Threshold is the throttling threshold the table was comparing the value with - double threshold = 4; - // Error indicates an error retrieving the value - string error = 5; - // Message - string message = 6; - // Scope used in this check - string scope = 7; - } - // Metrics is a map (metric name -> metric value/error) so that the client has as much - // information as possible about all the checked metrics. - map metrics = 7; + topodata.TabletAlias tablet_alias = 1; + + tabletmanagerdata.CheckThrottlerResponse Check = 2; } message CleanupSchemaMigrationRequest { @@ -1108,61 +1078,7 @@ message GetThrottlerStatusRequest { } message GetThrottlerStatusResponse { - // TabletAlias is the alias of probed tablet - string tablet_alias = 1; - string keyspace = 2; - string shard = 3; - - // IsLeader indicates if the tablet is the leader of the shard, ie. the primary - bool is_leader = 4; - // IsOpen per stateManager - bool is_open = 5; - // IsEnabled per throttler configuration - bool is_enabled = 6; - // IsDormant: whether the throttler is dormant, ie has not received any checks in a while - // and goes into low-frequency probing mode. - bool is_dormant = 7; - - // LagMetricQuery is the query used to check the lag metric, a constant used by the throttler. - string lag_metric_query = 8; - // CustomMetricQuery is the query used to check the custom metric, supplied by the user. - string custom_metric_query = 9; - // DefaultThreshold is the threshold used by the throttler for the default metric (lag or custom in single-metric throttlers) - double default_threshold = 10; - // MetricNameUsedAsDefault is the name of the metric used as the default metric: "lag" or "custom", for backwards compatibility - // with single-metric throttlers - string metric_name_used_as_default = 11; - - message MetricResult { - double value = 1; - string error = 2; - } - - // AggregatedMetrics is a map of metric names to their values/errors - // Names are, for example, "self", "self/lag", "shard/lag", "shard/loadavg", etc. - map aggregated_metrics = 12; - // MetricThresholds is a map of metric names to their thresholds. - map metric_thresholds = 13; - - message MetricHealth { - vttime.Time last_healthy_at = 1; - int64 seconds_since_last_healthy = 2; - } - // MetricsHealth is a map of metric names to their health status. - map metrics_health = 14; - // ThrottledApps is a map of app names to their throttling rules - map throttled_apps = 15; - // AppCheckedMetrics is a map of app names to their assigned metrics - map app_checked_metrics = 16; - - bool recently_checked = 17; - - message RecentApp { - vttime.Time checked_at = 1; - int32 status_code = 2; - } - // RecentApps is a map of app names to their recent check status - map recent_apps = 18; + tabletmanagerdata.GetThrottlerStatusResponse status = 1; } message GetTopologyPathRequest { @@ -2080,3 +1996,23 @@ message WorkflowUpdateResponse { string summary = 1; repeated TabletInfo details = 2; } + +message GetMirrorRulesRequest { +} + +message GetMirrorRulesResponse { + vschema.MirrorRules mirror_rules = 1; +} + +message WorkflowMirrorTrafficRequest { + string keyspace = 1; + string workflow = 2; + repeated topodata.TabletType tablet_types = 3; + float percent = 4; +} + +message WorkflowMirrorTrafficResponse { + string summary = 1; + string start_state = 2; + string current_state = 3; +} diff --git a/proto/vtctlservice.proto b/proto/vtctlservice.proto index 45100cd3d74..672374038b5 100644 --- a/proto/vtctlservice.proto +++ b/proto/vtctlservice.proto @@ -364,4 +364,7 @@ service Vtctld { // WorkflowUpdate updates the configuration of a vreplication workflow // using the provided updated parameters. rpc WorkflowUpdate(vtctldata.WorkflowUpdateRequest) returns (vtctldata.WorkflowUpdateResponse) {}; + // GetMirrorRules returns the VSchema routing rules. + rpc GetMirrorRules(vtctldata.GetMirrorRulesRequest) returns (vtctldata.GetMirrorRulesResponse) {}; + rpc WorkflowMirrorTraffic(vtctldata.WorkflowMirrorTrafficRequest) returns (vtctldata.WorkflowMirrorTrafficResponse) {}; } diff --git a/proto/vtgateservice.proto b/proto/vtgateservice.proto index 745302ecdad..fe6170b3ecc 100644 --- a/proto/vtgateservice.proto +++ b/proto/vtgateservice.proto @@ -48,10 +48,6 @@ service Vitess { // API group: v3 rpc StreamExecute(vtgate.StreamExecuteRequest) returns (stream vtgate.StreamExecuteResponse) {}; - // ResolveTransaction resolves a transaction. - // API group: Transactions - rpc ResolveTransaction(vtgate.ResolveTransactionRequest) returns (vtgate.ResolveTransactionResponse) {}; - // VStream streams binlog events from the requested sources. rpc VStream(vtgate.VStreamRequest) returns (stream vtgate.VStreamResponse) {}; diff --git a/proto/vttest.proto b/proto/vttest.proto index b48107044d7..fdabe7c40f5 100644 --- a/proto/vttest.proto +++ b/proto/vttest.proto @@ -94,4 +94,7 @@ message VTTestTopology { // routing rules for the topology. vschema.RoutingRules routing_rules = 3; + + // mirror rules for the topology. + vschema.MirrorRules mirror_rules = 4; } diff --git a/test.go b/test.go index ef0a28bafe0..360b231e889 100755 --- a/test.go +++ b/test.go @@ -77,7 +77,7 @@ 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", "33", "the version identifier to use for the docker images") + bootstrapVersion = flag.String("bootstrap-version", "34", "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") @@ -98,6 +98,7 @@ var ( dryRun = flag.Bool("dry-run", false, "For each test to be run, it will output the test attributes, but NOT run the tests. Useful while debugging changes to test.go (this file)") remoteStats = flag.String("remote-stats", "", "url to send remote stats") buildVTAdmin = flag.Bool("build-vtadmin", false, "Enable or disable VTAdmin build during 'make build'") + buildTag = flag.String("build-tag", "", "Build tag to create a custom debug build") ) var ( @@ -433,6 +434,9 @@ func main() { if !*buildVTAdmin { command.Env = append(os.Environ(), "NOVTADMINBUILD=1") } + if *buildTag != "" { + command.Env = append(command.Env, fmt.Sprintf(`EXTRA_BUILD_TAGS=%s`, *buildTag)) + } if out, err := command.CombinedOutput(); err != nil { log.Fatalf("make build failed; exit code: %d, error: %v\n%s", command.ProcessState.ExitCode(), err, out) diff --git a/test/ci_workflow_gen.go b/test/ci_workflow_gen.go index 9ead7f07963..09e2fbb6900 100644 --- a/test/ci_workflow_gen.go +++ b/test/ci_workflow_gen.go @@ -31,6 +31,7 @@ type mysqlVersion string const ( mysql57 mysqlVersion = "mysql57" mysql80 mysqlVersion = "mysql80" + mysql84 mysqlVersion = "mysql84" defaultMySQLVersion = mysql80 ) @@ -42,7 +43,7 @@ var ( ) var ( - unitTestDatabases = []mysqlVersion{mysql57, mysql80} + unitTestDatabases = []mysqlVersion{mysql57, mysql80, mysql84} ) const ( @@ -122,6 +123,10 @@ var ( "vttablet_prscomplex", } + buildTag = map[string]string{ + "vtgate_transaction": "debug2PC", + } + vitessTesterMap = map[string]string{ "vtgate": "./go/test/endtoend/vtgate/vitess_tester", } @@ -158,6 +163,7 @@ type unitTest struct { type clusterTest struct { Name, Shard, Platform string FileName string + BuildTag string MemoryCheck bool MakeTools, InstallXtraBackup bool Docker bool @@ -245,8 +251,9 @@ func generateClusterWorkflows(list []string, tpl string) { for _, cluster := range clusters { for _, mysqlVersion := range clusterMySQLVersions() { test := &clusterTest{ - Name: fmt.Sprintf("Cluster (%s)", cluster), - Shard: cluster, + Name: fmt.Sprintf("Cluster (%s)", cluster), + Shard: cluster, + BuildTag: buildTag[cluster], } cores16Clusters := canonnizeList(clusterRequiring16CoresMachines) for _, cores16Cluster := range cores16Clusters { diff --git a/test/config.json b/test/config.json index 713faf97024..1cdf92127ef 100644 --- a/test/config.json +++ b/test/config.json @@ -500,6 +500,15 @@ "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"], @@ -790,7 +799,7 @@ }, "vtgate_transaction": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/transaction"], + "Args": ["vitess.io/vitess/go/test/endtoend/transaction"], "Command": [], "Manual": false, "Shard": "vtgate_transaction", @@ -799,7 +808,7 @@ }, "vtgate_transaction_restart": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/transaction/restart"], + "Args": ["vitess.io/vitess/go/test/endtoend/transaction/restart"], "Command": [], "Manual": false, "Shard": "vtgate_transaction", @@ -808,7 +817,7 @@ }, "vtgate_transaction_rollback": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/transaction/rollback"], + "Args": ["vitess.io/vitess/go/test/endtoend/transaction/rollback"], "Command": [], "Manual": false, "Shard": "vtgate_transaction", @@ -817,7 +826,7 @@ }, "vtgate_transaction_single": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/transaction/single"], + "Args": ["vitess.io/vitess/go/test/endtoend/transaction/single"], "Command": [], "Manual": false, "Shard": "vtgate_transaction", @@ -826,7 +835,7 @@ }, "vtgate_transaction_twopc": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/transaction/twopc"], + "Args": ["vitess.io/vitess/go/test/endtoend/transaction/twopc"], "Command": [], "Manual": false, "Shard": "vtgate_transaction", diff --git a/test/config_partial_keyspace.json b/test/config_partial_keyspace.json index 38149fe7acd..bcd445d34bc 100644 --- a/test/config_partial_keyspace.json +++ b/test/config_partial_keyspace.json @@ -29,7 +29,7 @@ }, "vtgate_transaction_partial_keyspace": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/transaction"], + "Args": ["vitess.io/vitess/go/test/endtoend/transaction"], "Command": [], "Manual": false, "Shard": "vtgate_partial_keyspace", @@ -38,7 +38,7 @@ }, "vtgate_transaction_rollback_partial_keyspace": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/transaction/rollback"], + "Args": ["vitess.io/vitess/go/test/endtoend/transaction/rollback"], "Command": [], "Manual": false, "Shard": "vtgate_partial_keyspace", @@ -47,7 +47,7 @@ }, "vtgate_transaction_single_partial_keyspace": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/transaction/single"], + "Args": ["vitess.io/vitess/go/test/endtoend/transaction/single"], "Command": [], "Manual": false, "Shard": "vtgate_partial_keyspace", diff --git a/test/templates/cluster_endtoend_test.tpl b/test/templates/cluster_endtoend_test.tpl index 7532b51bb6e..332cb67fedc 100644 --- a/test/templates/cluster_endtoend_test.tpl +++ b/test/templates/cluster_endtoend_test.tpl @@ -87,7 +87,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -124,7 +124,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update @@ -207,7 +207,7 @@ jobs: {{end}} # run the tests however you normally do, then produce a JUnit XML file - eatmydata -- 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 + eatmydata -- 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: Print test output and Record test result in launchable if PR is not a draft if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && always() diff --git a/test/templates/cluster_endtoend_test_docker.tpl b/test/templates/cluster_endtoend_test_docker.tpl index 9aa49df5f18..2b63e6d3516 100644 --- a/test/templates/cluster_endtoend_test_docker.tpl +++ b/test/templates/cluster_endtoend_test_docker.tpl @@ -56,7 +56,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Tune the OS if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' diff --git a/test/templates/cluster_endtoend_test_mysql57.tpl b/test/templates/cluster_endtoend_test_mysql57.tpl index eaa9e366196..a29698da472 100644 --- a/test/templates/cluster_endtoend_test_mysql57.tpl +++ b/test/templates/cluster_endtoend_test_mysql57.tpl @@ -92,7 +92,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -126,7 +126,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb # Bionic packages are still compatible for Jammy since there's no MySQL 5.7 # packages for Jammy. echo mysql-apt-config mysql-apt-config/repo-codename select bionic | sudo debconf-set-selections @@ -147,6 +147,7 @@ jobs: 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" diff --git a/test/templates/cluster_vitess_tester.tpl b/test/templates/cluster_vitess_tester.tpl index 73175e5b892..7660cd05f14 100644 --- a/test/templates/cluster_vitess_tester.tpl +++ b/test/templates/cluster_vitess_tester.tpl @@ -71,7 +71,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' @@ -93,7 +93,7 @@ jobs: # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C # Setup MySQL 8.0 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update @@ -132,6 +132,7 @@ jobs: # which musn't be more than 107 characters long. export VTDATAROOT="/tmp/" source build.env + export NOVTADMINBUILD=1 make build set -exo pipefail diff --git a/test/templates/dockerfile.tpl b/test/templates/dockerfile.tpl index 502e553cabf..437971aa532 100644 --- a/test/templates/dockerfile.tpl +++ b/test/templates/dockerfile.tpl @@ -1,4 +1,4 @@ -ARG bootstrap_version=33 +ARG bootstrap_version=34 ARG image="vitess/bootstrap:${bootstrap_version}-{{.Platform}}" FROM "${image}" @@ -15,6 +15,7 @@ RUN wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_ 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}} diff --git a/test/templates/unit_test.tpl b/test/templates/unit_test.tpl index ca31dcbcaf9..21707a89e48 100644 --- a/test/templates/unit_test.tpl +++ b/test/templates/unit_test.tpl @@ -69,7 +69,7 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' uses: actions/setup-go@v5 with: - go-version: 1.22.4 + go-version: 1.22.5 - name: Set up python if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' @@ -98,12 +98,11 @@ jobs: sudo rm -rf /var/lib/mysql sudo rm -rf /etc/mysql - {{if (eq .Platform "mysql57")}} # Get key to latest MySQL repo sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb - # mysql57 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb + {{if (eq .Platform "mysql57")}} # Bionic packages are still compatible for Jammy since there's no MySQL 5.7 # packages for Jammy. echo mysql-apt-config mysql-apt-config/repo-codename select bionic | sudo debconf-set-selections @@ -111,20 +110,20 @@ jobs: sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update sudo DEBIAN_FRONTEND="noninteractive" apt-get -qq install -y mysql-client=5.7* mysql-community-server=5.7* mysql-server=5.7* libncurses5 - {{end}} {{if (eq .Platform "mysql80")}} - # Get key to latest MySQL repo - sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A8D3785C - - # mysql80 - wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* sudo apt-get -qq update sudo DEBIAN_FRONTEND="noninteractive" apt-get -qq install -y mysql-server mysql-client + {{end}} + {{if (eq .Platform "mysql84")}} + echo mysql-apt-config mysql-apt-config/select-server select mysql-8.4-lts | sudo debconf-set-selections + sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* + sudo apt-get -qq update + sudo DEBIAN_FRONTEND="noninteractive" apt-get -qq install -y mysql-server mysql-client {{end}} sudo apt-get -qq install -y make unzip g++ curl git wget ant openjdk-11-jdk eatmydata diff --git a/tools/check_astfmtgen.sh b/tools/check_astfmtgen.sh new file mode 100755 index 00000000000..caddeb61808 --- /dev/null +++ b/tools/check_astfmtgen.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# +# Validate that the current version of ast_format_fast matches what gets generated. +# + +source build.env + +first_output=$(git status --porcelain) + +go run ./go/tools/astfmtgen vitess.io/vitess/go/vt/sqlparser/... + +second_output=$(git status --porcelain) + +diff=$(diff <( echo "$first_output") <( echo "$second_output")) + +if [[ "$diff" != "" ]]; then + echo "ERROR: Regenerated ast_format_fast file do not match the current version." + echo -e "File containing differences:\n$diff" + exit 1 +fi diff --git a/vitess-mixin/go.mod b/vitess-mixin/go.mod index 591803ff433..20d3f33eed8 100644 --- a/vitess-mixin/go.mod +++ b/vitess-mixin/go.mod @@ -1,6 +1,6 @@ module vitess-mixin -go 1.22.4 +go 1.22.5 require ( github.com/evanphx/json-patch v5.9.0+incompatible diff --git a/web/vtadmin/src/components/pips/Pip.module.scss b/web/vtadmin/src/components/pips/Pip.module.scss index ece8042179f..341ed6ad314 100644 --- a/web/vtadmin/src/components/pips/Pip.module.scss +++ b/web/vtadmin/src/components/pips/Pip.module.scss @@ -35,4 +35,8 @@ &.danger { background: var(--colorError50); } + + &.throttled { + background: var(--grey900); + } } diff --git a/web/vtadmin/src/components/pips/Pip.tsx b/web/vtadmin/src/components/pips/Pip.tsx index 197249967aa..13d0e71fb3f 100644 --- a/web/vtadmin/src/components/pips/Pip.tsx +++ b/web/vtadmin/src/components/pips/Pip.tsx @@ -22,7 +22,7 @@ interface Props { state?: PipState; } -export type PipState = 'primary' | 'success' | 'warning' | 'danger' | null | undefined; +export type PipState = 'primary' | 'success' | 'warning' | 'danger' | 'throttled' | null | undefined; export const Pip = ({ className, state }: Props) => { return
; diff --git a/web/vtadmin/src/components/pips/StreamStatePip.tsx b/web/vtadmin/src/components/pips/StreamStatePip.tsx index e68d358b654..be0a7f9157b 100644 --- a/web/vtadmin/src/components/pips/StreamStatePip.tsx +++ b/web/vtadmin/src/components/pips/StreamStatePip.tsx @@ -25,6 +25,7 @@ const STREAM_STATES: { [key: string]: PipState } = { Error: 'danger', Running: 'success', Stopped: null, + Throttled: 'throttled', }; export const StreamStatePip = ({ state }: Props) => { diff --git a/web/vtadmin/src/components/routes/Workflows.tsx b/web/vtadmin/src/components/routes/Workflows.tsx index b9a85a8e3e4..32ddfcfb825 100644 --- a/web/vtadmin/src/components/routes/Workflows.tsx +++ b/web/vtadmin/src/components/routes/Workflows.tsx @@ -36,6 +36,8 @@ import { KeyspaceLink } from '../links/KeyspaceLink'; import { QueryLoadingPlaceholder } from '../placeholders/QueryLoadingPlaceholder'; import { UseQueryResult } from 'react-query'; +export const ThrottleThresholdSeconds = 60; + export const Workflows = () => { useDocumentTitle('Workflows'); const workflowsQuery = useWorkflows(); @@ -67,7 +69,6 @@ export const Workflows = () => { row.clusterID && row.keyspace && row.name ? `/workflow/${row.clusterID}/${row.keyspace}/${row.name}` : null; - return ( @@ -112,13 +113,52 @@ export const Workflows = () => { {/* TODO(doeg): add a protobuf enum for this (https://github.com/vitessio/vitess/projects/12#card-60190340) */} {['Error', 'Copying', 'Running', 'Stopped'].map((streamState) => { if (streamState in row.streams) { + var numThrottled = 0; + var throttledApp: string | undefined = ''; const streamCount = row.streams[streamState].length; + var streamDescription: string; + switch (streamState) { + case 'Error': + streamDescription = 'failed'; + break; + case 'Running': + case 'Copying': + const streams = row.streams[streamState]; + if (streams !== undefined && streams !== null) { + for (const stream of streams) { + if ( + stream?.throttler_status?.time_throttled !== null && + stream?.throttler_status?.time_throttled !== undefined && + // If the stream has been throttled recently, treat it as throttled. + Number(stream?.throttler_status?.time_throttled?.seconds) > + Date.now() / 1000 - ThrottleThresholdSeconds + ) { + numThrottled++; + // In case of multiple streams, show the first throttled app and time. + // The detail page will show each stream separately. + if (numThrottled === 1) { + throttledApp = + stream?.throttler_status?.component_throttled?.toString(); + } + } + } + } + streamDescription = streamState.toLocaleLowerCase(); + if (numThrottled > 0) { + streamState = 'Throttled'; + } + break; + default: + streamDescription = streamState.toLocaleLowerCase(); + } const tooltip = [ streamCount, - streamState === 'Error' ? 'failed' : streamState.toLocaleLowerCase(), + streamDescription, streamCount === 1 ? 'stream' : 'streams', + numThrottled > 0 + ? '(' + numThrottled + ' throttled in ' + throttledApp + ')' + : '', ].join(' '); - return ( diff --git a/web/vtadmin/src/components/routes/workflow/Workflow.module.scss b/web/vtadmin/src/components/routes/workflow/Workflow.module.scss index 65691d00e4c..0aa70d66828 100644 --- a/web/vtadmin/src/components/routes/workflow/Workflow.module.scss +++ b/web/vtadmin/src/components/routes/workflow/Workflow.module.scss @@ -32,3 +32,11 @@ content: none; } } + +.headingMetaContainer div { + width: '100%'; + display: 'flex'; + justify-content: 'space-between'; + padding-top: '0px'; + padding-bottom: '0px'; +} diff --git a/web/vtadmin/src/components/routes/workflow/Workflow.tsx b/web/vtadmin/src/components/routes/workflow/Workflow.tsx index 5abbcb25e83..a81901786d8 100644 --- a/web/vtadmin/src/components/routes/workflow/Workflow.tsx +++ b/web/vtadmin/src/components/routes/workflow/Workflow.tsx @@ -53,16 +53,21 @@ export const Workflow = () => { {name} -
- - Cluster: {clusterID} - - - Target keyspace:{' '} - - {keyspace} - - +
+
+ + Cluster: {clusterID} + + + Target keyspace:{' '} + + {keyspace} + + +
+
+ Scroll To Streams +
diff --git a/web/vtadmin/src/components/routes/workflow/WorkflowStreams.tsx b/web/vtadmin/src/components/routes/workflow/WorkflowStreams.tsx index 6c9bcae2dfa..2d86e1141a6 100644 --- a/web/vtadmin/src/components/routes/workflow/WorkflowStreams.tsx +++ b/web/vtadmin/src/components/routes/workflow/WorkflowStreams.tsx @@ -14,14 +14,14 @@ * limitations under the License. */ -import { orderBy, groupBy } from 'lodash-es'; +import { groupBy, orderBy } from 'lodash-es'; import React, { useMemo } from 'react'; import { Link } from 'react-router-dom'; import { useWorkflow } from '../../../hooks/api'; import { formatAlias } from '../../../util/tablets'; -import { formatDateTime } from '../../../util/time'; -import { getStreams, formatStreamKey, getStreamSource, getStreamTarget } from '../../../util/workflows'; +import { formatDateTime, formatRelativeTime } from '../../../util/time'; +import { formatStreamKey, getStreams, getStreamSource, getStreamTarget } from '../../../util/workflows'; import { DataCell } from '../../dataTable/DataCell'; import { DataTable } from '../../dataTable/DataTable'; import { TabletLink } from '../../links/TabletLink'; @@ -29,6 +29,7 @@ import { StreamStatePip } from '../../pips/StreamStatePip'; import { WorkflowStreamsLagChart } from '../../charts/WorkflowStreamsLagChart'; import { ShardLink } from '../../links/ShardLink'; import { env } from '../../../util/env'; +import { ThrottleThresholdSeconds } from '../Workflows'; interface Props { clusterID: string; @@ -61,17 +62,25 @@ export const WorkflowStreams = ({ clusterID, keyspace, name }: Props) => { const source = getStreamSource(row); const target = getStreamTarget(row, keyspace); - + var isThrottled = + Number(row?.throttler_status?.time_throttled?.seconds) > Date.now() / 1000 - ThrottleThresholdSeconds; + const rowState = isThrottled ? 'Throttled' : row.state; return ( - {' '} + {' '} {row.key}
Updated {formatDateTime(row.time_updated?.seconds)}
+ {isThrottled ? ( +
+ Throttled: + in {row.throttler_status?.component_throttled} +
+ ) : null}
{source ? ( @@ -114,7 +123,9 @@ export const WorkflowStreams = ({ clusterID, keyspace, name }: Props) => { )} -

Streams

+

+ Streams +

{/* TODO(doeg): add a protobuf enum for this (https://github.com/vitessio/vitess/projects/12#card-60190340) */} {['Error', 'Copying', 'Running', 'Stopped'].map((streamState) => { if (!Array.isArray(streamsByState[streamState])) { diff --git a/web/vtadmin/src/proto/vtadmin.d.ts b/web/vtadmin/src/proto/vtadmin.d.ts index 021ece60596..bf371914dca 100644 --- a/web/vtadmin/src/proto/vtadmin.d.ts +++ b/web/vtadmin/src/proto/vtadmin.d.ts @@ -35943,7 +35943,8 @@ export namespace query { EXPRESSION = 31, HEXNUM = 4128, HEXVAL = 4129, - BITNUM = 4130 + BITNUM = 4130, + VECTOR = 2083 } /** Properties of a Value. */ @@ -40102,6 +40103,212 @@ export namespace query { public static getTypeUrl(typeUrlPrefix?: string): string; } + /** Properties of an UnresolvedTransactionsRequest. */ + interface IUnresolvedTransactionsRequest { + + /** UnresolvedTransactionsRequest effective_caller_id */ + effective_caller_id?: (vtrpc.ICallerID|null); + + /** UnresolvedTransactionsRequest immediate_caller_id */ + immediate_caller_id?: (query.IVTGateCallerID|null); + + /** UnresolvedTransactionsRequest target */ + target?: (query.ITarget|null); + } + + /** Represents an UnresolvedTransactionsRequest. */ + class UnresolvedTransactionsRequest implements IUnresolvedTransactionsRequest { + + /** + * Constructs a new UnresolvedTransactionsRequest. + * @param [properties] Properties to set + */ + constructor(properties?: query.IUnresolvedTransactionsRequest); + + /** UnresolvedTransactionsRequest effective_caller_id. */ + public effective_caller_id?: (vtrpc.ICallerID|null); + + /** UnresolvedTransactionsRequest immediate_caller_id. */ + public immediate_caller_id?: (query.IVTGateCallerID|null); + + /** UnresolvedTransactionsRequest target. */ + public target?: (query.ITarget|null); + + /** + * Creates a new UnresolvedTransactionsRequest instance using the specified properties. + * @param [properties] Properties to set + * @returns UnresolvedTransactionsRequest instance + */ + public static create(properties?: query.IUnresolvedTransactionsRequest): query.UnresolvedTransactionsRequest; + + /** + * Encodes the specified UnresolvedTransactionsRequest message. Does not implicitly {@link query.UnresolvedTransactionsRequest.verify|verify} messages. + * @param message UnresolvedTransactionsRequest message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encode(message: query.IUnresolvedTransactionsRequest, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified UnresolvedTransactionsRequest message, length delimited. Does not implicitly {@link query.UnresolvedTransactionsRequest.verify|verify} messages. + * @param message UnresolvedTransactionsRequest message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: query.IUnresolvedTransactionsRequest, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes an UnresolvedTransactionsRequest message from the specified reader or buffer. + * @param reader Reader or buffer to decode from + * @param [length] Message length if known beforehand + * @returns UnresolvedTransactionsRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): query.UnresolvedTransactionsRequest; + + /** + * Decodes an UnresolvedTransactionsRequest message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns UnresolvedTransactionsRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): query.UnresolvedTransactionsRequest; + + /** + * Verifies an UnresolvedTransactionsRequest message. + * @param message Plain object to verify + * @returns `null` if valid, otherwise the reason why it is not + */ + public static verify(message: { [k: string]: any }): (string|null); + + /** + * Creates an UnresolvedTransactionsRequest message from a plain object. Also converts values to their respective internal types. + * @param object Plain object + * @returns UnresolvedTransactionsRequest + */ + public static fromObject(object: { [k: string]: any }): query.UnresolvedTransactionsRequest; + + /** + * Creates a plain object from an UnresolvedTransactionsRequest message. Also converts values to other types if specified. + * @param message UnresolvedTransactionsRequest + * @param [options] Conversion options + * @returns Plain object + */ + public static toObject(message: query.UnresolvedTransactionsRequest, options?: $protobuf.IConversionOptions): { [k: string]: any }; + + /** + * Converts this UnresolvedTransactionsRequest to JSON. + * @returns JSON object + */ + public toJSON(): { [k: string]: any }; + + /** + * Gets the default type url for UnresolvedTransactionsRequest + * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns The default type url + */ + public static getTypeUrl(typeUrlPrefix?: string): string; + } + + /** Properties of an UnresolvedTransactionsResponse. */ + interface IUnresolvedTransactionsResponse { + + /** UnresolvedTransactionsResponse transactions */ + transactions?: (query.ITransactionMetadata[]|null); + } + + /** Represents an UnresolvedTransactionsResponse. */ + class UnresolvedTransactionsResponse implements IUnresolvedTransactionsResponse { + + /** + * Constructs a new UnresolvedTransactionsResponse. + * @param [properties] Properties to set + */ + constructor(properties?: query.IUnresolvedTransactionsResponse); + + /** UnresolvedTransactionsResponse transactions. */ + public transactions: query.ITransactionMetadata[]; + + /** + * Creates a new UnresolvedTransactionsResponse instance using the specified properties. + * @param [properties] Properties to set + * @returns UnresolvedTransactionsResponse instance + */ + public static create(properties?: query.IUnresolvedTransactionsResponse): query.UnresolvedTransactionsResponse; + + /** + * Encodes the specified UnresolvedTransactionsResponse message. Does not implicitly {@link query.UnresolvedTransactionsResponse.verify|verify} messages. + * @param message UnresolvedTransactionsResponse message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encode(message: query.IUnresolvedTransactionsResponse, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified UnresolvedTransactionsResponse message, length delimited. Does not implicitly {@link query.UnresolvedTransactionsResponse.verify|verify} messages. + * @param message UnresolvedTransactionsResponse message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: query.IUnresolvedTransactionsResponse, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes an UnresolvedTransactionsResponse message from the specified reader or buffer. + * @param reader Reader or buffer to decode from + * @param [length] Message length if known beforehand + * @returns UnresolvedTransactionsResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): query.UnresolvedTransactionsResponse; + + /** + * Decodes an UnresolvedTransactionsResponse message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns UnresolvedTransactionsResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): query.UnresolvedTransactionsResponse; + + /** + * Verifies an UnresolvedTransactionsResponse message. + * @param message Plain object to verify + * @returns `null` if valid, otherwise the reason why it is not + */ + public static verify(message: { [k: string]: any }): (string|null); + + /** + * Creates an UnresolvedTransactionsResponse message from a plain object. Also converts values to their respective internal types. + * @param object Plain object + * @returns UnresolvedTransactionsResponse + */ + public static fromObject(object: { [k: string]: any }): query.UnresolvedTransactionsResponse; + + /** + * Creates a plain object from an UnresolvedTransactionsResponse message. Also converts values to other types if specified. + * @param message UnresolvedTransactionsResponse + * @param [options] Conversion options + * @returns Plain object + */ + public static toObject(message: query.UnresolvedTransactionsResponse, options?: $protobuf.IConversionOptions): { [k: string]: any }; + + /** + * Converts this UnresolvedTransactionsResponse to JSON. + * @returns JSON object + */ + public toJSON(): { [k: string]: any }; + + /** + * Gets the default type url for UnresolvedTransactionsResponse + * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns The default type url + */ + public static getTypeUrl(typeUrlPrefix?: string): string; + } + /** Properties of a BeginExecuteRequest. */ interface IBeginExecuteRequest { @@ -42388,6 +42595,9 @@ export namespace query { /** RealtimeStats udfs_changed */ udfs_changed?: (boolean|null); + + /** RealtimeStats tx_unresolved */ + tx_unresolved?: (boolean|null); } /** Represents a RealtimeStats. */ @@ -42426,6 +42636,9 @@ export namespace query { /** RealtimeStats udfs_changed. */ public udfs_changed: boolean; + /** RealtimeStats tx_unresolved. */ + public tx_unresolved: boolean; + /** * Creates a new RealtimeStats instance using the specified properties. * @param [properties] Properties to set @@ -42744,8 +42957,8 @@ export namespace query { enum TransactionState { UNKNOWN = 0, PREPARE = 1, - COMMIT = 2, - ROLLBACK = 3 + ROLLBACK = 2, + COMMIT = 3 } /** Properties of a TransactionMetadata. */ @@ -45018,6 +45231,9 @@ export namespace vschema { /** SrvVSchema keyspace_routing_rules */ keyspace_routing_rules?: (vschema.IKeyspaceRoutingRules|null); + + /** SrvVSchema mirror_rules */ + mirror_rules?: (vschema.IMirrorRules|null); } /** Represents a SrvVSchema. */ @@ -45041,6 +45257,9 @@ export namespace vschema { /** SrvVSchema keyspace_routing_rules. */ public keyspace_routing_rules?: (vschema.IKeyspaceRoutingRules|null); + /** SrvVSchema mirror_rules. */ + public mirror_rules?: (vschema.IMirrorRules|null); + /** * Creates a new SrvVSchema instance using the specified properties. * @param [properties] Properties to set @@ -45524,6 +45743,212 @@ export namespace vschema { */ public static getTypeUrl(typeUrlPrefix?: string): string; } + + /** Properties of a MirrorRules. */ + interface IMirrorRules { + + /** MirrorRules rules */ + rules?: (vschema.IMirrorRule[]|null); + } + + /** Represents a MirrorRules. */ + class MirrorRules implements IMirrorRules { + + /** + * Constructs a new MirrorRules. + * @param [properties] Properties to set + */ + constructor(properties?: vschema.IMirrorRules); + + /** MirrorRules rules. */ + public rules: vschema.IMirrorRule[]; + + /** + * Creates a new MirrorRules instance using the specified properties. + * @param [properties] Properties to set + * @returns MirrorRules instance + */ + public static create(properties?: vschema.IMirrorRules): vschema.MirrorRules; + + /** + * Encodes the specified MirrorRules message. Does not implicitly {@link vschema.MirrorRules.verify|verify} messages. + * @param message MirrorRules message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encode(message: vschema.IMirrorRules, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified MirrorRules message, length delimited. Does not implicitly {@link vschema.MirrorRules.verify|verify} messages. + * @param message MirrorRules message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: vschema.IMirrorRules, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a MirrorRules message from the specified reader or buffer. + * @param reader Reader or buffer to decode from + * @param [length] Message length if known beforehand + * @returns MirrorRules + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): vschema.MirrorRules; + + /** + * Decodes a MirrorRules message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns MirrorRules + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): vschema.MirrorRules; + + /** + * Verifies a MirrorRules message. + * @param message Plain object to verify + * @returns `null` if valid, otherwise the reason why it is not + */ + public static verify(message: { [k: string]: any }): (string|null); + + /** + * Creates a MirrorRules message from a plain object. Also converts values to their respective internal types. + * @param object Plain object + * @returns MirrorRules + */ + public static fromObject(object: { [k: string]: any }): vschema.MirrorRules; + + /** + * Creates a plain object from a MirrorRules message. Also converts values to other types if specified. + * @param message MirrorRules + * @param [options] Conversion options + * @returns Plain object + */ + public static toObject(message: vschema.MirrorRules, options?: $protobuf.IConversionOptions): { [k: string]: any }; + + /** + * Converts this MirrorRules to JSON. + * @returns JSON object + */ + public toJSON(): { [k: string]: any }; + + /** + * Gets the default type url for MirrorRules + * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns The default type url + */ + public static getTypeUrl(typeUrlPrefix?: string): string; + } + + /** Properties of a MirrorRule. */ + interface IMirrorRule { + + /** MirrorRule from_table */ + from_table?: (string|null); + + /** MirrorRule to_table */ + to_table?: (string|null); + + /** MirrorRule percent */ + percent?: (number|null); + } + + /** Represents a MirrorRule. */ + class MirrorRule implements IMirrorRule { + + /** + * Constructs a new MirrorRule. + * @param [properties] Properties to set + */ + constructor(properties?: vschema.IMirrorRule); + + /** MirrorRule from_table. */ + public from_table: string; + + /** MirrorRule to_table. */ + public to_table: string; + + /** MirrorRule percent. */ + public percent: number; + + /** + * Creates a new MirrorRule instance using the specified properties. + * @param [properties] Properties to set + * @returns MirrorRule instance + */ + public static create(properties?: vschema.IMirrorRule): vschema.MirrorRule; + + /** + * Encodes the specified MirrorRule message. Does not implicitly {@link vschema.MirrorRule.verify|verify} messages. + * @param message MirrorRule message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encode(message: vschema.IMirrorRule, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified MirrorRule message, length delimited. Does not implicitly {@link vschema.MirrorRule.verify|verify} messages. + * @param message MirrorRule message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: vschema.IMirrorRule, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a MirrorRule message from the specified reader or buffer. + * @param reader Reader or buffer to decode from + * @param [length] Message length if known beforehand + * @returns MirrorRule + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): vschema.MirrorRule; + + /** + * Decodes a MirrorRule message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns MirrorRule + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): vschema.MirrorRule; + + /** + * Verifies a MirrorRule message. + * @param message Plain object to verify + * @returns `null` if valid, otherwise the reason why it is not + */ + public static verify(message: { [k: string]: any }): (string|null); + + /** + * Creates a MirrorRule message from a plain object. Also converts values to their respective internal types. + * @param object Plain object + * @returns MirrorRule + */ + public static fromObject(object: { [k: string]: any }): vschema.MirrorRule; + + /** + * Creates a plain object from a MirrorRule message. Also converts values to other types if specified. + * @param message MirrorRule + * @param [options] Conversion options + * @returns Plain object + */ + public static toObject(message: vschema.MirrorRule, options?: $protobuf.IConversionOptions): { [k: string]: any }; + + /** + * Converts this MirrorRule to JSON. + * @returns JSON object + */ + public toJSON(): { [k: string]: any }; + + /** + * Gets the default type url for MirrorRule + * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns The default type url + */ + public static getTypeUrl(typeUrlPrefix?: string): string; + } } /** Namespace vtctldata. */ @@ -50214,26 +50639,11 @@ export namespace vtctldata { /** Properties of a CheckThrottlerResponse. */ interface ICheckThrottlerResponse { - /** CheckThrottlerResponse status_code */ - status_code?: (number|null); - - /** CheckThrottlerResponse value */ - value?: (number|null); - - /** CheckThrottlerResponse threshold */ - threshold?: (number|null); - - /** CheckThrottlerResponse error */ - error?: (string|null); - - /** CheckThrottlerResponse message */ - message?: (string|null); - - /** CheckThrottlerResponse recently_checked */ - recently_checked?: (boolean|null); + /** CheckThrottlerResponse tablet_alias */ + tablet_alias?: (topodata.ITabletAlias|null); - /** CheckThrottlerResponse metrics */ - metrics?: ({ [k: string]: vtctldata.CheckThrottlerResponse.IMetric }|null); + /** CheckThrottlerResponse Check */ + Check?: (tabletmanagerdata.ICheckThrottlerResponse|null); } /** Represents a CheckThrottlerResponse. */ @@ -50245,26 +50655,11 @@ export namespace vtctldata { */ constructor(properties?: vtctldata.ICheckThrottlerResponse); - /** CheckThrottlerResponse status_code. */ - public status_code: number; - - /** CheckThrottlerResponse value. */ - public value: number; - - /** CheckThrottlerResponse threshold. */ - public threshold: number; - - /** CheckThrottlerResponse error. */ - public error: string; - - /** CheckThrottlerResponse message. */ - public message: string; - - /** CheckThrottlerResponse recently_checked. */ - public recently_checked: boolean; + /** CheckThrottlerResponse tablet_alias. */ + public tablet_alias?: (topodata.ITabletAlias|null); - /** CheckThrottlerResponse metrics. */ - public metrics: { [k: string]: vtctldata.CheckThrottlerResponse.IMetric }; + /** CheckThrottlerResponse Check. */ + public Check?: (tabletmanagerdata.ICheckThrottlerResponse|null); /** * Creates a new CheckThrottlerResponse instance using the specified properties. @@ -50344,142 +50739,6 @@ export namespace vtctldata { public static getTypeUrl(typeUrlPrefix?: string): string; } - namespace CheckThrottlerResponse { - - /** Properties of a Metric. */ - interface IMetric { - - /** Metric name */ - name?: (string|null); - - /** Metric status_code */ - status_code?: (number|null); - - /** Metric value */ - value?: (number|null); - - /** Metric threshold */ - threshold?: (number|null); - - /** Metric error */ - error?: (string|null); - - /** Metric message */ - message?: (string|null); - - /** Metric scope */ - scope?: (string|null); - } - - /** Represents a Metric. */ - class Metric implements IMetric { - - /** - * Constructs a new Metric. - * @param [properties] Properties to set - */ - constructor(properties?: vtctldata.CheckThrottlerResponse.IMetric); - - /** Metric name. */ - public name: string; - - /** Metric status_code. */ - public status_code: number; - - /** Metric value. */ - public value: number; - - /** Metric threshold. */ - public threshold: number; - - /** Metric error. */ - public error: string; - - /** Metric message. */ - public message: string; - - /** Metric scope. */ - public scope: string; - - /** - * Creates a new Metric instance using the specified properties. - * @param [properties] Properties to set - * @returns Metric instance - */ - public static create(properties?: vtctldata.CheckThrottlerResponse.IMetric): vtctldata.CheckThrottlerResponse.Metric; - - /** - * Encodes the specified Metric message. Does not implicitly {@link vtctldata.CheckThrottlerResponse.Metric.verify|verify} messages. - * @param message Metric message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encode(message: vtctldata.CheckThrottlerResponse.IMetric, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Encodes the specified Metric message, length delimited. Does not implicitly {@link vtctldata.CheckThrottlerResponse.Metric.verify|verify} messages. - * @param message Metric message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encodeDelimited(message: vtctldata.CheckThrottlerResponse.IMetric, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Decodes a Metric message from the specified reader or buffer. - * @param reader Reader or buffer to decode from - * @param [length] Message length if known beforehand - * @returns Metric - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): vtctldata.CheckThrottlerResponse.Metric; - - /** - * Decodes a Metric message from the specified reader or buffer, length delimited. - * @param reader Reader or buffer to decode from - * @returns Metric - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): vtctldata.CheckThrottlerResponse.Metric; - - /** - * Verifies a Metric message. - * @param message Plain object to verify - * @returns `null` if valid, otherwise the reason why it is not - */ - public static verify(message: { [k: string]: any }): (string|null); - - /** - * Creates a Metric message from a plain object. Also converts values to their respective internal types. - * @param object Plain object - * @returns Metric - */ - public static fromObject(object: { [k: string]: any }): vtctldata.CheckThrottlerResponse.Metric; - - /** - * Creates a plain object from a Metric message. Also converts values to other types if specified. - * @param message Metric - * @param [options] Conversion options - * @returns Plain object - */ - public static toObject(message: vtctldata.CheckThrottlerResponse.Metric, options?: $protobuf.IConversionOptions): { [k: string]: any }; - - /** - * Converts this Metric to JSON. - * @returns JSON object - */ - public toJSON(): { [k: string]: any }; - - /** - * Gets the default type url for Metric - * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns The default type url - */ - public static getTypeUrl(typeUrlPrefix?: string): string; - } - } - /** Properties of a CleanupSchemaMigrationRequest. */ interface ICleanupSchemaMigrationRequest { @@ -58648,59 +58907,8 @@ export namespace vtctldata { /** Properties of a GetThrottlerStatusResponse. */ interface IGetThrottlerStatusResponse { - /** GetThrottlerStatusResponse tablet_alias */ - tablet_alias?: (string|null); - - /** GetThrottlerStatusResponse keyspace */ - keyspace?: (string|null); - - /** GetThrottlerStatusResponse shard */ - shard?: (string|null); - - /** GetThrottlerStatusResponse is_leader */ - is_leader?: (boolean|null); - - /** GetThrottlerStatusResponse is_open */ - is_open?: (boolean|null); - - /** GetThrottlerStatusResponse is_enabled */ - is_enabled?: (boolean|null); - - /** GetThrottlerStatusResponse is_dormant */ - is_dormant?: (boolean|null); - - /** GetThrottlerStatusResponse lag_metric_query */ - lag_metric_query?: (string|null); - - /** GetThrottlerStatusResponse custom_metric_query */ - custom_metric_query?: (string|null); - - /** GetThrottlerStatusResponse default_threshold */ - default_threshold?: (number|null); - - /** GetThrottlerStatusResponse metric_name_used_as_default */ - metric_name_used_as_default?: (string|null); - - /** GetThrottlerStatusResponse aggregated_metrics */ - aggregated_metrics?: ({ [k: string]: vtctldata.GetThrottlerStatusResponse.IMetricResult }|null); - - /** GetThrottlerStatusResponse metric_thresholds */ - metric_thresholds?: ({ [k: string]: number }|null); - - /** GetThrottlerStatusResponse metrics_health */ - metrics_health?: ({ [k: string]: vtctldata.GetThrottlerStatusResponse.IMetricHealth }|null); - - /** GetThrottlerStatusResponse throttled_apps */ - throttled_apps?: ({ [k: string]: topodata.IThrottledAppRule }|null); - - /** GetThrottlerStatusResponse app_checked_metrics */ - app_checked_metrics?: ({ [k: string]: string }|null); - - /** GetThrottlerStatusResponse recently_checked */ - recently_checked?: (boolean|null); - - /** GetThrottlerStatusResponse recent_apps */ - recent_apps?: ({ [k: string]: vtctldata.GetThrottlerStatusResponse.IRecentApp }|null); + /** GetThrottlerStatusResponse status */ + status?: (tabletmanagerdata.IGetThrottlerStatusResponse|null); } /** Represents a GetThrottlerStatusResponse. */ @@ -58712,59 +58920,8 @@ export namespace vtctldata { */ constructor(properties?: vtctldata.IGetThrottlerStatusResponse); - /** GetThrottlerStatusResponse tablet_alias. */ - public tablet_alias: string; - - /** GetThrottlerStatusResponse keyspace. */ - public keyspace: string; - - /** GetThrottlerStatusResponse shard. */ - public shard: string; - - /** GetThrottlerStatusResponse is_leader. */ - public is_leader: boolean; - - /** GetThrottlerStatusResponse is_open. */ - public is_open: boolean; - - /** GetThrottlerStatusResponse is_enabled. */ - public is_enabled: boolean; - - /** GetThrottlerStatusResponse is_dormant. */ - public is_dormant: boolean; - - /** GetThrottlerStatusResponse lag_metric_query. */ - public lag_metric_query: string; - - /** GetThrottlerStatusResponse custom_metric_query. */ - public custom_metric_query: string; - - /** GetThrottlerStatusResponse default_threshold. */ - public default_threshold: number; - - /** GetThrottlerStatusResponse metric_name_used_as_default. */ - public metric_name_used_as_default: string; - - /** GetThrottlerStatusResponse aggregated_metrics. */ - public aggregated_metrics: { [k: string]: vtctldata.GetThrottlerStatusResponse.IMetricResult }; - - /** GetThrottlerStatusResponse metric_thresholds. */ - public metric_thresholds: { [k: string]: number }; - - /** GetThrottlerStatusResponse metrics_health. */ - public metrics_health: { [k: string]: vtctldata.GetThrottlerStatusResponse.IMetricHealth }; - - /** GetThrottlerStatusResponse throttled_apps. */ - public throttled_apps: { [k: string]: topodata.IThrottledAppRule }; - - /** GetThrottlerStatusResponse app_checked_metrics. */ - public app_checked_metrics: { [k: string]: string }; - - /** GetThrottlerStatusResponse recently_checked. */ - public recently_checked: boolean; - - /** GetThrottlerStatusResponse recent_apps. */ - public recent_apps: { [k: string]: vtctldata.GetThrottlerStatusResponse.IRecentApp }; + /** GetThrottlerStatusResponse status. */ + public status?: (tabletmanagerdata.IGetThrottlerStatusResponse|null); /** * Creates a new GetThrottlerStatusResponse instance using the specified properties. @@ -58844,318 +59001,6 @@ export namespace vtctldata { public static getTypeUrl(typeUrlPrefix?: string): string; } - namespace GetThrottlerStatusResponse { - - /** Properties of a MetricResult. */ - interface IMetricResult { - - /** MetricResult value */ - value?: (number|null); - - /** MetricResult error */ - error?: (string|null); - } - - /** Represents a MetricResult. */ - class MetricResult implements IMetricResult { - - /** - * Constructs a new MetricResult. - * @param [properties] Properties to set - */ - constructor(properties?: vtctldata.GetThrottlerStatusResponse.IMetricResult); - - /** MetricResult value. */ - public value: number; - - /** MetricResult error. */ - public error: string; - - /** - * Creates a new MetricResult instance using the specified properties. - * @param [properties] Properties to set - * @returns MetricResult instance - */ - public static create(properties?: vtctldata.GetThrottlerStatusResponse.IMetricResult): vtctldata.GetThrottlerStatusResponse.MetricResult; - - /** - * Encodes the specified MetricResult message. Does not implicitly {@link vtctldata.GetThrottlerStatusResponse.MetricResult.verify|verify} messages. - * @param message MetricResult message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encode(message: vtctldata.GetThrottlerStatusResponse.IMetricResult, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Encodes the specified MetricResult message, length delimited. Does not implicitly {@link vtctldata.GetThrottlerStatusResponse.MetricResult.verify|verify} messages. - * @param message MetricResult message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encodeDelimited(message: vtctldata.GetThrottlerStatusResponse.IMetricResult, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Decodes a MetricResult message from the specified reader or buffer. - * @param reader Reader or buffer to decode from - * @param [length] Message length if known beforehand - * @returns MetricResult - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): vtctldata.GetThrottlerStatusResponse.MetricResult; - - /** - * Decodes a MetricResult message from the specified reader or buffer, length delimited. - * @param reader Reader or buffer to decode from - * @returns MetricResult - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): vtctldata.GetThrottlerStatusResponse.MetricResult; - - /** - * Verifies a MetricResult message. - * @param message Plain object to verify - * @returns `null` if valid, otherwise the reason why it is not - */ - public static verify(message: { [k: string]: any }): (string|null); - - /** - * Creates a MetricResult message from a plain object. Also converts values to their respective internal types. - * @param object Plain object - * @returns MetricResult - */ - public static fromObject(object: { [k: string]: any }): vtctldata.GetThrottlerStatusResponse.MetricResult; - - /** - * Creates a plain object from a MetricResult message. Also converts values to other types if specified. - * @param message MetricResult - * @param [options] Conversion options - * @returns Plain object - */ - public static toObject(message: vtctldata.GetThrottlerStatusResponse.MetricResult, options?: $protobuf.IConversionOptions): { [k: string]: any }; - - /** - * Converts this MetricResult to JSON. - * @returns JSON object - */ - public toJSON(): { [k: string]: any }; - - /** - * Gets the default type url for MetricResult - * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns The default type url - */ - public static getTypeUrl(typeUrlPrefix?: string): string; - } - - /** Properties of a MetricHealth. */ - interface IMetricHealth { - - /** MetricHealth last_healthy_at */ - last_healthy_at?: (vttime.ITime|null); - - /** MetricHealth seconds_since_last_healthy */ - seconds_since_last_healthy?: (number|Long|null); - } - - /** Represents a MetricHealth. */ - class MetricHealth implements IMetricHealth { - - /** - * Constructs a new MetricHealth. - * @param [properties] Properties to set - */ - constructor(properties?: vtctldata.GetThrottlerStatusResponse.IMetricHealth); - - /** MetricHealth last_healthy_at. */ - public last_healthy_at?: (vttime.ITime|null); - - /** MetricHealth seconds_since_last_healthy. */ - public seconds_since_last_healthy: (number|Long); - - /** - * Creates a new MetricHealth instance using the specified properties. - * @param [properties] Properties to set - * @returns MetricHealth instance - */ - public static create(properties?: vtctldata.GetThrottlerStatusResponse.IMetricHealth): vtctldata.GetThrottlerStatusResponse.MetricHealth; - - /** - * Encodes the specified MetricHealth message. Does not implicitly {@link vtctldata.GetThrottlerStatusResponse.MetricHealth.verify|verify} messages. - * @param message MetricHealth message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encode(message: vtctldata.GetThrottlerStatusResponse.IMetricHealth, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Encodes the specified MetricHealth message, length delimited. Does not implicitly {@link vtctldata.GetThrottlerStatusResponse.MetricHealth.verify|verify} messages. - * @param message MetricHealth message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encodeDelimited(message: vtctldata.GetThrottlerStatusResponse.IMetricHealth, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Decodes a MetricHealth message from the specified reader or buffer. - * @param reader Reader or buffer to decode from - * @param [length] Message length if known beforehand - * @returns MetricHealth - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): vtctldata.GetThrottlerStatusResponse.MetricHealth; - - /** - * Decodes a MetricHealth message from the specified reader or buffer, length delimited. - * @param reader Reader or buffer to decode from - * @returns MetricHealth - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): vtctldata.GetThrottlerStatusResponse.MetricHealth; - - /** - * Verifies a MetricHealth message. - * @param message Plain object to verify - * @returns `null` if valid, otherwise the reason why it is not - */ - public static verify(message: { [k: string]: any }): (string|null); - - /** - * Creates a MetricHealth message from a plain object. Also converts values to their respective internal types. - * @param object Plain object - * @returns MetricHealth - */ - public static fromObject(object: { [k: string]: any }): vtctldata.GetThrottlerStatusResponse.MetricHealth; - - /** - * Creates a plain object from a MetricHealth message. Also converts values to other types if specified. - * @param message MetricHealth - * @param [options] Conversion options - * @returns Plain object - */ - public static toObject(message: vtctldata.GetThrottlerStatusResponse.MetricHealth, options?: $protobuf.IConversionOptions): { [k: string]: any }; - - /** - * Converts this MetricHealth to JSON. - * @returns JSON object - */ - public toJSON(): { [k: string]: any }; - - /** - * Gets the default type url for MetricHealth - * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns The default type url - */ - public static getTypeUrl(typeUrlPrefix?: string): string; - } - - /** Properties of a RecentApp. */ - interface IRecentApp { - - /** RecentApp checked_at */ - checked_at?: (vttime.ITime|null); - - /** RecentApp status_code */ - status_code?: (number|null); - } - - /** Represents a RecentApp. */ - class RecentApp implements IRecentApp { - - /** - * Constructs a new RecentApp. - * @param [properties] Properties to set - */ - constructor(properties?: vtctldata.GetThrottlerStatusResponse.IRecentApp); - - /** RecentApp checked_at. */ - public checked_at?: (vttime.ITime|null); - - /** RecentApp status_code. */ - public status_code: number; - - /** - * Creates a new RecentApp instance using the specified properties. - * @param [properties] Properties to set - * @returns RecentApp instance - */ - public static create(properties?: vtctldata.GetThrottlerStatusResponse.IRecentApp): vtctldata.GetThrottlerStatusResponse.RecentApp; - - /** - * Encodes the specified RecentApp message. Does not implicitly {@link vtctldata.GetThrottlerStatusResponse.RecentApp.verify|verify} messages. - * @param message RecentApp message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encode(message: vtctldata.GetThrottlerStatusResponse.IRecentApp, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Encodes the specified RecentApp message, length delimited. Does not implicitly {@link vtctldata.GetThrottlerStatusResponse.RecentApp.verify|verify} messages. - * @param message RecentApp message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encodeDelimited(message: vtctldata.GetThrottlerStatusResponse.IRecentApp, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Decodes a RecentApp message from the specified reader or buffer. - * @param reader Reader or buffer to decode from - * @param [length] Message length if known beforehand - * @returns RecentApp - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): vtctldata.GetThrottlerStatusResponse.RecentApp; - - /** - * Decodes a RecentApp message from the specified reader or buffer, length delimited. - * @param reader Reader or buffer to decode from - * @returns RecentApp - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): vtctldata.GetThrottlerStatusResponse.RecentApp; - - /** - * Verifies a RecentApp message. - * @param message Plain object to verify - * @returns `null` if valid, otherwise the reason why it is not - */ - public static verify(message: { [k: string]: any }): (string|null); - - /** - * Creates a RecentApp message from a plain object. Also converts values to their respective internal types. - * @param object Plain object - * @returns RecentApp - */ - public static fromObject(object: { [k: string]: any }): vtctldata.GetThrottlerStatusResponse.RecentApp; - - /** - * Creates a plain object from a RecentApp message. Also converts values to other types if specified. - * @param message RecentApp - * @param [options] Conversion options - * @returns Plain object - */ - public static toObject(message: vtctldata.GetThrottlerStatusResponse.RecentApp, options?: $protobuf.IConversionOptions): { [k: string]: any }; - - /** - * Converts this RecentApp to JSON. - * @returns JSON object - */ - public toJSON(): { [k: string]: any }; - - /** - * Gets the default type url for RecentApp - * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns The default type url - */ - public static getTypeUrl(typeUrlPrefix?: string): string; - } - } - /** Properties of a GetTopologyPathRequest. */ interface IGetTopologyPathRequest { @@ -73976,4 +73821,416 @@ export namespace vtctldata { public static getTypeUrl(typeUrlPrefix?: string): string; } } + + /** Properties of a GetMirrorRulesRequest. */ + interface IGetMirrorRulesRequest { + } + + /** Represents a GetMirrorRulesRequest. */ + class GetMirrorRulesRequest implements IGetMirrorRulesRequest { + + /** + * Constructs a new GetMirrorRulesRequest. + * @param [properties] Properties to set + */ + constructor(properties?: vtctldata.IGetMirrorRulesRequest); + + /** + * Creates a new GetMirrorRulesRequest instance using the specified properties. + * @param [properties] Properties to set + * @returns GetMirrorRulesRequest instance + */ + public static create(properties?: vtctldata.IGetMirrorRulesRequest): vtctldata.GetMirrorRulesRequest; + + /** + * Encodes the specified GetMirrorRulesRequest message. Does not implicitly {@link vtctldata.GetMirrorRulesRequest.verify|verify} messages. + * @param message GetMirrorRulesRequest message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encode(message: vtctldata.IGetMirrorRulesRequest, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified GetMirrorRulesRequest message, length delimited. Does not implicitly {@link vtctldata.GetMirrorRulesRequest.verify|verify} messages. + * @param message GetMirrorRulesRequest message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: vtctldata.IGetMirrorRulesRequest, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a GetMirrorRulesRequest message from the specified reader or buffer. + * @param reader Reader or buffer to decode from + * @param [length] Message length if known beforehand + * @returns GetMirrorRulesRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): vtctldata.GetMirrorRulesRequest; + + /** + * Decodes a GetMirrorRulesRequest message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns GetMirrorRulesRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): vtctldata.GetMirrorRulesRequest; + + /** + * Verifies a GetMirrorRulesRequest message. + * @param message Plain object to verify + * @returns `null` if valid, otherwise the reason why it is not + */ + public static verify(message: { [k: string]: any }): (string|null); + + /** + * Creates a GetMirrorRulesRequest message from a plain object. Also converts values to their respective internal types. + * @param object Plain object + * @returns GetMirrorRulesRequest + */ + public static fromObject(object: { [k: string]: any }): vtctldata.GetMirrorRulesRequest; + + /** + * Creates a plain object from a GetMirrorRulesRequest message. Also converts values to other types if specified. + * @param message GetMirrorRulesRequest + * @param [options] Conversion options + * @returns Plain object + */ + public static toObject(message: vtctldata.GetMirrorRulesRequest, options?: $protobuf.IConversionOptions): { [k: string]: any }; + + /** + * Converts this GetMirrorRulesRequest to JSON. + * @returns JSON object + */ + public toJSON(): { [k: string]: any }; + + /** + * Gets the default type url for GetMirrorRulesRequest + * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns The default type url + */ + public static getTypeUrl(typeUrlPrefix?: string): string; + } + + /** Properties of a GetMirrorRulesResponse. */ + interface IGetMirrorRulesResponse { + + /** GetMirrorRulesResponse mirror_rules */ + mirror_rules?: (vschema.IMirrorRules|null); + } + + /** Represents a GetMirrorRulesResponse. */ + class GetMirrorRulesResponse implements IGetMirrorRulesResponse { + + /** + * Constructs a new GetMirrorRulesResponse. + * @param [properties] Properties to set + */ + constructor(properties?: vtctldata.IGetMirrorRulesResponse); + + /** GetMirrorRulesResponse mirror_rules. */ + public mirror_rules?: (vschema.IMirrorRules|null); + + /** + * Creates a new GetMirrorRulesResponse instance using the specified properties. + * @param [properties] Properties to set + * @returns GetMirrorRulesResponse instance + */ + public static create(properties?: vtctldata.IGetMirrorRulesResponse): vtctldata.GetMirrorRulesResponse; + + /** + * Encodes the specified GetMirrorRulesResponse message. Does not implicitly {@link vtctldata.GetMirrorRulesResponse.verify|verify} messages. + * @param message GetMirrorRulesResponse message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encode(message: vtctldata.IGetMirrorRulesResponse, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified GetMirrorRulesResponse message, length delimited. Does not implicitly {@link vtctldata.GetMirrorRulesResponse.verify|verify} messages. + * @param message GetMirrorRulesResponse message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: vtctldata.IGetMirrorRulesResponse, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a GetMirrorRulesResponse message from the specified reader or buffer. + * @param reader Reader or buffer to decode from + * @param [length] Message length if known beforehand + * @returns GetMirrorRulesResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): vtctldata.GetMirrorRulesResponse; + + /** + * Decodes a GetMirrorRulesResponse message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns GetMirrorRulesResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): vtctldata.GetMirrorRulesResponse; + + /** + * Verifies a GetMirrorRulesResponse message. + * @param message Plain object to verify + * @returns `null` if valid, otherwise the reason why it is not + */ + public static verify(message: { [k: string]: any }): (string|null); + + /** + * Creates a GetMirrorRulesResponse message from a plain object. Also converts values to their respective internal types. + * @param object Plain object + * @returns GetMirrorRulesResponse + */ + public static fromObject(object: { [k: string]: any }): vtctldata.GetMirrorRulesResponse; + + /** + * Creates a plain object from a GetMirrorRulesResponse message. Also converts values to other types if specified. + * @param message GetMirrorRulesResponse + * @param [options] Conversion options + * @returns Plain object + */ + public static toObject(message: vtctldata.GetMirrorRulesResponse, options?: $protobuf.IConversionOptions): { [k: string]: any }; + + /** + * Converts this GetMirrorRulesResponse to JSON. + * @returns JSON object + */ + public toJSON(): { [k: string]: any }; + + /** + * Gets the default type url for GetMirrorRulesResponse + * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns The default type url + */ + public static getTypeUrl(typeUrlPrefix?: string): string; + } + + /** Properties of a WorkflowMirrorTrafficRequest. */ + interface IWorkflowMirrorTrafficRequest { + + /** WorkflowMirrorTrafficRequest keyspace */ + keyspace?: (string|null); + + /** WorkflowMirrorTrafficRequest workflow */ + workflow?: (string|null); + + /** WorkflowMirrorTrafficRequest tablet_types */ + tablet_types?: (topodata.TabletType[]|null); + + /** WorkflowMirrorTrafficRequest percent */ + percent?: (number|null); + } + + /** Represents a WorkflowMirrorTrafficRequest. */ + class WorkflowMirrorTrafficRequest implements IWorkflowMirrorTrafficRequest { + + /** + * Constructs a new WorkflowMirrorTrafficRequest. + * @param [properties] Properties to set + */ + constructor(properties?: vtctldata.IWorkflowMirrorTrafficRequest); + + /** WorkflowMirrorTrafficRequest keyspace. */ + public keyspace: string; + + /** WorkflowMirrorTrafficRequest workflow. */ + public workflow: string; + + /** WorkflowMirrorTrafficRequest tablet_types. */ + public tablet_types: topodata.TabletType[]; + + /** WorkflowMirrorTrafficRequest percent. */ + public percent: number; + + /** + * Creates a new WorkflowMirrorTrafficRequest instance using the specified properties. + * @param [properties] Properties to set + * @returns WorkflowMirrorTrafficRequest instance + */ + public static create(properties?: vtctldata.IWorkflowMirrorTrafficRequest): vtctldata.WorkflowMirrorTrafficRequest; + + /** + * Encodes the specified WorkflowMirrorTrafficRequest message. Does not implicitly {@link vtctldata.WorkflowMirrorTrafficRequest.verify|verify} messages. + * @param message WorkflowMirrorTrafficRequest message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encode(message: vtctldata.IWorkflowMirrorTrafficRequest, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified WorkflowMirrorTrafficRequest message, length delimited. Does not implicitly {@link vtctldata.WorkflowMirrorTrafficRequest.verify|verify} messages. + * @param message WorkflowMirrorTrafficRequest message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: vtctldata.IWorkflowMirrorTrafficRequest, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a WorkflowMirrorTrafficRequest message from the specified reader or buffer. + * @param reader Reader or buffer to decode from + * @param [length] Message length if known beforehand + * @returns WorkflowMirrorTrafficRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): vtctldata.WorkflowMirrorTrafficRequest; + + /** + * Decodes a WorkflowMirrorTrafficRequest message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns WorkflowMirrorTrafficRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): vtctldata.WorkflowMirrorTrafficRequest; + + /** + * Verifies a WorkflowMirrorTrafficRequest message. + * @param message Plain object to verify + * @returns `null` if valid, otherwise the reason why it is not + */ + public static verify(message: { [k: string]: any }): (string|null); + + /** + * Creates a WorkflowMirrorTrafficRequest message from a plain object. Also converts values to their respective internal types. + * @param object Plain object + * @returns WorkflowMirrorTrafficRequest + */ + public static fromObject(object: { [k: string]: any }): vtctldata.WorkflowMirrorTrafficRequest; + + /** + * Creates a plain object from a WorkflowMirrorTrafficRequest message. Also converts values to other types if specified. + * @param message WorkflowMirrorTrafficRequest + * @param [options] Conversion options + * @returns Plain object + */ + public static toObject(message: vtctldata.WorkflowMirrorTrafficRequest, options?: $protobuf.IConversionOptions): { [k: string]: any }; + + /** + * Converts this WorkflowMirrorTrafficRequest to JSON. + * @returns JSON object + */ + public toJSON(): { [k: string]: any }; + + /** + * Gets the default type url for WorkflowMirrorTrafficRequest + * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns The default type url + */ + public static getTypeUrl(typeUrlPrefix?: string): string; + } + + /** Properties of a WorkflowMirrorTrafficResponse. */ + interface IWorkflowMirrorTrafficResponse { + + /** WorkflowMirrorTrafficResponse summary */ + summary?: (string|null); + + /** WorkflowMirrorTrafficResponse start_state */ + start_state?: (string|null); + + /** WorkflowMirrorTrafficResponse current_state */ + current_state?: (string|null); + } + + /** Represents a WorkflowMirrorTrafficResponse. */ + class WorkflowMirrorTrafficResponse implements IWorkflowMirrorTrafficResponse { + + /** + * Constructs a new WorkflowMirrorTrafficResponse. + * @param [properties] Properties to set + */ + constructor(properties?: vtctldata.IWorkflowMirrorTrafficResponse); + + /** WorkflowMirrorTrafficResponse summary. */ + public summary: string; + + /** WorkflowMirrorTrafficResponse start_state. */ + public start_state: string; + + /** WorkflowMirrorTrafficResponse current_state. */ + public current_state: string; + + /** + * Creates a new WorkflowMirrorTrafficResponse instance using the specified properties. + * @param [properties] Properties to set + * @returns WorkflowMirrorTrafficResponse instance + */ + public static create(properties?: vtctldata.IWorkflowMirrorTrafficResponse): vtctldata.WorkflowMirrorTrafficResponse; + + /** + * Encodes the specified WorkflowMirrorTrafficResponse message. Does not implicitly {@link vtctldata.WorkflowMirrorTrafficResponse.verify|verify} messages. + * @param message WorkflowMirrorTrafficResponse message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encode(message: vtctldata.IWorkflowMirrorTrafficResponse, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified WorkflowMirrorTrafficResponse message, length delimited. Does not implicitly {@link vtctldata.WorkflowMirrorTrafficResponse.verify|verify} messages. + * @param message WorkflowMirrorTrafficResponse message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: vtctldata.IWorkflowMirrorTrafficResponse, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a WorkflowMirrorTrafficResponse message from the specified reader or buffer. + * @param reader Reader or buffer to decode from + * @param [length] Message length if known beforehand + * @returns WorkflowMirrorTrafficResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): vtctldata.WorkflowMirrorTrafficResponse; + + /** + * Decodes a WorkflowMirrorTrafficResponse message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns WorkflowMirrorTrafficResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): vtctldata.WorkflowMirrorTrafficResponse; + + /** + * Verifies a WorkflowMirrorTrafficResponse message. + * @param message Plain object to verify + * @returns `null` if valid, otherwise the reason why it is not + */ + public static verify(message: { [k: string]: any }): (string|null); + + /** + * Creates a WorkflowMirrorTrafficResponse message from a plain object. Also converts values to their respective internal types. + * @param object Plain object + * @returns WorkflowMirrorTrafficResponse + */ + public static fromObject(object: { [k: string]: any }): vtctldata.WorkflowMirrorTrafficResponse; + + /** + * Creates a plain object from a WorkflowMirrorTrafficResponse message. Also converts values to other types if specified. + * @param message WorkflowMirrorTrafficResponse + * @param [options] Conversion options + * @returns Plain object + */ + public static toObject(message: vtctldata.WorkflowMirrorTrafficResponse, options?: $protobuf.IConversionOptions): { [k: string]: any }; + + /** + * Converts this WorkflowMirrorTrafficResponse to JSON. + * @returns JSON object + */ + public toJSON(): { [k: string]: any }; + + /** + * Gets the default type url for WorkflowMirrorTrafficResponse + * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns The default type url + */ + public static getTypeUrl(typeUrlPrefix?: string): string; + } } diff --git a/web/vtadmin/src/proto/vtadmin.js b/web/vtadmin/src/proto/vtadmin.js index eca2d8aa0e7..d3b9f6ead0e 100644 --- a/web/vtadmin/src/proto/vtadmin.js +++ b/web/vtadmin/src/proto/vtadmin.js @@ -85549,6 +85549,7 @@ export const query = $root.query = (() => { * @property {number} HEXNUM=4128 HEXNUM value * @property {number} HEXVAL=4129 HEXVAL value * @property {number} BITNUM=4130 BITNUM value + * @property {number} VECTOR=2083 VECTOR value */ query.Type = (function() { const valuesById = {}, values = Object.create(valuesById); @@ -85587,6 +85588,7 @@ export const query = $root.query = (() => { values[valuesById[4128] = "HEXNUM"] = 4128; values[valuesById[4129] = "HEXVAL"] = 4129; values[valuesById[4130] = "BITNUM"] = 4130; + values[valuesById[2083] = "VECTOR"] = 2083; return values; })(); @@ -85775,6 +85777,7 @@ export const query = $root.query = (() => { case 4128: case 4129: case 4130: + case 2083: break; } if (message.value != null && message.hasOwnProperty("value")) @@ -85942,6 +85945,10 @@ export const query = $root.query = (() => { case 4130: message.type = 4130; break; + case "VECTOR": + case 2083: + message.type = 2083; + break; } if (object.value != null) if (typeof object.value === "string") @@ -86214,6 +86221,7 @@ export const query = $root.query = (() => { case 4128: case 4129: case 4130: + case 2083: break; } if (message.value != null && message.hasOwnProperty("value")) @@ -86390,6 +86398,10 @@ export const query = $root.query = (() => { case 4130: message.type = 4130; break; + case "VECTOR": + case 2083: + message.type = 2083; + break; } if (object.value != null) if (typeof object.value === "string") @@ -87880,6 +87892,7 @@ export const query = $root.query = (() => { case 4128: case 4129: case 4130: + case 2083: break; } if (message.table != null && message.hasOwnProperty("table")) @@ -88073,6 +88086,10 @@ export const query = $root.query = (() => { case 4130: message.type = 4130; break; + case "VECTOR": + case 2083: + message.type = 2083; + break; } if (object.table != null) message.table = String(object.table); @@ -96678,6 +96695,495 @@ export const query = $root.query = (() => { return ReadTransactionResponse; })(); + query.UnresolvedTransactionsRequest = (function() { + + /** + * Properties of an UnresolvedTransactionsRequest. + * @memberof query + * @interface IUnresolvedTransactionsRequest + * @property {vtrpc.ICallerID|null} [effective_caller_id] UnresolvedTransactionsRequest effective_caller_id + * @property {query.IVTGateCallerID|null} [immediate_caller_id] UnresolvedTransactionsRequest immediate_caller_id + * @property {query.ITarget|null} [target] UnresolvedTransactionsRequest target + */ + + /** + * Constructs a new UnresolvedTransactionsRequest. + * @memberof query + * @classdesc Represents an UnresolvedTransactionsRequest. + * @implements IUnresolvedTransactionsRequest + * @constructor + * @param {query.IUnresolvedTransactionsRequest=} [properties] Properties to set + */ + function UnresolvedTransactionsRequest(properties) { + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * UnresolvedTransactionsRequest effective_caller_id. + * @member {vtrpc.ICallerID|null|undefined} effective_caller_id + * @memberof query.UnresolvedTransactionsRequest + * @instance + */ + UnresolvedTransactionsRequest.prototype.effective_caller_id = null; + + /** + * UnresolvedTransactionsRequest immediate_caller_id. + * @member {query.IVTGateCallerID|null|undefined} immediate_caller_id + * @memberof query.UnresolvedTransactionsRequest + * @instance + */ + UnresolvedTransactionsRequest.prototype.immediate_caller_id = null; + + /** + * UnresolvedTransactionsRequest target. + * @member {query.ITarget|null|undefined} target + * @memberof query.UnresolvedTransactionsRequest + * @instance + */ + UnresolvedTransactionsRequest.prototype.target = null; + + /** + * Creates a new UnresolvedTransactionsRequest instance using the specified properties. + * @function create + * @memberof query.UnresolvedTransactionsRequest + * @static + * @param {query.IUnresolvedTransactionsRequest=} [properties] Properties to set + * @returns {query.UnresolvedTransactionsRequest} UnresolvedTransactionsRequest instance + */ + UnresolvedTransactionsRequest.create = function create(properties) { + return new UnresolvedTransactionsRequest(properties); + }; + + /** + * Encodes the specified UnresolvedTransactionsRequest message. Does not implicitly {@link query.UnresolvedTransactionsRequest.verify|verify} messages. + * @function encode + * @memberof query.UnresolvedTransactionsRequest + * @static + * @param {query.IUnresolvedTransactionsRequest} message UnresolvedTransactionsRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + UnresolvedTransactionsRequest.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.effective_caller_id != null && Object.hasOwnProperty.call(message, "effective_caller_id")) + $root.vtrpc.CallerID.encode(message.effective_caller_id, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + if (message.immediate_caller_id != null && Object.hasOwnProperty.call(message, "immediate_caller_id")) + $root.query.VTGateCallerID.encode(message.immediate_caller_id, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); + if (message.target != null && Object.hasOwnProperty.call(message, "target")) + $root.query.Target.encode(message.target, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified UnresolvedTransactionsRequest message, length delimited. Does not implicitly {@link query.UnresolvedTransactionsRequest.verify|verify} messages. + * @function encodeDelimited + * @memberof query.UnresolvedTransactionsRequest + * @static + * @param {query.IUnresolvedTransactionsRequest} message UnresolvedTransactionsRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + UnresolvedTransactionsRequest.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes an UnresolvedTransactionsRequest message from the specified reader or buffer. + * @function decode + * @memberof query.UnresolvedTransactionsRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {query.UnresolvedTransactionsRequest} UnresolvedTransactionsRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + UnresolvedTransactionsRequest.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, message = new $root.query.UnresolvedTransactionsRequest(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.effective_caller_id = $root.vtrpc.CallerID.decode(reader, reader.uint32()); + break; + } + case 2: { + message.immediate_caller_id = $root.query.VTGateCallerID.decode(reader, reader.uint32()); + break; + } + case 3: { + message.target = $root.query.Target.decode(reader, reader.uint32()); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes an UnresolvedTransactionsRequest message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof query.UnresolvedTransactionsRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {query.UnresolvedTransactionsRequest} UnresolvedTransactionsRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + UnresolvedTransactionsRequest.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies an UnresolvedTransactionsRequest message. + * @function verify + * @memberof query.UnresolvedTransactionsRequest + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + UnresolvedTransactionsRequest.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.effective_caller_id != null && message.hasOwnProperty("effective_caller_id")) { + let error = $root.vtrpc.CallerID.verify(message.effective_caller_id); + if (error) + return "effective_caller_id." + error; + } + if (message.immediate_caller_id != null && message.hasOwnProperty("immediate_caller_id")) { + let error = $root.query.VTGateCallerID.verify(message.immediate_caller_id); + if (error) + return "immediate_caller_id." + error; + } + if (message.target != null && message.hasOwnProperty("target")) { + let error = $root.query.Target.verify(message.target); + if (error) + return "target." + error; + } + return null; + }; + + /** + * Creates an UnresolvedTransactionsRequest message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof query.UnresolvedTransactionsRequest + * @static + * @param {Object.} object Plain object + * @returns {query.UnresolvedTransactionsRequest} UnresolvedTransactionsRequest + */ + UnresolvedTransactionsRequest.fromObject = function fromObject(object) { + if (object instanceof $root.query.UnresolvedTransactionsRequest) + return object; + let message = new $root.query.UnresolvedTransactionsRequest(); + if (object.effective_caller_id != null) { + if (typeof object.effective_caller_id !== "object") + throw TypeError(".query.UnresolvedTransactionsRequest.effective_caller_id: object expected"); + message.effective_caller_id = $root.vtrpc.CallerID.fromObject(object.effective_caller_id); + } + if (object.immediate_caller_id != null) { + if (typeof object.immediate_caller_id !== "object") + throw TypeError(".query.UnresolvedTransactionsRequest.immediate_caller_id: object expected"); + message.immediate_caller_id = $root.query.VTGateCallerID.fromObject(object.immediate_caller_id); + } + if (object.target != null) { + if (typeof object.target !== "object") + throw TypeError(".query.UnresolvedTransactionsRequest.target: object expected"); + message.target = $root.query.Target.fromObject(object.target); + } + return message; + }; + + /** + * Creates a plain object from an UnresolvedTransactionsRequest message. Also converts values to other types if specified. + * @function toObject + * @memberof query.UnresolvedTransactionsRequest + * @static + * @param {query.UnresolvedTransactionsRequest} message UnresolvedTransactionsRequest + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + UnresolvedTransactionsRequest.toObject = function toObject(message, options) { + if (!options) + options = {}; + let object = {}; + if (options.defaults) { + object.effective_caller_id = null; + object.immediate_caller_id = null; + object.target = null; + } + if (message.effective_caller_id != null && message.hasOwnProperty("effective_caller_id")) + object.effective_caller_id = $root.vtrpc.CallerID.toObject(message.effective_caller_id, options); + if (message.immediate_caller_id != null && message.hasOwnProperty("immediate_caller_id")) + object.immediate_caller_id = $root.query.VTGateCallerID.toObject(message.immediate_caller_id, options); + if (message.target != null && message.hasOwnProperty("target")) + object.target = $root.query.Target.toObject(message.target, options); + return object; + }; + + /** + * Converts this UnresolvedTransactionsRequest to JSON. + * @function toJSON + * @memberof query.UnresolvedTransactionsRequest + * @instance + * @returns {Object.} JSON object + */ + UnresolvedTransactionsRequest.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for UnresolvedTransactionsRequest + * @function getTypeUrl + * @memberof query.UnresolvedTransactionsRequest + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + UnresolvedTransactionsRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/query.UnresolvedTransactionsRequest"; + }; + + return UnresolvedTransactionsRequest; + })(); + + query.UnresolvedTransactionsResponse = (function() { + + /** + * Properties of an UnresolvedTransactionsResponse. + * @memberof query + * @interface IUnresolvedTransactionsResponse + * @property {Array.|null} [transactions] UnresolvedTransactionsResponse transactions + */ + + /** + * Constructs a new UnresolvedTransactionsResponse. + * @memberof query + * @classdesc Represents an UnresolvedTransactionsResponse. + * @implements IUnresolvedTransactionsResponse + * @constructor + * @param {query.IUnresolvedTransactionsResponse=} [properties] Properties to set + */ + function UnresolvedTransactionsResponse(properties) { + this.transactions = []; + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * UnresolvedTransactionsResponse transactions. + * @member {Array.} transactions + * @memberof query.UnresolvedTransactionsResponse + * @instance + */ + UnresolvedTransactionsResponse.prototype.transactions = $util.emptyArray; + + /** + * Creates a new UnresolvedTransactionsResponse instance using the specified properties. + * @function create + * @memberof query.UnresolvedTransactionsResponse + * @static + * @param {query.IUnresolvedTransactionsResponse=} [properties] Properties to set + * @returns {query.UnresolvedTransactionsResponse} UnresolvedTransactionsResponse instance + */ + UnresolvedTransactionsResponse.create = function create(properties) { + return new UnresolvedTransactionsResponse(properties); + }; + + /** + * Encodes the specified UnresolvedTransactionsResponse message. Does not implicitly {@link query.UnresolvedTransactionsResponse.verify|verify} messages. + * @function encode + * @memberof query.UnresolvedTransactionsResponse + * @static + * @param {query.IUnresolvedTransactionsResponse} message UnresolvedTransactionsResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + UnresolvedTransactionsResponse.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.transactions != null && message.transactions.length) + for (let i = 0; i < message.transactions.length; ++i) + $root.query.TransactionMetadata.encode(message.transactions[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified UnresolvedTransactionsResponse message, length delimited. Does not implicitly {@link query.UnresolvedTransactionsResponse.verify|verify} messages. + * @function encodeDelimited + * @memberof query.UnresolvedTransactionsResponse + * @static + * @param {query.IUnresolvedTransactionsResponse} message UnresolvedTransactionsResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + UnresolvedTransactionsResponse.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes an UnresolvedTransactionsResponse message from the specified reader or buffer. + * @function decode + * @memberof query.UnresolvedTransactionsResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {query.UnresolvedTransactionsResponse} UnresolvedTransactionsResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + UnresolvedTransactionsResponse.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, message = new $root.query.UnresolvedTransactionsResponse(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (!(message.transactions && message.transactions.length)) + message.transactions = []; + message.transactions.push($root.query.TransactionMetadata.decode(reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes an UnresolvedTransactionsResponse message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof query.UnresolvedTransactionsResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {query.UnresolvedTransactionsResponse} UnresolvedTransactionsResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + UnresolvedTransactionsResponse.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies an UnresolvedTransactionsResponse message. + * @function verify + * @memberof query.UnresolvedTransactionsResponse + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + UnresolvedTransactionsResponse.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.transactions != null && message.hasOwnProperty("transactions")) { + if (!Array.isArray(message.transactions)) + return "transactions: array expected"; + for (let i = 0; i < message.transactions.length; ++i) { + let error = $root.query.TransactionMetadata.verify(message.transactions[i]); + if (error) + return "transactions." + error; + } + } + return null; + }; + + /** + * Creates an UnresolvedTransactionsResponse message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof query.UnresolvedTransactionsResponse + * @static + * @param {Object.} object Plain object + * @returns {query.UnresolvedTransactionsResponse} UnresolvedTransactionsResponse + */ + UnresolvedTransactionsResponse.fromObject = function fromObject(object) { + if (object instanceof $root.query.UnresolvedTransactionsResponse) + return object; + let message = new $root.query.UnresolvedTransactionsResponse(); + if (object.transactions) { + if (!Array.isArray(object.transactions)) + throw TypeError(".query.UnresolvedTransactionsResponse.transactions: array expected"); + message.transactions = []; + for (let i = 0; i < object.transactions.length; ++i) { + if (typeof object.transactions[i] !== "object") + throw TypeError(".query.UnresolvedTransactionsResponse.transactions: object expected"); + message.transactions[i] = $root.query.TransactionMetadata.fromObject(object.transactions[i]); + } + } + return message; + }; + + /** + * Creates a plain object from an UnresolvedTransactionsResponse message. Also converts values to other types if specified. + * @function toObject + * @memberof query.UnresolvedTransactionsResponse + * @static + * @param {query.UnresolvedTransactionsResponse} message UnresolvedTransactionsResponse + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + UnresolvedTransactionsResponse.toObject = function toObject(message, options) { + if (!options) + options = {}; + let object = {}; + if (options.arrays || options.defaults) + object.transactions = []; + if (message.transactions && message.transactions.length) { + object.transactions = []; + for (let j = 0; j < message.transactions.length; ++j) + object.transactions[j] = $root.query.TransactionMetadata.toObject(message.transactions[j], options); + } + return object; + }; + + /** + * Converts this UnresolvedTransactionsResponse to JSON. + * @function toJSON + * @memberof query.UnresolvedTransactionsResponse + * @instance + * @returns {Object.} JSON object + */ + UnresolvedTransactionsResponse.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for UnresolvedTransactionsResponse + * @function getTypeUrl + * @memberof query.UnresolvedTransactionsResponse + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + UnresolvedTransactionsResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/query.UnresolvedTransactionsResponse"; + }; + + return UnresolvedTransactionsResponse; + })(); + query.BeginExecuteRequest = (function() { /** @@ -102791,6 +103297,7 @@ export const query = $root.query = (() => { * @property {Array.|null} [table_schema_changed] RealtimeStats table_schema_changed * @property {Array.|null} [view_schema_changed] RealtimeStats view_schema_changed * @property {boolean|null} [udfs_changed] RealtimeStats udfs_changed + * @property {boolean|null} [tx_unresolved] RealtimeStats tx_unresolved */ /** @@ -102882,6 +103389,14 @@ export const query = $root.query = (() => { */ RealtimeStats.prototype.udfs_changed = false; + /** + * RealtimeStats tx_unresolved. + * @member {boolean} tx_unresolved + * @memberof query.RealtimeStats + * @instance + */ + RealtimeStats.prototype.tx_unresolved = false; + /** * Creates a new RealtimeStats instance using the specified properties. * @function create @@ -102926,6 +103441,8 @@ export const query = $root.query = (() => { writer.uint32(/* id 8, wireType 2 =*/66).string(message.view_schema_changed[i]); if (message.udfs_changed != null && Object.hasOwnProperty.call(message, "udfs_changed")) writer.uint32(/* id 9, wireType 0 =*/72).bool(message.udfs_changed); + if (message.tx_unresolved != null && Object.hasOwnProperty.call(message, "tx_unresolved")) + writer.uint32(/* id 10, wireType 0 =*/80).bool(message.tx_unresolved); return writer; }; @@ -103000,6 +103517,10 @@ export const query = $root.query = (() => { message.udfs_changed = reader.bool(); break; } + case 10: { + message.tx_unresolved = reader.bool(); + break; + } default: reader.skipType(tag & 7); break; @@ -103070,6 +103591,9 @@ export const query = $root.query = (() => { if (message.udfs_changed != null && message.hasOwnProperty("udfs_changed")) if (typeof message.udfs_changed !== "boolean") return "udfs_changed: boolean expected"; + if (message.tx_unresolved != null && message.hasOwnProperty("tx_unresolved")) + if (typeof message.tx_unresolved !== "boolean") + return "tx_unresolved: boolean expected"; return null; }; @@ -103120,6 +103644,8 @@ export const query = $root.query = (() => { } if (object.udfs_changed != null) message.udfs_changed = Boolean(object.udfs_changed); + if (object.tx_unresolved != null) + message.tx_unresolved = Boolean(object.tx_unresolved); return message; }; @@ -103152,6 +103678,7 @@ export const query = $root.query = (() => { object.cpu_usage = 0; object.qps = 0; object.udfs_changed = false; + object.tx_unresolved = false; } if (message.health_error != null && message.hasOwnProperty("health_error")) object.health_error = message.health_error; @@ -103180,6 +103707,8 @@ export const query = $root.query = (() => { } if (message.udfs_changed != null && message.hasOwnProperty("udfs_changed")) object.udfs_changed = message.udfs_changed; + if (message.tx_unresolved != null && message.hasOwnProperty("tx_unresolved")) + object.tx_unresolved = message.tx_unresolved; return object; }; @@ -103816,15 +104345,15 @@ export const query = $root.query = (() => { * @enum {number} * @property {number} UNKNOWN=0 UNKNOWN value * @property {number} PREPARE=1 PREPARE value - * @property {number} COMMIT=2 COMMIT value - * @property {number} ROLLBACK=3 ROLLBACK value + * @property {number} ROLLBACK=2 ROLLBACK value + * @property {number} COMMIT=3 COMMIT value */ query.TransactionState = (function() { const valuesById = {}, values = Object.create(valuesById); values[valuesById[0] = "UNKNOWN"] = 0; values[valuesById[1] = "PREPARE"] = 1; - values[valuesById[2] = "COMMIT"] = 2; - values[valuesById[3] = "ROLLBACK"] = 3; + values[valuesById[2] = "ROLLBACK"] = 2; + values[valuesById[3] = "COMMIT"] = 3; return values; })(); @@ -104065,11 +104594,11 @@ export const query = $root.query = (() => { case 1: message.state = 1; break; - case "COMMIT": + case "ROLLBACK": case 2: message.state = 2; break; - case "ROLLBACK": + case "COMMIT": case 3: message.state = 3; break; @@ -104691,6 +105220,7 @@ export const query = $root.query = (() => { case 4128: case 4129: case 4130: + case 2083: break; } return null; @@ -104859,6 +105389,10 @@ export const query = $root.query = (() => { case 4130: message.return_type = 4130; break; + case "VECTOR": + case 2083: + message.return_type = 2083; + break; } return message; }; @@ -108445,6 +108979,7 @@ export const vschema = $root.vschema = (() => { case 4128: case 4129: case 4130: + case 2083: break; } return null; @@ -108611,6 +109146,10 @@ export const vschema = $root.vschema = (() => { case 4130: message.tenant_id_column_type = 4130; break; + case "VECTOR": + case 2083: + message.tenant_id_column_type = 2083; + break; } return message; }; @@ -110151,6 +110690,7 @@ export const vschema = $root.vschema = (() => { case 4128: case 4129: case 4130: + case 2083: break; } if (message.invisible != null && message.hasOwnProperty("invisible")) @@ -110344,6 +110884,10 @@ export const vschema = $root.vschema = (() => { case 4130: message.type = 4130; break; + case "VECTOR": + case 2083: + message.type = 2083; + break; } if (object.invisible != null) message.invisible = Boolean(object.invisible); @@ -110457,6 +111001,7 @@ export const vschema = $root.vschema = (() => { * @property {vschema.IRoutingRules|null} [routing_rules] SrvVSchema routing_rules * @property {vschema.IShardRoutingRules|null} [shard_routing_rules] SrvVSchema shard_routing_rules * @property {vschema.IKeyspaceRoutingRules|null} [keyspace_routing_rules] SrvVSchema keyspace_routing_rules + * @property {vschema.IMirrorRules|null} [mirror_rules] SrvVSchema mirror_rules */ /** @@ -110507,6 +111052,14 @@ export const vschema = $root.vschema = (() => { */ SrvVSchema.prototype.keyspace_routing_rules = null; + /** + * SrvVSchema mirror_rules. + * @member {vschema.IMirrorRules|null|undefined} mirror_rules + * @memberof vschema.SrvVSchema + * @instance + */ + SrvVSchema.prototype.mirror_rules = null; + /** * Creates a new SrvVSchema instance using the specified properties. * @function create @@ -110542,6 +111095,8 @@ export const vschema = $root.vschema = (() => { $root.vschema.ShardRoutingRules.encode(message.shard_routing_rules, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); if (message.keyspace_routing_rules != null && Object.hasOwnProperty.call(message, "keyspace_routing_rules")) $root.vschema.KeyspaceRoutingRules.encode(message.keyspace_routing_rules, writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim(); + if (message.mirror_rules != null && Object.hasOwnProperty.call(message, "mirror_rules")) + $root.vschema.MirrorRules.encode(message.mirror_rules, writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim(); return writer; }; @@ -110611,6 +111166,10 @@ export const vschema = $root.vschema = (() => { message.keyspace_routing_rules = $root.vschema.KeyspaceRoutingRules.decode(reader, reader.uint32()); break; } + case 5: { + message.mirror_rules = $root.vschema.MirrorRules.decode(reader, reader.uint32()); + break; + } default: reader.skipType(tag & 7); break; @@ -110671,6 +111230,11 @@ export const vschema = $root.vschema = (() => { if (error) return "keyspace_routing_rules." + error; } + if (message.mirror_rules != null && message.hasOwnProperty("mirror_rules")) { + let error = $root.vschema.MirrorRules.verify(message.mirror_rules); + if (error) + return "mirror_rules." + error; + } return null; }; @@ -110711,6 +111275,11 @@ export const vschema = $root.vschema = (() => { throw TypeError(".vschema.SrvVSchema.keyspace_routing_rules: object expected"); message.keyspace_routing_rules = $root.vschema.KeyspaceRoutingRules.fromObject(object.keyspace_routing_rules); } + if (object.mirror_rules != null) { + if (typeof object.mirror_rules !== "object") + throw TypeError(".vschema.SrvVSchema.mirror_rules: object expected"); + message.mirror_rules = $root.vschema.MirrorRules.fromObject(object.mirror_rules); + } return message; }; @@ -110733,6 +111302,7 @@ export const vschema = $root.vschema = (() => { object.routing_rules = null; object.shard_routing_rules = null; object.keyspace_routing_rules = null; + object.mirror_rules = null; } let keys2; if (message.keyspaces && (keys2 = Object.keys(message.keyspaces)).length) { @@ -110746,6 +111316,8 @@ export const vschema = $root.vschema = (() => { object.shard_routing_rules = $root.vschema.ShardRoutingRules.toObject(message.shard_routing_rules, options); if (message.keyspace_routing_rules != null && message.hasOwnProperty("keyspace_routing_rules")) object.keyspace_routing_rules = $root.vschema.KeyspaceRoutingRules.toObject(message.keyspace_routing_rules, options); + if (message.mirror_rules != null && message.hasOwnProperty("mirror_rules")) + object.mirror_rules = $root.vschema.MirrorRules.toObject(message.mirror_rules, options); return object; }; @@ -111703,6 +112275,480 @@ export const vschema = $root.vschema = (() => { return KeyspaceRoutingRule; })(); + vschema.MirrorRules = (function() { + + /** + * Properties of a MirrorRules. + * @memberof vschema + * @interface IMirrorRules + * @property {Array.|null} [rules] MirrorRules rules + */ + + /** + * Constructs a new MirrorRules. + * @memberof vschema + * @classdesc Represents a MirrorRules. + * @implements IMirrorRules + * @constructor + * @param {vschema.IMirrorRules=} [properties] Properties to set + */ + function MirrorRules(properties) { + this.rules = []; + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * MirrorRules rules. + * @member {Array.} rules + * @memberof vschema.MirrorRules + * @instance + */ + MirrorRules.prototype.rules = $util.emptyArray; + + /** + * Creates a new MirrorRules instance using the specified properties. + * @function create + * @memberof vschema.MirrorRules + * @static + * @param {vschema.IMirrorRules=} [properties] Properties to set + * @returns {vschema.MirrorRules} MirrorRules instance + */ + MirrorRules.create = function create(properties) { + return new MirrorRules(properties); + }; + + /** + * Encodes the specified MirrorRules message. Does not implicitly {@link vschema.MirrorRules.verify|verify} messages. + * @function encode + * @memberof vschema.MirrorRules + * @static + * @param {vschema.IMirrorRules} message MirrorRules message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + MirrorRules.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.rules != null && message.rules.length) + for (let i = 0; i < message.rules.length; ++i) + $root.vschema.MirrorRule.encode(message.rules[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified MirrorRules message, length delimited. Does not implicitly {@link vschema.MirrorRules.verify|verify} messages. + * @function encodeDelimited + * @memberof vschema.MirrorRules + * @static + * @param {vschema.IMirrorRules} message MirrorRules message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + MirrorRules.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a MirrorRules message from the specified reader or buffer. + * @function decode + * @memberof vschema.MirrorRules + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {vschema.MirrorRules} MirrorRules + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + MirrorRules.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vschema.MirrorRules(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (!(message.rules && message.rules.length)) + message.rules = []; + message.rules.push($root.vschema.MirrorRule.decode(reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a MirrorRules message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof vschema.MirrorRules + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {vschema.MirrorRules} MirrorRules + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + MirrorRules.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a MirrorRules message. + * @function verify + * @memberof vschema.MirrorRules + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + MirrorRules.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.rules != null && message.hasOwnProperty("rules")) { + if (!Array.isArray(message.rules)) + return "rules: array expected"; + for (let i = 0; i < message.rules.length; ++i) { + let error = $root.vschema.MirrorRule.verify(message.rules[i]); + if (error) + return "rules." + error; + } + } + return null; + }; + + /** + * Creates a MirrorRules message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof vschema.MirrorRules + * @static + * @param {Object.} object Plain object + * @returns {vschema.MirrorRules} MirrorRules + */ + MirrorRules.fromObject = function fromObject(object) { + if (object instanceof $root.vschema.MirrorRules) + return object; + let message = new $root.vschema.MirrorRules(); + if (object.rules) { + if (!Array.isArray(object.rules)) + throw TypeError(".vschema.MirrorRules.rules: array expected"); + message.rules = []; + for (let i = 0; i < object.rules.length; ++i) { + if (typeof object.rules[i] !== "object") + throw TypeError(".vschema.MirrorRules.rules: object expected"); + message.rules[i] = $root.vschema.MirrorRule.fromObject(object.rules[i]); + } + } + return message; + }; + + /** + * Creates a plain object from a MirrorRules message. Also converts values to other types if specified. + * @function toObject + * @memberof vschema.MirrorRules + * @static + * @param {vschema.MirrorRules} message MirrorRules + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + MirrorRules.toObject = function toObject(message, options) { + if (!options) + options = {}; + let object = {}; + if (options.arrays || options.defaults) + object.rules = []; + if (message.rules && message.rules.length) { + object.rules = []; + for (let j = 0; j < message.rules.length; ++j) + object.rules[j] = $root.vschema.MirrorRule.toObject(message.rules[j], options); + } + return object; + }; + + /** + * Converts this MirrorRules to JSON. + * @function toJSON + * @memberof vschema.MirrorRules + * @instance + * @returns {Object.} JSON object + */ + MirrorRules.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for MirrorRules + * @function getTypeUrl + * @memberof vschema.MirrorRules + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + MirrorRules.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/vschema.MirrorRules"; + }; + + return MirrorRules; + })(); + + vschema.MirrorRule = (function() { + + /** + * Properties of a MirrorRule. + * @memberof vschema + * @interface IMirrorRule + * @property {string|null} [from_table] MirrorRule from_table + * @property {string|null} [to_table] MirrorRule to_table + * @property {number|null} [percent] MirrorRule percent + */ + + /** + * Constructs a new MirrorRule. + * @memberof vschema + * @classdesc Represents a MirrorRule. + * @implements IMirrorRule + * @constructor + * @param {vschema.IMirrorRule=} [properties] Properties to set + */ + function MirrorRule(properties) { + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * MirrorRule from_table. + * @member {string} from_table + * @memberof vschema.MirrorRule + * @instance + */ + MirrorRule.prototype.from_table = ""; + + /** + * MirrorRule to_table. + * @member {string} to_table + * @memberof vschema.MirrorRule + * @instance + */ + MirrorRule.prototype.to_table = ""; + + /** + * MirrorRule percent. + * @member {number} percent + * @memberof vschema.MirrorRule + * @instance + */ + MirrorRule.prototype.percent = 0; + + /** + * Creates a new MirrorRule instance using the specified properties. + * @function create + * @memberof vschema.MirrorRule + * @static + * @param {vschema.IMirrorRule=} [properties] Properties to set + * @returns {vschema.MirrorRule} MirrorRule instance + */ + MirrorRule.create = function create(properties) { + return new MirrorRule(properties); + }; + + /** + * Encodes the specified MirrorRule message. Does not implicitly {@link vschema.MirrorRule.verify|verify} messages. + * @function encode + * @memberof vschema.MirrorRule + * @static + * @param {vschema.IMirrorRule} message MirrorRule message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + MirrorRule.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.from_table != null && Object.hasOwnProperty.call(message, "from_table")) + writer.uint32(/* id 1, wireType 2 =*/10).string(message.from_table); + if (message.to_table != null && Object.hasOwnProperty.call(message, "to_table")) + writer.uint32(/* id 2, wireType 2 =*/18).string(message.to_table); + if (message.percent != null && Object.hasOwnProperty.call(message, "percent")) + writer.uint32(/* id 3, wireType 5 =*/29).float(message.percent); + return writer; + }; + + /** + * Encodes the specified MirrorRule message, length delimited. Does not implicitly {@link vschema.MirrorRule.verify|verify} messages. + * @function encodeDelimited + * @memberof vschema.MirrorRule + * @static + * @param {vschema.IMirrorRule} message MirrorRule message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + MirrorRule.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a MirrorRule message from the specified reader or buffer. + * @function decode + * @memberof vschema.MirrorRule + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {vschema.MirrorRule} MirrorRule + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + MirrorRule.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vschema.MirrorRule(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.from_table = reader.string(); + break; + } + case 2: { + message.to_table = reader.string(); + break; + } + case 3: { + message.percent = reader.float(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a MirrorRule message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof vschema.MirrorRule + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {vschema.MirrorRule} MirrorRule + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + MirrorRule.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a MirrorRule message. + * @function verify + * @memberof vschema.MirrorRule + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + MirrorRule.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.from_table != null && message.hasOwnProperty("from_table")) + if (!$util.isString(message.from_table)) + return "from_table: string expected"; + if (message.to_table != null && message.hasOwnProperty("to_table")) + if (!$util.isString(message.to_table)) + return "to_table: string expected"; + if (message.percent != null && message.hasOwnProperty("percent")) + if (typeof message.percent !== "number") + return "percent: number expected"; + return null; + }; + + /** + * Creates a MirrorRule message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof vschema.MirrorRule + * @static + * @param {Object.} object Plain object + * @returns {vschema.MirrorRule} MirrorRule + */ + MirrorRule.fromObject = function fromObject(object) { + if (object instanceof $root.vschema.MirrorRule) + return object; + let message = new $root.vschema.MirrorRule(); + if (object.from_table != null) + message.from_table = String(object.from_table); + if (object.to_table != null) + message.to_table = String(object.to_table); + if (object.percent != null) + message.percent = Number(object.percent); + return message; + }; + + /** + * Creates a plain object from a MirrorRule message. Also converts values to other types if specified. + * @function toObject + * @memberof vschema.MirrorRule + * @static + * @param {vschema.MirrorRule} message MirrorRule + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + MirrorRule.toObject = function toObject(message, options) { + if (!options) + options = {}; + let object = {}; + if (options.defaults) { + object.from_table = ""; + object.to_table = ""; + object.percent = 0; + } + if (message.from_table != null && message.hasOwnProperty("from_table")) + object.from_table = message.from_table; + if (message.to_table != null && message.hasOwnProperty("to_table")) + object.to_table = message.to_table; + if (message.percent != null && message.hasOwnProperty("percent")) + object.percent = options.json && !isFinite(message.percent) ? String(message.percent) : message.percent; + return object; + }; + + /** + * Converts this MirrorRule to JSON. + * @function toJSON + * @memberof vschema.MirrorRule + * @instance + * @returns {Object.} JSON object + */ + MirrorRule.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for MirrorRule + * @function getTypeUrl + * @memberof vschema.MirrorRule + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + MirrorRule.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/vschema.MirrorRule"; + }; + + return MirrorRule; + })(); + return vschema; })(); @@ -124433,13 +125479,8 @@ export const vtctldata = $root.vtctldata = (() => { * Properties of a CheckThrottlerResponse. * @memberof vtctldata * @interface ICheckThrottlerResponse - * @property {number|null} [status_code] CheckThrottlerResponse status_code - * @property {number|null} [value] CheckThrottlerResponse value - * @property {number|null} [threshold] CheckThrottlerResponse threshold - * @property {string|null} [error] CheckThrottlerResponse error - * @property {string|null} [message] CheckThrottlerResponse message - * @property {boolean|null} [recently_checked] CheckThrottlerResponse recently_checked - * @property {Object.|null} [metrics] CheckThrottlerResponse metrics + * @property {topodata.ITabletAlias|null} [tablet_alias] CheckThrottlerResponse tablet_alias + * @property {tabletmanagerdata.ICheckThrottlerResponse|null} [Check] CheckThrottlerResponse Check */ /** @@ -124451,7 +125492,6 @@ export const vtctldata = $root.vtctldata = (() => { * @param {vtctldata.ICheckThrottlerResponse=} [properties] Properties to set */ function CheckThrottlerResponse(properties) { - this.metrics = {}; if (properties) for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) @@ -124459,60 +125499,20 @@ export const vtctldata = $root.vtctldata = (() => { } /** - * CheckThrottlerResponse status_code. - * @member {number} status_code - * @memberof vtctldata.CheckThrottlerResponse - * @instance - */ - CheckThrottlerResponse.prototype.status_code = 0; - - /** - * CheckThrottlerResponse value. - * @member {number} value - * @memberof vtctldata.CheckThrottlerResponse - * @instance - */ - CheckThrottlerResponse.prototype.value = 0; - - /** - * CheckThrottlerResponse threshold. - * @member {number} threshold - * @memberof vtctldata.CheckThrottlerResponse - * @instance - */ - CheckThrottlerResponse.prototype.threshold = 0; - - /** - * CheckThrottlerResponse error. - * @member {string} error - * @memberof vtctldata.CheckThrottlerResponse - * @instance - */ - CheckThrottlerResponse.prototype.error = ""; - - /** - * CheckThrottlerResponse message. - * @member {string} message - * @memberof vtctldata.CheckThrottlerResponse - * @instance - */ - CheckThrottlerResponse.prototype.message = ""; - - /** - * CheckThrottlerResponse recently_checked. - * @member {boolean} recently_checked + * CheckThrottlerResponse tablet_alias. + * @member {topodata.ITabletAlias|null|undefined} tablet_alias * @memberof vtctldata.CheckThrottlerResponse * @instance */ - CheckThrottlerResponse.prototype.recently_checked = false; + CheckThrottlerResponse.prototype.tablet_alias = null; /** - * CheckThrottlerResponse metrics. - * @member {Object.} metrics + * CheckThrottlerResponse Check. + * @member {tabletmanagerdata.ICheckThrottlerResponse|null|undefined} Check * @memberof vtctldata.CheckThrottlerResponse * @instance */ - CheckThrottlerResponse.prototype.metrics = $util.emptyObject; + CheckThrottlerResponse.prototype.Check = null; /** * Creates a new CheckThrottlerResponse instance using the specified properties. @@ -124538,23 +125538,10 @@ export const vtctldata = $root.vtctldata = (() => { CheckThrottlerResponse.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.status_code != null && Object.hasOwnProperty.call(message, "status_code")) - writer.uint32(/* id 1, wireType 0 =*/8).int32(message.status_code); - if (message.value != null && Object.hasOwnProperty.call(message, "value")) - writer.uint32(/* id 2, wireType 1 =*/17).double(message.value); - if (message.threshold != null && Object.hasOwnProperty.call(message, "threshold")) - writer.uint32(/* id 3, wireType 1 =*/25).double(message.threshold); - if (message.error != null && Object.hasOwnProperty.call(message, "error")) - writer.uint32(/* id 4, wireType 2 =*/34).string(message.error); - if (message.message != null && Object.hasOwnProperty.call(message, "message")) - writer.uint32(/* id 5, wireType 2 =*/42).string(message.message); - if (message.recently_checked != null && Object.hasOwnProperty.call(message, "recently_checked")) - writer.uint32(/* id 6, wireType 0 =*/48).bool(message.recently_checked); - if (message.metrics != null && Object.hasOwnProperty.call(message, "metrics")) - for (let keys = Object.keys(message.metrics), i = 0; i < keys.length; ++i) { - writer.uint32(/* id 7, wireType 2 =*/58).fork().uint32(/* id 1, wireType 2 =*/10).string(keys[i]); - $root.vtctldata.CheckThrottlerResponse.Metric.encode(message.metrics[keys[i]], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim().ldelim(); - } + if (message.tablet_alias != null && Object.hasOwnProperty.call(message, "tablet_alias")) + $root.topodata.TabletAlias.encode(message.tablet_alias, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + if (message.Check != null && Object.hasOwnProperty.call(message, "Check")) + $root.tabletmanagerdata.CheckThrottlerResponse.encode(message.Check, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); return writer; }; @@ -124585,55 +125572,16 @@ export const vtctldata = $root.vtctldata = (() => { CheckThrottlerResponse.decode = function decode(reader, length) { if (!(reader instanceof $Reader)) reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.CheckThrottlerResponse(), key, value; + let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.CheckThrottlerResponse(); while (reader.pos < end) { let tag = reader.uint32(); switch (tag >>> 3) { case 1: { - message.status_code = reader.int32(); + message.tablet_alias = $root.topodata.TabletAlias.decode(reader, reader.uint32()); break; } case 2: { - message.value = reader.double(); - break; - } - case 3: { - message.threshold = reader.double(); - break; - } - case 4: { - message.error = reader.string(); - break; - } - case 5: { - message.message = reader.string(); - break; - } - case 6: { - message.recently_checked = reader.bool(); - break; - } - case 7: { - if (message.metrics === $util.emptyObject) - message.metrics = {}; - let end2 = reader.uint32() + reader.pos; - key = ""; - value = null; - while (reader.pos < end2) { - let tag2 = reader.uint32(); - switch (tag2 >>> 3) { - case 1: - key = reader.string(); - break; - case 2: - value = $root.vtctldata.CheckThrottlerResponse.Metric.decode(reader, reader.uint32()); - break; - default: - reader.skipType(tag2 & 7); - break; - } - } - message.metrics[key] = value; + message.Check = $root.tabletmanagerdata.CheckThrottlerResponse.decode(reader, reader.uint32()); break; } default: @@ -124671,33 +125619,15 @@ export const vtctldata = $root.vtctldata = (() => { CheckThrottlerResponse.verify = function verify(message) { if (typeof message !== "object" || message === null) return "object expected"; - if (message.status_code != null && message.hasOwnProperty("status_code")) - if (!$util.isInteger(message.status_code)) - return "status_code: integer expected"; - if (message.value != null && message.hasOwnProperty("value")) - if (typeof message.value !== "number") - return "value: number expected"; - if (message.threshold != null && message.hasOwnProperty("threshold")) - if (typeof message.threshold !== "number") - return "threshold: number expected"; - if (message.error != null && message.hasOwnProperty("error")) - if (!$util.isString(message.error)) - return "error: string expected"; - if (message.message != null && message.hasOwnProperty("message")) - if (!$util.isString(message.message)) - return "message: string expected"; - if (message.recently_checked != null && message.hasOwnProperty("recently_checked")) - if (typeof message.recently_checked !== "boolean") - return "recently_checked: boolean expected"; - if (message.metrics != null && message.hasOwnProperty("metrics")) { - if (!$util.isObject(message.metrics)) - return "metrics: object expected"; - let key = Object.keys(message.metrics); - for (let i = 0; i < key.length; ++i) { - let error = $root.vtctldata.CheckThrottlerResponse.Metric.verify(message.metrics[key[i]]); - if (error) - return "metrics." + error; - } + if (message.tablet_alias != null && message.hasOwnProperty("tablet_alias")) { + let error = $root.topodata.TabletAlias.verify(message.tablet_alias); + if (error) + return "tablet_alias." + error; + } + if (message.Check != null && message.hasOwnProperty("Check")) { + let error = $root.tabletmanagerdata.CheckThrottlerResponse.verify(message.Check); + if (error) + return "Check." + error; } return null; }; @@ -124714,27 +125644,15 @@ export const vtctldata = $root.vtctldata = (() => { if (object instanceof $root.vtctldata.CheckThrottlerResponse) return object; let message = new $root.vtctldata.CheckThrottlerResponse(); - if (object.status_code != null) - message.status_code = object.status_code | 0; - if (object.value != null) - message.value = Number(object.value); - if (object.threshold != null) - message.threshold = Number(object.threshold); - if (object.error != null) - message.error = String(object.error); - if (object.message != null) - message.message = String(object.message); - if (object.recently_checked != null) - message.recently_checked = Boolean(object.recently_checked); - if (object.metrics) { - if (typeof object.metrics !== "object") - throw TypeError(".vtctldata.CheckThrottlerResponse.metrics: object expected"); - message.metrics = {}; - for (let keys = Object.keys(object.metrics), i = 0; i < keys.length; ++i) { - if (typeof object.metrics[keys[i]] !== "object") - throw TypeError(".vtctldata.CheckThrottlerResponse.metrics: object expected"); - message.metrics[keys[i]] = $root.vtctldata.CheckThrottlerResponse.Metric.fromObject(object.metrics[keys[i]]); - } + if (object.tablet_alias != null) { + if (typeof object.tablet_alias !== "object") + throw TypeError(".vtctldata.CheckThrottlerResponse.tablet_alias: object expected"); + message.tablet_alias = $root.topodata.TabletAlias.fromObject(object.tablet_alias); + } + if (object.Check != null) { + if (typeof object.Check !== "object") + throw TypeError(".vtctldata.CheckThrottlerResponse.Check: object expected"); + message.Check = $root.tabletmanagerdata.CheckThrottlerResponse.fromObject(object.Check); } return message; }; @@ -124752,34 +125670,14 @@ export const vtctldata = $root.vtctldata = (() => { if (!options) options = {}; let object = {}; - if (options.objects || options.defaults) - object.metrics = {}; if (options.defaults) { - object.status_code = 0; - object.value = 0; - object.threshold = 0; - object.error = ""; - object.message = ""; - object.recently_checked = false; - } - if (message.status_code != null && message.hasOwnProperty("status_code")) - object.status_code = message.status_code; - if (message.value != null && message.hasOwnProperty("value")) - object.value = options.json && !isFinite(message.value) ? String(message.value) : message.value; - if (message.threshold != null && message.hasOwnProperty("threshold")) - object.threshold = options.json && !isFinite(message.threshold) ? String(message.threshold) : message.threshold; - if (message.error != null && message.hasOwnProperty("error")) - object.error = message.error; - if (message.message != null && message.hasOwnProperty("message")) - object.message = message.message; - if (message.recently_checked != null && message.hasOwnProperty("recently_checked")) - object.recently_checked = message.recently_checked; - let keys2; - if (message.metrics && (keys2 = Object.keys(message.metrics)).length) { - object.metrics = {}; - for (let j = 0; j < keys2.length; ++j) - object.metrics[keys2[j]] = $root.vtctldata.CheckThrottlerResponse.Metric.toObject(message.metrics[keys2[j]], options); + object.tablet_alias = null; + object.Check = null; } + if (message.tablet_alias != null && message.hasOwnProperty("tablet_alias")) + object.tablet_alias = $root.topodata.TabletAlias.toObject(message.tablet_alias, options); + if (message.Check != null && message.hasOwnProperty("Check")) + object.Check = $root.tabletmanagerdata.CheckThrottlerResponse.toObject(message.Check, options); return object; }; @@ -124809,348 +125707,6 @@ export const vtctldata = $root.vtctldata = (() => { return typeUrlPrefix + "/vtctldata.CheckThrottlerResponse"; }; - CheckThrottlerResponse.Metric = (function() { - - /** - * Properties of a Metric. - * @memberof vtctldata.CheckThrottlerResponse - * @interface IMetric - * @property {string|null} [name] Metric name - * @property {number|null} [status_code] Metric status_code - * @property {number|null} [value] Metric value - * @property {number|null} [threshold] Metric threshold - * @property {string|null} [error] Metric error - * @property {string|null} [message] Metric message - * @property {string|null} [scope] Metric scope - */ - - /** - * Constructs a new Metric. - * @memberof vtctldata.CheckThrottlerResponse - * @classdesc Represents a Metric. - * @implements IMetric - * @constructor - * @param {vtctldata.CheckThrottlerResponse.IMetric=} [properties] Properties to set - */ - function Metric(properties) { - if (properties) - for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * Metric name. - * @member {string} name - * @memberof vtctldata.CheckThrottlerResponse.Metric - * @instance - */ - Metric.prototype.name = ""; - - /** - * Metric status_code. - * @member {number} status_code - * @memberof vtctldata.CheckThrottlerResponse.Metric - * @instance - */ - Metric.prototype.status_code = 0; - - /** - * Metric value. - * @member {number} value - * @memberof vtctldata.CheckThrottlerResponse.Metric - * @instance - */ - Metric.prototype.value = 0; - - /** - * Metric threshold. - * @member {number} threshold - * @memberof vtctldata.CheckThrottlerResponse.Metric - * @instance - */ - Metric.prototype.threshold = 0; - - /** - * Metric error. - * @member {string} error - * @memberof vtctldata.CheckThrottlerResponse.Metric - * @instance - */ - Metric.prototype.error = ""; - - /** - * Metric message. - * @member {string} message - * @memberof vtctldata.CheckThrottlerResponse.Metric - * @instance - */ - Metric.prototype.message = ""; - - /** - * Metric scope. - * @member {string} scope - * @memberof vtctldata.CheckThrottlerResponse.Metric - * @instance - */ - Metric.prototype.scope = ""; - - /** - * Creates a new Metric instance using the specified properties. - * @function create - * @memberof vtctldata.CheckThrottlerResponse.Metric - * @static - * @param {vtctldata.CheckThrottlerResponse.IMetric=} [properties] Properties to set - * @returns {vtctldata.CheckThrottlerResponse.Metric} Metric instance - */ - Metric.create = function create(properties) { - return new Metric(properties); - }; - - /** - * Encodes the specified Metric message. Does not implicitly {@link vtctldata.CheckThrottlerResponse.Metric.verify|verify} messages. - * @function encode - * @memberof vtctldata.CheckThrottlerResponse.Metric - * @static - * @param {vtctldata.CheckThrottlerResponse.IMetric} message Metric message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Metric.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.name != null && Object.hasOwnProperty.call(message, "name")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.name); - if (message.status_code != null && Object.hasOwnProperty.call(message, "status_code")) - writer.uint32(/* id 2, wireType 0 =*/16).int32(message.status_code); - if (message.value != null && Object.hasOwnProperty.call(message, "value")) - writer.uint32(/* id 3, wireType 1 =*/25).double(message.value); - if (message.threshold != null && Object.hasOwnProperty.call(message, "threshold")) - writer.uint32(/* id 4, wireType 1 =*/33).double(message.threshold); - if (message.error != null && Object.hasOwnProperty.call(message, "error")) - writer.uint32(/* id 5, wireType 2 =*/42).string(message.error); - if (message.message != null && Object.hasOwnProperty.call(message, "message")) - writer.uint32(/* id 6, wireType 2 =*/50).string(message.message); - if (message.scope != null && Object.hasOwnProperty.call(message, "scope")) - writer.uint32(/* id 7, wireType 2 =*/58).string(message.scope); - return writer; - }; - - /** - * Encodes the specified Metric message, length delimited. Does not implicitly {@link vtctldata.CheckThrottlerResponse.Metric.verify|verify} messages. - * @function encodeDelimited - * @memberof vtctldata.CheckThrottlerResponse.Metric - * @static - * @param {vtctldata.CheckThrottlerResponse.IMetric} message Metric message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Metric.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a Metric message from the specified reader or buffer. - * @function decode - * @memberof vtctldata.CheckThrottlerResponse.Metric - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {vtctldata.CheckThrottlerResponse.Metric} Metric - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Metric.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.CheckThrottlerResponse.Metric(); - while (reader.pos < end) { - let tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.name = reader.string(); - break; - } - case 2: { - message.status_code = reader.int32(); - break; - } - case 3: { - message.value = reader.double(); - break; - } - case 4: { - message.threshold = reader.double(); - break; - } - case 5: { - message.error = reader.string(); - break; - } - case 6: { - message.message = reader.string(); - break; - } - case 7: { - message.scope = reader.string(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a Metric message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof vtctldata.CheckThrottlerResponse.Metric - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {vtctldata.CheckThrottlerResponse.Metric} Metric - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Metric.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a Metric message. - * @function verify - * @memberof vtctldata.CheckThrottlerResponse.Metric - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - Metric.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.name != null && message.hasOwnProperty("name")) - if (!$util.isString(message.name)) - return "name: string expected"; - if (message.status_code != null && message.hasOwnProperty("status_code")) - if (!$util.isInteger(message.status_code)) - return "status_code: integer expected"; - if (message.value != null && message.hasOwnProperty("value")) - if (typeof message.value !== "number") - return "value: number expected"; - if (message.threshold != null && message.hasOwnProperty("threshold")) - if (typeof message.threshold !== "number") - return "threshold: number expected"; - if (message.error != null && message.hasOwnProperty("error")) - if (!$util.isString(message.error)) - return "error: string expected"; - if (message.message != null && message.hasOwnProperty("message")) - if (!$util.isString(message.message)) - return "message: string expected"; - if (message.scope != null && message.hasOwnProperty("scope")) - if (!$util.isString(message.scope)) - return "scope: string expected"; - return null; - }; - - /** - * Creates a Metric message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof vtctldata.CheckThrottlerResponse.Metric - * @static - * @param {Object.} object Plain object - * @returns {vtctldata.CheckThrottlerResponse.Metric} Metric - */ - Metric.fromObject = function fromObject(object) { - if (object instanceof $root.vtctldata.CheckThrottlerResponse.Metric) - return object; - let message = new $root.vtctldata.CheckThrottlerResponse.Metric(); - if (object.name != null) - message.name = String(object.name); - if (object.status_code != null) - message.status_code = object.status_code | 0; - if (object.value != null) - message.value = Number(object.value); - if (object.threshold != null) - message.threshold = Number(object.threshold); - if (object.error != null) - message.error = String(object.error); - if (object.message != null) - message.message = String(object.message); - if (object.scope != null) - message.scope = String(object.scope); - return message; - }; - - /** - * Creates a plain object from a Metric message. Also converts values to other types if specified. - * @function toObject - * @memberof vtctldata.CheckThrottlerResponse.Metric - * @static - * @param {vtctldata.CheckThrottlerResponse.Metric} message Metric - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - Metric.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (options.defaults) { - object.name = ""; - object.status_code = 0; - object.value = 0; - object.threshold = 0; - object.error = ""; - object.message = ""; - object.scope = ""; - } - if (message.name != null && message.hasOwnProperty("name")) - object.name = message.name; - if (message.status_code != null && message.hasOwnProperty("status_code")) - object.status_code = message.status_code; - if (message.value != null && message.hasOwnProperty("value")) - object.value = options.json && !isFinite(message.value) ? String(message.value) : message.value; - if (message.threshold != null && message.hasOwnProperty("threshold")) - object.threshold = options.json && !isFinite(message.threshold) ? String(message.threshold) : message.threshold; - if (message.error != null && message.hasOwnProperty("error")) - object.error = message.error; - if (message.message != null && message.hasOwnProperty("message")) - object.message = message.message; - if (message.scope != null && message.hasOwnProperty("scope")) - object.scope = message.scope; - return object; - }; - - /** - * Converts this Metric to JSON. - * @function toJSON - * @memberof vtctldata.CheckThrottlerResponse.Metric - * @instance - * @returns {Object.} JSON object - */ - Metric.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for Metric - * @function getTypeUrl - * @memberof vtctldata.CheckThrottlerResponse.Metric - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - Metric.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/vtctldata.CheckThrottlerResponse.Metric"; - }; - - return Metric; - })(); - return CheckThrottlerResponse; })(); @@ -144057,24 +144613,7 @@ export const vtctldata = $root.vtctldata = (() => { * Properties of a GetThrottlerStatusResponse. * @memberof vtctldata * @interface IGetThrottlerStatusResponse - * @property {string|null} [tablet_alias] GetThrottlerStatusResponse tablet_alias - * @property {string|null} [keyspace] GetThrottlerStatusResponse keyspace - * @property {string|null} [shard] GetThrottlerStatusResponse shard - * @property {boolean|null} [is_leader] GetThrottlerStatusResponse is_leader - * @property {boolean|null} [is_open] GetThrottlerStatusResponse is_open - * @property {boolean|null} [is_enabled] GetThrottlerStatusResponse is_enabled - * @property {boolean|null} [is_dormant] GetThrottlerStatusResponse is_dormant - * @property {string|null} [lag_metric_query] GetThrottlerStatusResponse lag_metric_query - * @property {string|null} [custom_metric_query] GetThrottlerStatusResponse custom_metric_query - * @property {number|null} [default_threshold] GetThrottlerStatusResponse default_threshold - * @property {string|null} [metric_name_used_as_default] GetThrottlerStatusResponse metric_name_used_as_default - * @property {Object.|null} [aggregated_metrics] GetThrottlerStatusResponse aggregated_metrics - * @property {Object.|null} [metric_thresholds] GetThrottlerStatusResponse metric_thresholds - * @property {Object.|null} [metrics_health] GetThrottlerStatusResponse metrics_health - * @property {Object.|null} [throttled_apps] GetThrottlerStatusResponse throttled_apps - * @property {Object.|null} [app_checked_metrics] GetThrottlerStatusResponse app_checked_metrics - * @property {boolean|null} [recently_checked] GetThrottlerStatusResponse recently_checked - * @property {Object.|null} [recent_apps] GetThrottlerStatusResponse recent_apps + * @property {tabletmanagerdata.IGetThrottlerStatusResponse|null} [status] GetThrottlerStatusResponse status */ /** @@ -144086,12 +144625,6 @@ export const vtctldata = $root.vtctldata = (() => { * @param {vtctldata.IGetThrottlerStatusResponse=} [properties] Properties to set */ function GetThrottlerStatusResponse(properties) { - this.aggregated_metrics = {}; - this.metric_thresholds = {}; - this.metrics_health = {}; - this.throttled_apps = {}; - this.app_checked_metrics = {}; - this.recent_apps = {}; if (properties) for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) @@ -144099,148 +144632,12 @@ export const vtctldata = $root.vtctldata = (() => { } /** - * GetThrottlerStatusResponse tablet_alias. - * @member {string} tablet_alias - * @memberof vtctldata.GetThrottlerStatusResponse - * @instance - */ - GetThrottlerStatusResponse.prototype.tablet_alias = ""; - - /** - * GetThrottlerStatusResponse keyspace. - * @member {string} keyspace - * @memberof vtctldata.GetThrottlerStatusResponse - * @instance - */ - GetThrottlerStatusResponse.prototype.keyspace = ""; - - /** - * GetThrottlerStatusResponse shard. - * @member {string} shard - * @memberof vtctldata.GetThrottlerStatusResponse - * @instance - */ - GetThrottlerStatusResponse.prototype.shard = ""; - - /** - * GetThrottlerStatusResponse is_leader. - * @member {boolean} is_leader - * @memberof vtctldata.GetThrottlerStatusResponse - * @instance - */ - GetThrottlerStatusResponse.prototype.is_leader = false; - - /** - * GetThrottlerStatusResponse is_open. - * @member {boolean} is_open - * @memberof vtctldata.GetThrottlerStatusResponse - * @instance - */ - GetThrottlerStatusResponse.prototype.is_open = false; - - /** - * GetThrottlerStatusResponse is_enabled. - * @member {boolean} is_enabled - * @memberof vtctldata.GetThrottlerStatusResponse - * @instance - */ - GetThrottlerStatusResponse.prototype.is_enabled = false; - - /** - * GetThrottlerStatusResponse is_dormant. - * @member {boolean} is_dormant - * @memberof vtctldata.GetThrottlerStatusResponse - * @instance - */ - GetThrottlerStatusResponse.prototype.is_dormant = false; - - /** - * GetThrottlerStatusResponse lag_metric_query. - * @member {string} lag_metric_query - * @memberof vtctldata.GetThrottlerStatusResponse - * @instance - */ - GetThrottlerStatusResponse.prototype.lag_metric_query = ""; - - /** - * GetThrottlerStatusResponse custom_metric_query. - * @member {string} custom_metric_query - * @memberof vtctldata.GetThrottlerStatusResponse - * @instance - */ - GetThrottlerStatusResponse.prototype.custom_metric_query = ""; - - /** - * GetThrottlerStatusResponse default_threshold. - * @member {number} default_threshold - * @memberof vtctldata.GetThrottlerStatusResponse - * @instance - */ - GetThrottlerStatusResponse.prototype.default_threshold = 0; - - /** - * GetThrottlerStatusResponse metric_name_used_as_default. - * @member {string} metric_name_used_as_default - * @memberof vtctldata.GetThrottlerStatusResponse - * @instance - */ - GetThrottlerStatusResponse.prototype.metric_name_used_as_default = ""; - - /** - * GetThrottlerStatusResponse aggregated_metrics. - * @member {Object.} aggregated_metrics - * @memberof vtctldata.GetThrottlerStatusResponse - * @instance - */ - GetThrottlerStatusResponse.prototype.aggregated_metrics = $util.emptyObject; - - /** - * GetThrottlerStatusResponse metric_thresholds. - * @member {Object.} metric_thresholds - * @memberof vtctldata.GetThrottlerStatusResponse - * @instance - */ - GetThrottlerStatusResponse.prototype.metric_thresholds = $util.emptyObject; - - /** - * GetThrottlerStatusResponse metrics_health. - * @member {Object.} metrics_health - * @memberof vtctldata.GetThrottlerStatusResponse - * @instance - */ - GetThrottlerStatusResponse.prototype.metrics_health = $util.emptyObject; - - /** - * GetThrottlerStatusResponse throttled_apps. - * @member {Object.} throttled_apps - * @memberof vtctldata.GetThrottlerStatusResponse - * @instance - */ - GetThrottlerStatusResponse.prototype.throttled_apps = $util.emptyObject; - - /** - * GetThrottlerStatusResponse app_checked_metrics. - * @member {Object.} app_checked_metrics - * @memberof vtctldata.GetThrottlerStatusResponse - * @instance - */ - GetThrottlerStatusResponse.prototype.app_checked_metrics = $util.emptyObject; - - /** - * GetThrottlerStatusResponse recently_checked. - * @member {boolean} recently_checked - * @memberof vtctldata.GetThrottlerStatusResponse - * @instance - */ - GetThrottlerStatusResponse.prototype.recently_checked = false; - - /** - * GetThrottlerStatusResponse recent_apps. - * @member {Object.} recent_apps + * GetThrottlerStatusResponse status. + * @member {tabletmanagerdata.IGetThrottlerStatusResponse|null|undefined} status * @memberof vtctldata.GetThrottlerStatusResponse * @instance */ - GetThrottlerStatusResponse.prototype.recent_apps = $util.emptyObject; + GetThrottlerStatusResponse.prototype.status = null; /** * Creates a new GetThrottlerStatusResponse instance using the specified properties. @@ -144266,56 +144663,8 @@ export const vtctldata = $root.vtctldata = (() => { GetThrottlerStatusResponse.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.tablet_alias != null && Object.hasOwnProperty.call(message, "tablet_alias")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.tablet_alias); - if (message.keyspace != null && Object.hasOwnProperty.call(message, "keyspace")) - writer.uint32(/* id 2, wireType 2 =*/18).string(message.keyspace); - if (message.shard != null && Object.hasOwnProperty.call(message, "shard")) - writer.uint32(/* id 3, wireType 2 =*/26).string(message.shard); - if (message.is_leader != null && Object.hasOwnProperty.call(message, "is_leader")) - writer.uint32(/* id 4, wireType 0 =*/32).bool(message.is_leader); - if (message.is_open != null && Object.hasOwnProperty.call(message, "is_open")) - writer.uint32(/* id 5, wireType 0 =*/40).bool(message.is_open); - if (message.is_enabled != null && Object.hasOwnProperty.call(message, "is_enabled")) - writer.uint32(/* id 6, wireType 0 =*/48).bool(message.is_enabled); - if (message.is_dormant != null && Object.hasOwnProperty.call(message, "is_dormant")) - writer.uint32(/* id 7, wireType 0 =*/56).bool(message.is_dormant); - if (message.lag_metric_query != null && Object.hasOwnProperty.call(message, "lag_metric_query")) - writer.uint32(/* id 8, wireType 2 =*/66).string(message.lag_metric_query); - if (message.custom_metric_query != null && Object.hasOwnProperty.call(message, "custom_metric_query")) - writer.uint32(/* id 9, wireType 2 =*/74).string(message.custom_metric_query); - if (message.default_threshold != null && Object.hasOwnProperty.call(message, "default_threshold")) - writer.uint32(/* id 10, wireType 1 =*/81).double(message.default_threshold); - if (message.metric_name_used_as_default != null && Object.hasOwnProperty.call(message, "metric_name_used_as_default")) - writer.uint32(/* id 11, wireType 2 =*/90).string(message.metric_name_used_as_default); - if (message.aggregated_metrics != null && Object.hasOwnProperty.call(message, "aggregated_metrics")) - for (let keys = Object.keys(message.aggregated_metrics), i = 0; i < keys.length; ++i) { - writer.uint32(/* id 12, wireType 2 =*/98).fork().uint32(/* id 1, wireType 2 =*/10).string(keys[i]); - $root.vtctldata.GetThrottlerStatusResponse.MetricResult.encode(message.aggregated_metrics[keys[i]], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim().ldelim(); - } - if (message.metric_thresholds != null && Object.hasOwnProperty.call(message, "metric_thresholds")) - for (let keys = Object.keys(message.metric_thresholds), i = 0; i < keys.length; ++i) - writer.uint32(/* id 13, wireType 2 =*/106).fork().uint32(/* id 1, wireType 2 =*/10).string(keys[i]).uint32(/* id 2, wireType 1 =*/17).double(message.metric_thresholds[keys[i]]).ldelim(); - if (message.metrics_health != null && Object.hasOwnProperty.call(message, "metrics_health")) - for (let keys = Object.keys(message.metrics_health), i = 0; i < keys.length; ++i) { - writer.uint32(/* id 14, wireType 2 =*/114).fork().uint32(/* id 1, wireType 2 =*/10).string(keys[i]); - $root.vtctldata.GetThrottlerStatusResponse.MetricHealth.encode(message.metrics_health[keys[i]], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim().ldelim(); - } - if (message.throttled_apps != null && Object.hasOwnProperty.call(message, "throttled_apps")) - for (let keys = Object.keys(message.throttled_apps), i = 0; i < keys.length; ++i) { - writer.uint32(/* id 15, wireType 2 =*/122).fork().uint32(/* id 1, wireType 2 =*/10).string(keys[i]); - $root.topodata.ThrottledAppRule.encode(message.throttled_apps[keys[i]], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim().ldelim(); - } - if (message.app_checked_metrics != null && Object.hasOwnProperty.call(message, "app_checked_metrics")) - for (let keys = Object.keys(message.app_checked_metrics), i = 0; i < keys.length; ++i) - writer.uint32(/* id 16, wireType 2 =*/130).fork().uint32(/* id 1, wireType 2 =*/10).string(keys[i]).uint32(/* id 2, wireType 2 =*/18).string(message.app_checked_metrics[keys[i]]).ldelim(); - if (message.recently_checked != null && Object.hasOwnProperty.call(message, "recently_checked")) - writer.uint32(/* id 17, wireType 0 =*/136).bool(message.recently_checked); - if (message.recent_apps != null && Object.hasOwnProperty.call(message, "recent_apps")) - for (let keys = Object.keys(message.recent_apps), i = 0; i < keys.length; ++i) { - writer.uint32(/* id 18, wireType 2 =*/146).fork().uint32(/* id 1, wireType 2 =*/10).string(keys[i]); - $root.vtctldata.GetThrottlerStatusResponse.RecentApp.encode(message.recent_apps[keys[i]], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim().ldelim(); - } + if (message.status != null && Object.hasOwnProperty.call(message, "status")) + $root.tabletmanagerdata.GetThrottlerStatusResponse.encode(message.status, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); return writer; }; @@ -144346,194 +144695,12 @@ export const vtctldata = $root.vtctldata = (() => { GetThrottlerStatusResponse.decode = function decode(reader, length) { if (!(reader instanceof $Reader)) reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.GetThrottlerStatusResponse(), key, value; + let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.GetThrottlerStatusResponse(); while (reader.pos < end) { let tag = reader.uint32(); switch (tag >>> 3) { case 1: { - message.tablet_alias = reader.string(); - break; - } - case 2: { - message.keyspace = reader.string(); - break; - } - case 3: { - message.shard = reader.string(); - break; - } - case 4: { - message.is_leader = reader.bool(); - break; - } - case 5: { - message.is_open = reader.bool(); - break; - } - case 6: { - message.is_enabled = reader.bool(); - break; - } - case 7: { - message.is_dormant = reader.bool(); - break; - } - case 8: { - message.lag_metric_query = reader.string(); - break; - } - case 9: { - message.custom_metric_query = reader.string(); - break; - } - case 10: { - message.default_threshold = reader.double(); - break; - } - case 11: { - message.metric_name_used_as_default = reader.string(); - break; - } - case 12: { - if (message.aggregated_metrics === $util.emptyObject) - message.aggregated_metrics = {}; - let end2 = reader.uint32() + reader.pos; - key = ""; - value = null; - while (reader.pos < end2) { - let tag2 = reader.uint32(); - switch (tag2 >>> 3) { - case 1: - key = reader.string(); - break; - case 2: - value = $root.vtctldata.GetThrottlerStatusResponse.MetricResult.decode(reader, reader.uint32()); - break; - default: - reader.skipType(tag2 & 7); - break; - } - } - message.aggregated_metrics[key] = value; - break; - } - case 13: { - if (message.metric_thresholds === $util.emptyObject) - message.metric_thresholds = {}; - let end2 = reader.uint32() + reader.pos; - key = ""; - value = 0; - while (reader.pos < end2) { - let tag2 = reader.uint32(); - switch (tag2 >>> 3) { - case 1: - key = reader.string(); - break; - case 2: - value = reader.double(); - break; - default: - reader.skipType(tag2 & 7); - break; - } - } - message.metric_thresholds[key] = value; - break; - } - case 14: { - if (message.metrics_health === $util.emptyObject) - message.metrics_health = {}; - let end2 = reader.uint32() + reader.pos; - key = ""; - value = null; - while (reader.pos < end2) { - let tag2 = reader.uint32(); - switch (tag2 >>> 3) { - case 1: - key = reader.string(); - break; - case 2: - value = $root.vtctldata.GetThrottlerStatusResponse.MetricHealth.decode(reader, reader.uint32()); - break; - default: - reader.skipType(tag2 & 7); - break; - } - } - message.metrics_health[key] = value; - break; - } - case 15: { - if (message.throttled_apps === $util.emptyObject) - message.throttled_apps = {}; - let end2 = reader.uint32() + reader.pos; - key = ""; - value = null; - while (reader.pos < end2) { - let tag2 = reader.uint32(); - switch (tag2 >>> 3) { - case 1: - key = reader.string(); - break; - case 2: - value = $root.topodata.ThrottledAppRule.decode(reader, reader.uint32()); - break; - default: - reader.skipType(tag2 & 7); - break; - } - } - message.throttled_apps[key] = value; - break; - } - case 16: { - if (message.app_checked_metrics === $util.emptyObject) - message.app_checked_metrics = {}; - let end2 = reader.uint32() + reader.pos; - key = ""; - value = ""; - while (reader.pos < end2) { - let tag2 = reader.uint32(); - switch (tag2 >>> 3) { - case 1: - key = reader.string(); - break; - case 2: - value = reader.string(); - break; - default: - reader.skipType(tag2 & 7); - break; - } - } - message.app_checked_metrics[key] = value; - break; - } - case 17: { - message.recently_checked = reader.bool(); - break; - } - case 18: { - if (message.recent_apps === $util.emptyObject) - message.recent_apps = {}; - let end2 = reader.uint32() + reader.pos; - key = ""; - value = null; - while (reader.pos < end2) { - let tag2 = reader.uint32(); - switch (tag2 >>> 3) { - case 1: - key = reader.string(); - break; - case 2: - value = $root.vtctldata.GetThrottlerStatusResponse.RecentApp.decode(reader, reader.uint32()); - break; - default: - reader.skipType(tag2 & 7); - break; - } - } - message.recent_apps[key] = value; + message.status = $root.tabletmanagerdata.GetThrottlerStatusResponse.decode(reader, reader.uint32()); break; } default: @@ -144571,97 +144738,10 @@ export const vtctldata = $root.vtctldata = (() => { GetThrottlerStatusResponse.verify = function verify(message) { if (typeof message !== "object" || message === null) return "object expected"; - if (message.tablet_alias != null && message.hasOwnProperty("tablet_alias")) - if (!$util.isString(message.tablet_alias)) - return "tablet_alias: string expected"; - if (message.keyspace != null && message.hasOwnProperty("keyspace")) - if (!$util.isString(message.keyspace)) - return "keyspace: string expected"; - if (message.shard != null && message.hasOwnProperty("shard")) - if (!$util.isString(message.shard)) - return "shard: string expected"; - if (message.is_leader != null && message.hasOwnProperty("is_leader")) - if (typeof message.is_leader !== "boolean") - return "is_leader: boolean expected"; - if (message.is_open != null && message.hasOwnProperty("is_open")) - if (typeof message.is_open !== "boolean") - return "is_open: boolean expected"; - if (message.is_enabled != null && message.hasOwnProperty("is_enabled")) - if (typeof message.is_enabled !== "boolean") - return "is_enabled: boolean expected"; - if (message.is_dormant != null && message.hasOwnProperty("is_dormant")) - if (typeof message.is_dormant !== "boolean") - return "is_dormant: boolean expected"; - if (message.lag_metric_query != null && message.hasOwnProperty("lag_metric_query")) - if (!$util.isString(message.lag_metric_query)) - return "lag_metric_query: string expected"; - if (message.custom_metric_query != null && message.hasOwnProperty("custom_metric_query")) - if (!$util.isString(message.custom_metric_query)) - return "custom_metric_query: string expected"; - if (message.default_threshold != null && message.hasOwnProperty("default_threshold")) - if (typeof message.default_threshold !== "number") - return "default_threshold: number expected"; - if (message.metric_name_used_as_default != null && message.hasOwnProperty("metric_name_used_as_default")) - if (!$util.isString(message.metric_name_used_as_default)) - return "metric_name_used_as_default: string expected"; - if (message.aggregated_metrics != null && message.hasOwnProperty("aggregated_metrics")) { - if (!$util.isObject(message.aggregated_metrics)) - return "aggregated_metrics: object expected"; - let key = Object.keys(message.aggregated_metrics); - for (let i = 0; i < key.length; ++i) { - let error = $root.vtctldata.GetThrottlerStatusResponse.MetricResult.verify(message.aggregated_metrics[key[i]]); - if (error) - return "aggregated_metrics." + error; - } - } - if (message.metric_thresholds != null && message.hasOwnProperty("metric_thresholds")) { - if (!$util.isObject(message.metric_thresholds)) - return "metric_thresholds: object expected"; - let key = Object.keys(message.metric_thresholds); - for (let i = 0; i < key.length; ++i) - if (typeof message.metric_thresholds[key[i]] !== "number") - return "metric_thresholds: number{k:string} expected"; - } - if (message.metrics_health != null && message.hasOwnProperty("metrics_health")) { - if (!$util.isObject(message.metrics_health)) - return "metrics_health: object expected"; - let key = Object.keys(message.metrics_health); - for (let i = 0; i < key.length; ++i) { - let error = $root.vtctldata.GetThrottlerStatusResponse.MetricHealth.verify(message.metrics_health[key[i]]); - if (error) - return "metrics_health." + error; - } - } - if (message.throttled_apps != null && message.hasOwnProperty("throttled_apps")) { - if (!$util.isObject(message.throttled_apps)) - return "throttled_apps: object expected"; - let key = Object.keys(message.throttled_apps); - for (let i = 0; i < key.length; ++i) { - let error = $root.topodata.ThrottledAppRule.verify(message.throttled_apps[key[i]]); - if (error) - return "throttled_apps." + error; - } - } - if (message.app_checked_metrics != null && message.hasOwnProperty("app_checked_metrics")) { - if (!$util.isObject(message.app_checked_metrics)) - return "app_checked_metrics: object expected"; - let key = Object.keys(message.app_checked_metrics); - for (let i = 0; i < key.length; ++i) - if (!$util.isString(message.app_checked_metrics[key[i]])) - return "app_checked_metrics: string{k:string} expected"; - } - if (message.recently_checked != null && message.hasOwnProperty("recently_checked")) - if (typeof message.recently_checked !== "boolean") - return "recently_checked: boolean expected"; - if (message.recent_apps != null && message.hasOwnProperty("recent_apps")) { - if (!$util.isObject(message.recent_apps)) - return "recent_apps: object expected"; - let key = Object.keys(message.recent_apps); - for (let i = 0; i < key.length; ++i) { - let error = $root.vtctldata.GetThrottlerStatusResponse.RecentApp.verify(message.recent_apps[key[i]]); - if (error) - return "recent_apps." + error; - } + if (message.status != null && message.hasOwnProperty("status")) { + let error = $root.tabletmanagerdata.GetThrottlerStatusResponse.verify(message.status); + if (error) + return "status." + error; } return null; }; @@ -144678,83 +144758,10 @@ export const vtctldata = $root.vtctldata = (() => { if (object instanceof $root.vtctldata.GetThrottlerStatusResponse) return object; let message = new $root.vtctldata.GetThrottlerStatusResponse(); - if (object.tablet_alias != null) - message.tablet_alias = String(object.tablet_alias); - if (object.keyspace != null) - message.keyspace = String(object.keyspace); - if (object.shard != null) - message.shard = String(object.shard); - if (object.is_leader != null) - message.is_leader = Boolean(object.is_leader); - if (object.is_open != null) - message.is_open = Boolean(object.is_open); - if (object.is_enabled != null) - message.is_enabled = Boolean(object.is_enabled); - if (object.is_dormant != null) - message.is_dormant = Boolean(object.is_dormant); - if (object.lag_metric_query != null) - message.lag_metric_query = String(object.lag_metric_query); - if (object.custom_metric_query != null) - message.custom_metric_query = String(object.custom_metric_query); - if (object.default_threshold != null) - message.default_threshold = Number(object.default_threshold); - if (object.metric_name_used_as_default != null) - message.metric_name_used_as_default = String(object.metric_name_used_as_default); - if (object.aggregated_metrics) { - if (typeof object.aggregated_metrics !== "object") - throw TypeError(".vtctldata.GetThrottlerStatusResponse.aggregated_metrics: object expected"); - message.aggregated_metrics = {}; - for (let keys = Object.keys(object.aggregated_metrics), i = 0; i < keys.length; ++i) { - if (typeof object.aggregated_metrics[keys[i]] !== "object") - throw TypeError(".vtctldata.GetThrottlerStatusResponse.aggregated_metrics: object expected"); - message.aggregated_metrics[keys[i]] = $root.vtctldata.GetThrottlerStatusResponse.MetricResult.fromObject(object.aggregated_metrics[keys[i]]); - } - } - if (object.metric_thresholds) { - if (typeof object.metric_thresholds !== "object") - throw TypeError(".vtctldata.GetThrottlerStatusResponse.metric_thresholds: object expected"); - message.metric_thresholds = {}; - for (let keys = Object.keys(object.metric_thresholds), i = 0; i < keys.length; ++i) - message.metric_thresholds[keys[i]] = Number(object.metric_thresholds[keys[i]]); - } - if (object.metrics_health) { - if (typeof object.metrics_health !== "object") - throw TypeError(".vtctldata.GetThrottlerStatusResponse.metrics_health: object expected"); - message.metrics_health = {}; - for (let keys = Object.keys(object.metrics_health), i = 0; i < keys.length; ++i) { - if (typeof object.metrics_health[keys[i]] !== "object") - throw TypeError(".vtctldata.GetThrottlerStatusResponse.metrics_health: object expected"); - message.metrics_health[keys[i]] = $root.vtctldata.GetThrottlerStatusResponse.MetricHealth.fromObject(object.metrics_health[keys[i]]); - } - } - if (object.throttled_apps) { - if (typeof object.throttled_apps !== "object") - throw TypeError(".vtctldata.GetThrottlerStatusResponse.throttled_apps: object expected"); - message.throttled_apps = {}; - for (let keys = Object.keys(object.throttled_apps), i = 0; i < keys.length; ++i) { - if (typeof object.throttled_apps[keys[i]] !== "object") - throw TypeError(".vtctldata.GetThrottlerStatusResponse.throttled_apps: object expected"); - message.throttled_apps[keys[i]] = $root.topodata.ThrottledAppRule.fromObject(object.throttled_apps[keys[i]]); - } - } - if (object.app_checked_metrics) { - if (typeof object.app_checked_metrics !== "object") - throw TypeError(".vtctldata.GetThrottlerStatusResponse.app_checked_metrics: object expected"); - message.app_checked_metrics = {}; - for (let keys = Object.keys(object.app_checked_metrics), i = 0; i < keys.length; ++i) - message.app_checked_metrics[keys[i]] = String(object.app_checked_metrics[keys[i]]); - } - if (object.recently_checked != null) - message.recently_checked = Boolean(object.recently_checked); - if (object.recent_apps) { - if (typeof object.recent_apps !== "object") - throw TypeError(".vtctldata.GetThrottlerStatusResponse.recent_apps: object expected"); - message.recent_apps = {}; - for (let keys = Object.keys(object.recent_apps), i = 0; i < keys.length; ++i) { - if (typeof object.recent_apps[keys[i]] !== "object") - throw TypeError(".vtctldata.GetThrottlerStatusResponse.recent_apps: object expected"); - message.recent_apps[keys[i]] = $root.vtctldata.GetThrottlerStatusResponse.RecentApp.fromObject(object.recent_apps[keys[i]]); - } + if (object.status != null) { + if (typeof object.status !== "object") + throw TypeError(".vtctldata.GetThrottlerStatusResponse.status: object expected"); + message.status = $root.tabletmanagerdata.GetThrottlerStatusResponse.fromObject(object.status); } return message; }; @@ -144772,83 +144779,10 @@ export const vtctldata = $root.vtctldata = (() => { if (!options) options = {}; let object = {}; - if (options.objects || options.defaults) { - object.aggregated_metrics = {}; - object.metric_thresholds = {}; - object.metrics_health = {}; - object.throttled_apps = {}; - object.app_checked_metrics = {}; - object.recent_apps = {}; - } - if (options.defaults) { - object.tablet_alias = ""; - object.keyspace = ""; - object.shard = ""; - object.is_leader = false; - object.is_open = false; - object.is_enabled = false; - object.is_dormant = false; - object.lag_metric_query = ""; - object.custom_metric_query = ""; - object.default_threshold = 0; - object.metric_name_used_as_default = ""; - object.recently_checked = false; - } - if (message.tablet_alias != null && message.hasOwnProperty("tablet_alias")) - object.tablet_alias = message.tablet_alias; - if (message.keyspace != null && message.hasOwnProperty("keyspace")) - object.keyspace = message.keyspace; - if (message.shard != null && message.hasOwnProperty("shard")) - object.shard = message.shard; - if (message.is_leader != null && message.hasOwnProperty("is_leader")) - object.is_leader = message.is_leader; - if (message.is_open != null && message.hasOwnProperty("is_open")) - object.is_open = message.is_open; - if (message.is_enabled != null && message.hasOwnProperty("is_enabled")) - object.is_enabled = message.is_enabled; - if (message.is_dormant != null && message.hasOwnProperty("is_dormant")) - object.is_dormant = message.is_dormant; - if (message.lag_metric_query != null && message.hasOwnProperty("lag_metric_query")) - object.lag_metric_query = message.lag_metric_query; - if (message.custom_metric_query != null && message.hasOwnProperty("custom_metric_query")) - object.custom_metric_query = message.custom_metric_query; - if (message.default_threshold != null && message.hasOwnProperty("default_threshold")) - object.default_threshold = options.json && !isFinite(message.default_threshold) ? String(message.default_threshold) : message.default_threshold; - if (message.metric_name_used_as_default != null && message.hasOwnProperty("metric_name_used_as_default")) - object.metric_name_used_as_default = message.metric_name_used_as_default; - let keys2; - if (message.aggregated_metrics && (keys2 = Object.keys(message.aggregated_metrics)).length) { - object.aggregated_metrics = {}; - for (let j = 0; j < keys2.length; ++j) - object.aggregated_metrics[keys2[j]] = $root.vtctldata.GetThrottlerStatusResponse.MetricResult.toObject(message.aggregated_metrics[keys2[j]], options); - } - if (message.metric_thresholds && (keys2 = Object.keys(message.metric_thresholds)).length) { - object.metric_thresholds = {}; - for (let j = 0; j < keys2.length; ++j) - object.metric_thresholds[keys2[j]] = options.json && !isFinite(message.metric_thresholds[keys2[j]]) ? String(message.metric_thresholds[keys2[j]]) : message.metric_thresholds[keys2[j]]; - } - if (message.metrics_health && (keys2 = Object.keys(message.metrics_health)).length) { - object.metrics_health = {}; - for (let j = 0; j < keys2.length; ++j) - object.metrics_health[keys2[j]] = $root.vtctldata.GetThrottlerStatusResponse.MetricHealth.toObject(message.metrics_health[keys2[j]], options); - } - if (message.throttled_apps && (keys2 = Object.keys(message.throttled_apps)).length) { - object.throttled_apps = {}; - for (let j = 0; j < keys2.length; ++j) - object.throttled_apps[keys2[j]] = $root.topodata.ThrottledAppRule.toObject(message.throttled_apps[keys2[j]], options); - } - if (message.app_checked_metrics && (keys2 = Object.keys(message.app_checked_metrics)).length) { - object.app_checked_metrics = {}; - for (let j = 0; j < keys2.length; ++j) - object.app_checked_metrics[keys2[j]] = message.app_checked_metrics[keys2[j]]; - } - if (message.recently_checked != null && message.hasOwnProperty("recently_checked")) - object.recently_checked = message.recently_checked; - if (message.recent_apps && (keys2 = Object.keys(message.recent_apps)).length) { - object.recent_apps = {}; - for (let j = 0; j < keys2.length; ++j) - object.recent_apps[keys2[j]] = $root.vtctldata.GetThrottlerStatusResponse.RecentApp.toObject(message.recent_apps[keys2[j]], options); - } + if (options.defaults) + object.status = null; + if (message.status != null && message.hasOwnProperty("status")) + object.status = $root.tabletmanagerdata.GetThrottlerStatusResponse.toObject(message.status, options); return object; }; @@ -144878,734 +144812,291 @@ export const vtctldata = $root.vtctldata = (() => { return typeUrlPrefix + "/vtctldata.GetThrottlerStatusResponse"; }; - GetThrottlerStatusResponse.MetricResult = (function() { + return GetThrottlerStatusResponse; + })(); - /** - * Properties of a MetricResult. - * @memberof vtctldata.GetThrottlerStatusResponse - * @interface IMetricResult - * @property {number|null} [value] MetricResult value - * @property {string|null} [error] MetricResult error - */ + vtctldata.GetTopologyPathRequest = (function() { - /** - * Constructs a new MetricResult. - * @memberof vtctldata.GetThrottlerStatusResponse - * @classdesc Represents a MetricResult. - * @implements IMetricResult - * @constructor - * @param {vtctldata.GetThrottlerStatusResponse.IMetricResult=} [properties] Properties to set - */ - function MetricResult(properties) { - if (properties) - for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * Properties of a GetTopologyPathRequest. + * @memberof vtctldata + * @interface IGetTopologyPathRequest + * @property {string|null} [path] GetTopologyPathRequest path + * @property {number|Long|null} [version] GetTopologyPathRequest version + * @property {boolean|null} [as_json] GetTopologyPathRequest as_json + */ - /** - * MetricResult value. - * @member {number} value - * @memberof vtctldata.GetThrottlerStatusResponse.MetricResult - * @instance - */ - MetricResult.prototype.value = 0; + /** + * Constructs a new GetTopologyPathRequest. + * @memberof vtctldata + * @classdesc Represents a GetTopologyPathRequest. + * @implements IGetTopologyPathRequest + * @constructor + * @param {vtctldata.IGetTopologyPathRequest=} [properties] Properties to set + */ + function GetTopologyPathRequest(properties) { + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } - /** - * MetricResult error. - * @member {string} error - * @memberof vtctldata.GetThrottlerStatusResponse.MetricResult - * @instance - */ - MetricResult.prototype.error = ""; + /** + * GetTopologyPathRequest path. + * @member {string} path + * @memberof vtctldata.GetTopologyPathRequest + * @instance + */ + GetTopologyPathRequest.prototype.path = ""; - /** - * Creates a new MetricResult instance using the specified properties. - * @function create - * @memberof vtctldata.GetThrottlerStatusResponse.MetricResult - * @static - * @param {vtctldata.GetThrottlerStatusResponse.IMetricResult=} [properties] Properties to set - * @returns {vtctldata.GetThrottlerStatusResponse.MetricResult} MetricResult instance - */ - MetricResult.create = function create(properties) { - return new MetricResult(properties); - }; + /** + * GetTopologyPathRequest version. + * @member {number|Long} version + * @memberof vtctldata.GetTopologyPathRequest + * @instance + */ + GetTopologyPathRequest.prototype.version = $util.Long ? $util.Long.fromBits(0,0,false) : 0; - /** - * Encodes the specified MetricResult message. Does not implicitly {@link vtctldata.GetThrottlerStatusResponse.MetricResult.verify|verify} messages. - * @function encode - * @memberof vtctldata.GetThrottlerStatusResponse.MetricResult - * @static - * @param {vtctldata.GetThrottlerStatusResponse.IMetricResult} message MetricResult message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - MetricResult.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.value != null && Object.hasOwnProperty.call(message, "value")) - writer.uint32(/* id 1, wireType 1 =*/9).double(message.value); - if (message.error != null && Object.hasOwnProperty.call(message, "error")) - writer.uint32(/* id 2, wireType 2 =*/18).string(message.error); - return writer; - }; + /** + * GetTopologyPathRequest as_json. + * @member {boolean} as_json + * @memberof vtctldata.GetTopologyPathRequest + * @instance + */ + GetTopologyPathRequest.prototype.as_json = false; - /** - * Encodes the specified MetricResult message, length delimited. Does not implicitly {@link vtctldata.GetThrottlerStatusResponse.MetricResult.verify|verify} messages. - * @function encodeDelimited - * @memberof vtctldata.GetThrottlerStatusResponse.MetricResult - * @static - * @param {vtctldata.GetThrottlerStatusResponse.IMetricResult} message MetricResult message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - MetricResult.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; + /** + * Creates a new GetTopologyPathRequest instance using the specified properties. + * @function create + * @memberof vtctldata.GetTopologyPathRequest + * @static + * @param {vtctldata.IGetTopologyPathRequest=} [properties] Properties to set + * @returns {vtctldata.GetTopologyPathRequest} GetTopologyPathRequest instance + */ + GetTopologyPathRequest.create = function create(properties) { + return new GetTopologyPathRequest(properties); + }; - /** - * Decodes a MetricResult message from the specified reader or buffer. - * @function decode - * @memberof vtctldata.GetThrottlerStatusResponse.MetricResult - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {vtctldata.GetThrottlerStatusResponse.MetricResult} MetricResult - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - MetricResult.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.GetThrottlerStatusResponse.MetricResult(); - while (reader.pos < end) { - let tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.value = reader.double(); - break; - } - case 2: { - message.error = reader.string(); - break; - } - default: - reader.skipType(tag & 7); + /** + * Encodes the specified GetTopologyPathRequest message. Does not implicitly {@link vtctldata.GetTopologyPathRequest.verify|verify} messages. + * @function encode + * @memberof vtctldata.GetTopologyPathRequest + * @static + * @param {vtctldata.IGetTopologyPathRequest} message GetTopologyPathRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetTopologyPathRequest.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.path != null && Object.hasOwnProperty.call(message, "path")) + writer.uint32(/* id 1, wireType 2 =*/10).string(message.path); + if (message.version != null && Object.hasOwnProperty.call(message, "version")) + writer.uint32(/* id 2, wireType 0 =*/16).int64(message.version); + if (message.as_json != null && Object.hasOwnProperty.call(message, "as_json")) + writer.uint32(/* id 3, wireType 0 =*/24).bool(message.as_json); + return writer; + }; + + /** + * Encodes the specified GetTopologyPathRequest message, length delimited. Does not implicitly {@link vtctldata.GetTopologyPathRequest.verify|verify} messages. + * @function encodeDelimited + * @memberof vtctldata.GetTopologyPathRequest + * @static + * @param {vtctldata.IGetTopologyPathRequest} message GetTopologyPathRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetTopologyPathRequest.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a GetTopologyPathRequest message from the specified reader or buffer. + * @function decode + * @memberof vtctldata.GetTopologyPathRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {vtctldata.GetTopologyPathRequest} GetTopologyPathRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetTopologyPathRequest.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.GetTopologyPathRequest(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.path = reader.string(); + break; + } + case 2: { + message.version = reader.int64(); + break; + } + case 3: { + message.as_json = reader.bool(); break; } + default: + reader.skipType(tag & 7); + break; } - return message; - }; - - /** - * Decodes a MetricResult message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof vtctldata.GetThrottlerStatusResponse.MetricResult - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {vtctldata.GetThrottlerStatusResponse.MetricResult} MetricResult - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - MetricResult.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; + } + return message; + }; - /** - * Verifies a MetricResult message. - * @function verify - * @memberof vtctldata.GetThrottlerStatusResponse.MetricResult - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - MetricResult.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.value != null && message.hasOwnProperty("value")) - if (typeof message.value !== "number") - return "value: number expected"; - if (message.error != null && message.hasOwnProperty("error")) - if (!$util.isString(message.error)) - return "error: string expected"; - return null; - }; + /** + * Decodes a GetTopologyPathRequest message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof vtctldata.GetTopologyPathRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {vtctldata.GetTopologyPathRequest} GetTopologyPathRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetTopologyPathRequest.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; - /** - * Creates a MetricResult message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof vtctldata.GetThrottlerStatusResponse.MetricResult - * @static - * @param {Object.} object Plain object - * @returns {vtctldata.GetThrottlerStatusResponse.MetricResult} MetricResult - */ - MetricResult.fromObject = function fromObject(object) { - if (object instanceof $root.vtctldata.GetThrottlerStatusResponse.MetricResult) - return object; - let message = new $root.vtctldata.GetThrottlerStatusResponse.MetricResult(); - if (object.value != null) - message.value = Number(object.value); - if (object.error != null) - message.error = String(object.error); - return message; - }; + /** + * Verifies a GetTopologyPathRequest message. + * @function verify + * @memberof vtctldata.GetTopologyPathRequest + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + GetTopologyPathRequest.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.path != null && message.hasOwnProperty("path")) + if (!$util.isString(message.path)) + return "path: string expected"; + if (message.version != null && message.hasOwnProperty("version")) + if (!$util.isInteger(message.version) && !(message.version && $util.isInteger(message.version.low) && $util.isInteger(message.version.high))) + return "version: integer|Long expected"; + if (message.as_json != null && message.hasOwnProperty("as_json")) + if (typeof message.as_json !== "boolean") + return "as_json: boolean expected"; + return null; + }; - /** - * Creates a plain object from a MetricResult message. Also converts values to other types if specified. - * @function toObject - * @memberof vtctldata.GetThrottlerStatusResponse.MetricResult - * @static - * @param {vtctldata.GetThrottlerStatusResponse.MetricResult} message MetricResult - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - MetricResult.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (options.defaults) { - object.value = 0; - object.error = ""; - } - if (message.value != null && message.hasOwnProperty("value")) - object.value = options.json && !isFinite(message.value) ? String(message.value) : message.value; - if (message.error != null && message.hasOwnProperty("error")) - object.error = message.error; + /** + * Creates a GetTopologyPathRequest message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof vtctldata.GetTopologyPathRequest + * @static + * @param {Object.} object Plain object + * @returns {vtctldata.GetTopologyPathRequest} GetTopologyPathRequest + */ + GetTopologyPathRequest.fromObject = function fromObject(object) { + if (object instanceof $root.vtctldata.GetTopologyPathRequest) return object; - }; - - /** - * Converts this MetricResult to JSON. - * @function toJSON - * @memberof vtctldata.GetThrottlerStatusResponse.MetricResult - * @instance - * @returns {Object.} JSON object - */ - MetricResult.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for MetricResult - * @function getTypeUrl - * @memberof vtctldata.GetThrottlerStatusResponse.MetricResult - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - MetricResult.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/vtctldata.GetThrottlerStatusResponse.MetricResult"; - }; - - return MetricResult; - })(); + let message = new $root.vtctldata.GetTopologyPathRequest(); + if (object.path != null) + message.path = String(object.path); + if (object.version != null) + if ($util.Long) + (message.version = $util.Long.fromValue(object.version)).unsigned = false; + else if (typeof object.version === "string") + message.version = parseInt(object.version, 10); + else if (typeof object.version === "number") + message.version = object.version; + else if (typeof object.version === "object") + message.version = new $util.LongBits(object.version.low >>> 0, object.version.high >>> 0).toNumber(); + if (object.as_json != null) + message.as_json = Boolean(object.as_json); + return message; + }; - GetThrottlerStatusResponse.MetricHealth = (function() { + /** + * Creates a plain object from a GetTopologyPathRequest message. Also converts values to other types if specified. + * @function toObject + * @memberof vtctldata.GetTopologyPathRequest + * @static + * @param {vtctldata.GetTopologyPathRequest} message GetTopologyPathRequest + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + GetTopologyPathRequest.toObject = function toObject(message, options) { + if (!options) + options = {}; + let object = {}; + if (options.defaults) { + object.path = ""; + if ($util.Long) { + let long = new $util.Long(0, 0, false); + object.version = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.version = options.longs === String ? "0" : 0; + object.as_json = false; + } + if (message.path != null && message.hasOwnProperty("path")) + object.path = message.path; + if (message.version != null && message.hasOwnProperty("version")) + if (typeof message.version === "number") + object.version = options.longs === String ? String(message.version) : message.version; + else + object.version = options.longs === String ? $util.Long.prototype.toString.call(message.version) : options.longs === Number ? new $util.LongBits(message.version.low >>> 0, message.version.high >>> 0).toNumber() : message.version; + if (message.as_json != null && message.hasOwnProperty("as_json")) + object.as_json = message.as_json; + return object; + }; - /** - * Properties of a MetricHealth. - * @memberof vtctldata.GetThrottlerStatusResponse - * @interface IMetricHealth - * @property {vttime.ITime|null} [last_healthy_at] MetricHealth last_healthy_at - * @property {number|Long|null} [seconds_since_last_healthy] MetricHealth seconds_since_last_healthy - */ - - /** - * Constructs a new MetricHealth. - * @memberof vtctldata.GetThrottlerStatusResponse - * @classdesc Represents a MetricHealth. - * @implements IMetricHealth - * @constructor - * @param {vtctldata.GetThrottlerStatusResponse.IMetricHealth=} [properties] Properties to set - */ - function MetricHealth(properties) { - if (properties) - for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * MetricHealth last_healthy_at. - * @member {vttime.ITime|null|undefined} last_healthy_at - * @memberof vtctldata.GetThrottlerStatusResponse.MetricHealth - * @instance - */ - MetricHealth.prototype.last_healthy_at = null; - - /** - * MetricHealth seconds_since_last_healthy. - * @member {number|Long} seconds_since_last_healthy - * @memberof vtctldata.GetThrottlerStatusResponse.MetricHealth - * @instance - */ - MetricHealth.prototype.seconds_since_last_healthy = $util.Long ? $util.Long.fromBits(0,0,false) : 0; - - /** - * Creates a new MetricHealth instance using the specified properties. - * @function create - * @memberof vtctldata.GetThrottlerStatusResponse.MetricHealth - * @static - * @param {vtctldata.GetThrottlerStatusResponse.IMetricHealth=} [properties] Properties to set - * @returns {vtctldata.GetThrottlerStatusResponse.MetricHealth} MetricHealth instance - */ - MetricHealth.create = function create(properties) { - return new MetricHealth(properties); - }; - - /** - * Encodes the specified MetricHealth message. Does not implicitly {@link vtctldata.GetThrottlerStatusResponse.MetricHealth.verify|verify} messages. - * @function encode - * @memberof vtctldata.GetThrottlerStatusResponse.MetricHealth - * @static - * @param {vtctldata.GetThrottlerStatusResponse.IMetricHealth} message MetricHealth message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - MetricHealth.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.last_healthy_at != null && Object.hasOwnProperty.call(message, "last_healthy_at")) - $root.vttime.Time.encode(message.last_healthy_at, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - if (message.seconds_since_last_healthy != null && Object.hasOwnProperty.call(message, "seconds_since_last_healthy")) - writer.uint32(/* id 2, wireType 0 =*/16).int64(message.seconds_since_last_healthy); - return writer; - }; - - /** - * Encodes the specified MetricHealth message, length delimited. Does not implicitly {@link vtctldata.GetThrottlerStatusResponse.MetricHealth.verify|verify} messages. - * @function encodeDelimited - * @memberof vtctldata.GetThrottlerStatusResponse.MetricHealth - * @static - * @param {vtctldata.GetThrottlerStatusResponse.IMetricHealth} message MetricHealth message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - MetricHealth.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a MetricHealth message from the specified reader or buffer. - * @function decode - * @memberof vtctldata.GetThrottlerStatusResponse.MetricHealth - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {vtctldata.GetThrottlerStatusResponse.MetricHealth} MetricHealth - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - MetricHealth.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.GetThrottlerStatusResponse.MetricHealth(); - while (reader.pos < end) { - let tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.last_healthy_at = $root.vttime.Time.decode(reader, reader.uint32()); - break; - } - case 2: { - message.seconds_since_last_healthy = reader.int64(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a MetricHealth message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof vtctldata.GetThrottlerStatusResponse.MetricHealth - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {vtctldata.GetThrottlerStatusResponse.MetricHealth} MetricHealth - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - MetricHealth.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a MetricHealth message. - * @function verify - * @memberof vtctldata.GetThrottlerStatusResponse.MetricHealth - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - MetricHealth.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.last_healthy_at != null && message.hasOwnProperty("last_healthy_at")) { - let error = $root.vttime.Time.verify(message.last_healthy_at); - if (error) - return "last_healthy_at." + error; - } - if (message.seconds_since_last_healthy != null && message.hasOwnProperty("seconds_since_last_healthy")) - if (!$util.isInteger(message.seconds_since_last_healthy) && !(message.seconds_since_last_healthy && $util.isInteger(message.seconds_since_last_healthy.low) && $util.isInteger(message.seconds_since_last_healthy.high))) - return "seconds_since_last_healthy: integer|Long expected"; - return null; - }; - - /** - * Creates a MetricHealth message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof vtctldata.GetThrottlerStatusResponse.MetricHealth - * @static - * @param {Object.} object Plain object - * @returns {vtctldata.GetThrottlerStatusResponse.MetricHealth} MetricHealth - */ - MetricHealth.fromObject = function fromObject(object) { - if (object instanceof $root.vtctldata.GetThrottlerStatusResponse.MetricHealth) - return object; - let message = new $root.vtctldata.GetThrottlerStatusResponse.MetricHealth(); - if (object.last_healthy_at != null) { - if (typeof object.last_healthy_at !== "object") - throw TypeError(".vtctldata.GetThrottlerStatusResponse.MetricHealth.last_healthy_at: object expected"); - message.last_healthy_at = $root.vttime.Time.fromObject(object.last_healthy_at); - } - if (object.seconds_since_last_healthy != null) - if ($util.Long) - (message.seconds_since_last_healthy = $util.Long.fromValue(object.seconds_since_last_healthy)).unsigned = false; - else if (typeof object.seconds_since_last_healthy === "string") - message.seconds_since_last_healthy = parseInt(object.seconds_since_last_healthy, 10); - else if (typeof object.seconds_since_last_healthy === "number") - message.seconds_since_last_healthy = object.seconds_since_last_healthy; - else if (typeof object.seconds_since_last_healthy === "object") - message.seconds_since_last_healthy = new $util.LongBits(object.seconds_since_last_healthy.low >>> 0, object.seconds_since_last_healthy.high >>> 0).toNumber(); - return message; - }; - - /** - * Creates a plain object from a MetricHealth message. Also converts values to other types if specified. - * @function toObject - * @memberof vtctldata.GetThrottlerStatusResponse.MetricHealth - * @static - * @param {vtctldata.GetThrottlerStatusResponse.MetricHealth} message MetricHealth - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - MetricHealth.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (options.defaults) { - object.last_healthy_at = null; - if ($util.Long) { - let long = new $util.Long(0, 0, false); - object.seconds_since_last_healthy = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.seconds_since_last_healthy = options.longs === String ? "0" : 0; - } - if (message.last_healthy_at != null && message.hasOwnProperty("last_healthy_at")) - object.last_healthy_at = $root.vttime.Time.toObject(message.last_healthy_at, options); - if (message.seconds_since_last_healthy != null && message.hasOwnProperty("seconds_since_last_healthy")) - if (typeof message.seconds_since_last_healthy === "number") - object.seconds_since_last_healthy = options.longs === String ? String(message.seconds_since_last_healthy) : message.seconds_since_last_healthy; - else - object.seconds_since_last_healthy = options.longs === String ? $util.Long.prototype.toString.call(message.seconds_since_last_healthy) : options.longs === Number ? new $util.LongBits(message.seconds_since_last_healthy.low >>> 0, message.seconds_since_last_healthy.high >>> 0).toNumber() : message.seconds_since_last_healthy; - return object; - }; - - /** - * Converts this MetricHealth to JSON. - * @function toJSON - * @memberof vtctldata.GetThrottlerStatusResponse.MetricHealth - * @instance - * @returns {Object.} JSON object - */ - MetricHealth.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for MetricHealth - * @function getTypeUrl - * @memberof vtctldata.GetThrottlerStatusResponse.MetricHealth - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - MetricHealth.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/vtctldata.GetThrottlerStatusResponse.MetricHealth"; - }; - - return MetricHealth; - })(); - - GetThrottlerStatusResponse.RecentApp = (function() { - - /** - * Properties of a RecentApp. - * @memberof vtctldata.GetThrottlerStatusResponse - * @interface IRecentApp - * @property {vttime.ITime|null} [checked_at] RecentApp checked_at - * @property {number|null} [status_code] RecentApp status_code - */ + /** + * Converts this GetTopologyPathRequest to JSON. + * @function toJSON + * @memberof vtctldata.GetTopologyPathRequest + * @instance + * @returns {Object.} JSON object + */ + GetTopologyPathRequest.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; - /** - * Constructs a new RecentApp. - * @memberof vtctldata.GetThrottlerStatusResponse - * @classdesc Represents a RecentApp. - * @implements IRecentApp - * @constructor - * @param {vtctldata.GetThrottlerStatusResponse.IRecentApp=} [properties] Properties to set - */ - function RecentApp(properties) { - if (properties) - for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; + /** + * Gets the default type url for GetTopologyPathRequest + * @function getTypeUrl + * @memberof vtctldata.GetTopologyPathRequest + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + GetTopologyPathRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; } + return typeUrlPrefix + "/vtctldata.GetTopologyPathRequest"; + }; - /** - * RecentApp checked_at. - * @member {vttime.ITime|null|undefined} checked_at - * @memberof vtctldata.GetThrottlerStatusResponse.RecentApp - * @instance - */ - RecentApp.prototype.checked_at = null; - - /** - * RecentApp status_code. - * @member {number} status_code - * @memberof vtctldata.GetThrottlerStatusResponse.RecentApp - * @instance - */ - RecentApp.prototype.status_code = 0; - - /** - * Creates a new RecentApp instance using the specified properties. - * @function create - * @memberof vtctldata.GetThrottlerStatusResponse.RecentApp - * @static - * @param {vtctldata.GetThrottlerStatusResponse.IRecentApp=} [properties] Properties to set - * @returns {vtctldata.GetThrottlerStatusResponse.RecentApp} RecentApp instance - */ - RecentApp.create = function create(properties) { - return new RecentApp(properties); - }; - - /** - * Encodes the specified RecentApp message. Does not implicitly {@link vtctldata.GetThrottlerStatusResponse.RecentApp.verify|verify} messages. - * @function encode - * @memberof vtctldata.GetThrottlerStatusResponse.RecentApp - * @static - * @param {vtctldata.GetThrottlerStatusResponse.IRecentApp} message RecentApp message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - RecentApp.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.checked_at != null && Object.hasOwnProperty.call(message, "checked_at")) - $root.vttime.Time.encode(message.checked_at, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - if (message.status_code != null && Object.hasOwnProperty.call(message, "status_code")) - writer.uint32(/* id 2, wireType 0 =*/16).int32(message.status_code); - return writer; - }; - - /** - * Encodes the specified RecentApp message, length delimited. Does not implicitly {@link vtctldata.GetThrottlerStatusResponse.RecentApp.verify|verify} messages. - * @function encodeDelimited - * @memberof vtctldata.GetThrottlerStatusResponse.RecentApp - * @static - * @param {vtctldata.GetThrottlerStatusResponse.IRecentApp} message RecentApp message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - RecentApp.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a RecentApp message from the specified reader or buffer. - * @function decode - * @memberof vtctldata.GetThrottlerStatusResponse.RecentApp - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {vtctldata.GetThrottlerStatusResponse.RecentApp} RecentApp - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - RecentApp.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.GetThrottlerStatusResponse.RecentApp(); - while (reader.pos < end) { - let tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.checked_at = $root.vttime.Time.decode(reader, reader.uint32()); - break; - } - case 2: { - message.status_code = reader.int32(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a RecentApp message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof vtctldata.GetThrottlerStatusResponse.RecentApp - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {vtctldata.GetThrottlerStatusResponse.RecentApp} RecentApp - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - RecentApp.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a RecentApp message. - * @function verify - * @memberof vtctldata.GetThrottlerStatusResponse.RecentApp - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - RecentApp.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.checked_at != null && message.hasOwnProperty("checked_at")) { - let error = $root.vttime.Time.verify(message.checked_at); - if (error) - return "checked_at." + error; - } - if (message.status_code != null && message.hasOwnProperty("status_code")) - if (!$util.isInteger(message.status_code)) - return "status_code: integer expected"; - return null; - }; - - /** - * Creates a RecentApp message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof vtctldata.GetThrottlerStatusResponse.RecentApp - * @static - * @param {Object.} object Plain object - * @returns {vtctldata.GetThrottlerStatusResponse.RecentApp} RecentApp - */ - RecentApp.fromObject = function fromObject(object) { - if (object instanceof $root.vtctldata.GetThrottlerStatusResponse.RecentApp) - return object; - let message = new $root.vtctldata.GetThrottlerStatusResponse.RecentApp(); - if (object.checked_at != null) { - if (typeof object.checked_at !== "object") - throw TypeError(".vtctldata.GetThrottlerStatusResponse.RecentApp.checked_at: object expected"); - message.checked_at = $root.vttime.Time.fromObject(object.checked_at); - } - if (object.status_code != null) - message.status_code = object.status_code | 0; - return message; - }; - - /** - * Creates a plain object from a RecentApp message. Also converts values to other types if specified. - * @function toObject - * @memberof vtctldata.GetThrottlerStatusResponse.RecentApp - * @static - * @param {vtctldata.GetThrottlerStatusResponse.RecentApp} message RecentApp - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - RecentApp.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (options.defaults) { - object.checked_at = null; - object.status_code = 0; - } - if (message.checked_at != null && message.hasOwnProperty("checked_at")) - object.checked_at = $root.vttime.Time.toObject(message.checked_at, options); - if (message.status_code != null && message.hasOwnProperty("status_code")) - object.status_code = message.status_code; - return object; - }; - - /** - * Converts this RecentApp to JSON. - * @function toJSON - * @memberof vtctldata.GetThrottlerStatusResponse.RecentApp - * @instance - * @returns {Object.} JSON object - */ - RecentApp.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for RecentApp - * @function getTypeUrl - * @memberof vtctldata.GetThrottlerStatusResponse.RecentApp - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - RecentApp.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/vtctldata.GetThrottlerStatusResponse.RecentApp"; - }; - - return RecentApp; - })(); - - return GetThrottlerStatusResponse; + return GetTopologyPathRequest; })(); - vtctldata.GetTopologyPathRequest = (function() { + vtctldata.GetTopologyPathResponse = (function() { /** - * Properties of a GetTopologyPathRequest. + * Properties of a GetTopologyPathResponse. * @memberof vtctldata - * @interface IGetTopologyPathRequest - * @property {string|null} [path] GetTopologyPathRequest path - * @property {number|Long|null} [version] GetTopologyPathRequest version - * @property {boolean|null} [as_json] GetTopologyPathRequest as_json + * @interface IGetTopologyPathResponse + * @property {vtctldata.ITopologyCell|null} [cell] GetTopologyPathResponse cell */ /** - * Constructs a new GetTopologyPathRequest. + * Constructs a new GetTopologyPathResponse. * @memberof vtctldata - * @classdesc Represents a GetTopologyPathRequest. - * @implements IGetTopologyPathRequest + * @classdesc Represents a GetTopologyPathResponse. + * @implements IGetTopologyPathResponse * @constructor - * @param {vtctldata.IGetTopologyPathRequest=} [properties] Properties to set + * @param {vtctldata.IGetTopologyPathResponse=} [properties] Properties to set */ - function GetTopologyPathRequest(properties) { + function GetTopologyPathResponse(properties) { if (properties) for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) @@ -145613,306 +145104,44 @@ export const vtctldata = $root.vtctldata = (() => { } /** - * GetTopologyPathRequest path. - * @member {string} path - * @memberof vtctldata.GetTopologyPathRequest - * @instance - */ - GetTopologyPathRequest.prototype.path = ""; - - /** - * GetTopologyPathRequest version. - * @member {number|Long} version - * @memberof vtctldata.GetTopologyPathRequest - * @instance - */ - GetTopologyPathRequest.prototype.version = $util.Long ? $util.Long.fromBits(0,0,false) : 0; - - /** - * GetTopologyPathRequest as_json. - * @member {boolean} as_json - * @memberof vtctldata.GetTopologyPathRequest + * GetTopologyPathResponse cell. + * @member {vtctldata.ITopologyCell|null|undefined} cell + * @memberof vtctldata.GetTopologyPathResponse * @instance */ - GetTopologyPathRequest.prototype.as_json = false; + GetTopologyPathResponse.prototype.cell = null; /** - * Creates a new GetTopologyPathRequest instance using the specified properties. + * Creates a new GetTopologyPathResponse instance using the specified properties. * @function create - * @memberof vtctldata.GetTopologyPathRequest + * @memberof vtctldata.GetTopologyPathResponse * @static - * @param {vtctldata.IGetTopologyPathRequest=} [properties] Properties to set - * @returns {vtctldata.GetTopologyPathRequest} GetTopologyPathRequest instance + * @param {vtctldata.IGetTopologyPathResponse=} [properties] Properties to set + * @returns {vtctldata.GetTopologyPathResponse} GetTopologyPathResponse instance */ - GetTopologyPathRequest.create = function create(properties) { - return new GetTopologyPathRequest(properties); + GetTopologyPathResponse.create = function create(properties) { + return new GetTopologyPathResponse(properties); }; /** - * Encodes the specified GetTopologyPathRequest message. Does not implicitly {@link vtctldata.GetTopologyPathRequest.verify|verify} messages. + * Encodes the specified GetTopologyPathResponse message. Does not implicitly {@link vtctldata.GetTopologyPathResponse.verify|verify} messages. * @function encode - * @memberof vtctldata.GetTopologyPathRequest + * @memberof vtctldata.GetTopologyPathResponse * @static - * @param {vtctldata.IGetTopologyPathRequest} message GetTopologyPathRequest message or plain object to encode + * @param {vtctldata.IGetTopologyPathResponse} message GetTopologyPathResponse message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - GetTopologyPathRequest.encode = function encode(message, writer) { + GetTopologyPathResponse.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.path != null && Object.hasOwnProperty.call(message, "path")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.path); - if (message.version != null && Object.hasOwnProperty.call(message, "version")) - writer.uint32(/* id 2, wireType 0 =*/16).int64(message.version); - if (message.as_json != null && Object.hasOwnProperty.call(message, "as_json")) - writer.uint32(/* id 3, wireType 0 =*/24).bool(message.as_json); + if (message.cell != null && Object.hasOwnProperty.call(message, "cell")) + $root.vtctldata.TopologyCell.encode(message.cell, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); return writer; }; /** - * Encodes the specified GetTopologyPathRequest message, length delimited. Does not implicitly {@link vtctldata.GetTopologyPathRequest.verify|verify} messages. - * @function encodeDelimited - * @memberof vtctldata.GetTopologyPathRequest - * @static - * @param {vtctldata.IGetTopologyPathRequest} message GetTopologyPathRequest message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetTopologyPathRequest.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a GetTopologyPathRequest message from the specified reader or buffer. - * @function decode - * @memberof vtctldata.GetTopologyPathRequest - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {vtctldata.GetTopologyPathRequest} GetTopologyPathRequest - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetTopologyPathRequest.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.GetTopologyPathRequest(); - while (reader.pos < end) { - let tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.path = reader.string(); - break; - } - case 2: { - message.version = reader.int64(); - break; - } - case 3: { - message.as_json = reader.bool(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a GetTopologyPathRequest message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof vtctldata.GetTopologyPathRequest - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {vtctldata.GetTopologyPathRequest} GetTopologyPathRequest - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetTopologyPathRequest.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a GetTopologyPathRequest message. - * @function verify - * @memberof vtctldata.GetTopologyPathRequest - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - GetTopologyPathRequest.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.path != null && message.hasOwnProperty("path")) - if (!$util.isString(message.path)) - return "path: string expected"; - if (message.version != null && message.hasOwnProperty("version")) - if (!$util.isInteger(message.version) && !(message.version && $util.isInteger(message.version.low) && $util.isInteger(message.version.high))) - return "version: integer|Long expected"; - if (message.as_json != null && message.hasOwnProperty("as_json")) - if (typeof message.as_json !== "boolean") - return "as_json: boolean expected"; - return null; - }; - - /** - * Creates a GetTopologyPathRequest message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof vtctldata.GetTopologyPathRequest - * @static - * @param {Object.} object Plain object - * @returns {vtctldata.GetTopologyPathRequest} GetTopologyPathRequest - */ - GetTopologyPathRequest.fromObject = function fromObject(object) { - if (object instanceof $root.vtctldata.GetTopologyPathRequest) - return object; - let message = new $root.vtctldata.GetTopologyPathRequest(); - if (object.path != null) - message.path = String(object.path); - if (object.version != null) - if ($util.Long) - (message.version = $util.Long.fromValue(object.version)).unsigned = false; - else if (typeof object.version === "string") - message.version = parseInt(object.version, 10); - else if (typeof object.version === "number") - message.version = object.version; - else if (typeof object.version === "object") - message.version = new $util.LongBits(object.version.low >>> 0, object.version.high >>> 0).toNumber(); - if (object.as_json != null) - message.as_json = Boolean(object.as_json); - return message; - }; - - /** - * Creates a plain object from a GetTopologyPathRequest message. Also converts values to other types if specified. - * @function toObject - * @memberof vtctldata.GetTopologyPathRequest - * @static - * @param {vtctldata.GetTopologyPathRequest} message GetTopologyPathRequest - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - GetTopologyPathRequest.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (options.defaults) { - object.path = ""; - if ($util.Long) { - let long = new $util.Long(0, 0, false); - object.version = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.version = options.longs === String ? "0" : 0; - object.as_json = false; - } - if (message.path != null && message.hasOwnProperty("path")) - object.path = message.path; - if (message.version != null && message.hasOwnProperty("version")) - if (typeof message.version === "number") - object.version = options.longs === String ? String(message.version) : message.version; - else - object.version = options.longs === String ? $util.Long.prototype.toString.call(message.version) : options.longs === Number ? new $util.LongBits(message.version.low >>> 0, message.version.high >>> 0).toNumber() : message.version; - if (message.as_json != null && message.hasOwnProperty("as_json")) - object.as_json = message.as_json; - return object; - }; - - /** - * Converts this GetTopologyPathRequest to JSON. - * @function toJSON - * @memberof vtctldata.GetTopologyPathRequest - * @instance - * @returns {Object.} JSON object - */ - GetTopologyPathRequest.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for GetTopologyPathRequest - * @function getTypeUrl - * @memberof vtctldata.GetTopologyPathRequest - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - GetTopologyPathRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/vtctldata.GetTopologyPathRequest"; - }; - - return GetTopologyPathRequest; - })(); - - vtctldata.GetTopologyPathResponse = (function() { - - /** - * Properties of a GetTopologyPathResponse. - * @memberof vtctldata - * @interface IGetTopologyPathResponse - * @property {vtctldata.ITopologyCell|null} [cell] GetTopologyPathResponse cell - */ - - /** - * Constructs a new GetTopologyPathResponse. - * @memberof vtctldata - * @classdesc Represents a GetTopologyPathResponse. - * @implements IGetTopologyPathResponse - * @constructor - * @param {vtctldata.IGetTopologyPathResponse=} [properties] Properties to set - */ - function GetTopologyPathResponse(properties) { - if (properties) - for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * GetTopologyPathResponse cell. - * @member {vtctldata.ITopologyCell|null|undefined} cell - * @memberof vtctldata.GetTopologyPathResponse - * @instance - */ - GetTopologyPathResponse.prototype.cell = null; - - /** - * Creates a new GetTopologyPathResponse instance using the specified properties. - * @function create - * @memberof vtctldata.GetTopologyPathResponse - * @static - * @param {vtctldata.IGetTopologyPathResponse=} [properties] Properties to set - * @returns {vtctldata.GetTopologyPathResponse} GetTopologyPathResponse instance - */ - GetTopologyPathResponse.create = function create(properties) { - return new GetTopologyPathResponse(properties); - }; - - /** - * Encodes the specified GetTopologyPathResponse message. Does not implicitly {@link vtctldata.GetTopologyPathResponse.verify|verify} messages. - * @function encode - * @memberof vtctldata.GetTopologyPathResponse - * @static - * @param {vtctldata.IGetTopologyPathResponse} message GetTopologyPathResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetTopologyPathResponse.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.cell != null && Object.hasOwnProperty.call(message, "cell")) - $root.vtctldata.TopologyCell.encode(message.cell, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified GetTopologyPathResponse message, length delimited. Does not implicitly {@link vtctldata.GetTopologyPathResponse.verify|verify} messages. + * Encodes the specified GetTopologyPathResponse message, length delimited. Does not implicitly {@link vtctldata.GetTopologyPathResponse.verify|verify} messages. * @function encodeDelimited * @memberof vtctldata.GetTopologyPathResponse * @static @@ -179487,90 +178716,1650 @@ export const vtctldata = $root.vtctldata = (() => { return message; }; - /** - * Creates a plain object from a ShardStreamState message. Also converts values to other types if specified. - * @function toObject - * @memberof vtctldata.WorkflowStatusResponse.ShardStreamState - * @static - * @param {vtctldata.WorkflowStatusResponse.ShardStreamState} message ShardStreamState - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - ShardStreamState.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (options.defaults) { - object.id = 0; - object.tablet = null; - object.source_shard = ""; - object.position = ""; - object.status = ""; - object.info = ""; + /** + * Creates a plain object from a ShardStreamState message. Also converts values to other types if specified. + * @function toObject + * @memberof vtctldata.WorkflowStatusResponse.ShardStreamState + * @static + * @param {vtctldata.WorkflowStatusResponse.ShardStreamState} message ShardStreamState + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + ShardStreamState.toObject = function toObject(message, options) { + if (!options) + options = {}; + let object = {}; + if (options.defaults) { + object.id = 0; + object.tablet = null; + object.source_shard = ""; + object.position = ""; + object.status = ""; + object.info = ""; + } + if (message.id != null && message.hasOwnProperty("id")) + object.id = message.id; + if (message.tablet != null && message.hasOwnProperty("tablet")) + object.tablet = $root.topodata.TabletAlias.toObject(message.tablet, options); + if (message.source_shard != null && message.hasOwnProperty("source_shard")) + object.source_shard = message.source_shard; + if (message.position != null && message.hasOwnProperty("position")) + object.position = message.position; + if (message.status != null && message.hasOwnProperty("status")) + object.status = message.status; + if (message.info != null && message.hasOwnProperty("info")) + object.info = message.info; + return object; + }; + + /** + * Converts this ShardStreamState to JSON. + * @function toJSON + * @memberof vtctldata.WorkflowStatusResponse.ShardStreamState + * @instance + * @returns {Object.} JSON object + */ + ShardStreamState.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for ShardStreamState + * @function getTypeUrl + * @memberof vtctldata.WorkflowStatusResponse.ShardStreamState + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + ShardStreamState.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/vtctldata.WorkflowStatusResponse.ShardStreamState"; + }; + + return ShardStreamState; + })(); + + WorkflowStatusResponse.ShardStreams = (function() { + + /** + * Properties of a ShardStreams. + * @memberof vtctldata.WorkflowStatusResponse + * @interface IShardStreams + * @property {Array.|null} [streams] ShardStreams streams + */ + + /** + * Constructs a new ShardStreams. + * @memberof vtctldata.WorkflowStatusResponse + * @classdesc Represents a ShardStreams. + * @implements IShardStreams + * @constructor + * @param {vtctldata.WorkflowStatusResponse.IShardStreams=} [properties] Properties to set + */ + function ShardStreams(properties) { + this.streams = []; + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * ShardStreams streams. + * @member {Array.} streams + * @memberof vtctldata.WorkflowStatusResponse.ShardStreams + * @instance + */ + ShardStreams.prototype.streams = $util.emptyArray; + + /** + * Creates a new ShardStreams instance using the specified properties. + * @function create + * @memberof vtctldata.WorkflowStatusResponse.ShardStreams + * @static + * @param {vtctldata.WorkflowStatusResponse.IShardStreams=} [properties] Properties to set + * @returns {vtctldata.WorkflowStatusResponse.ShardStreams} ShardStreams instance + */ + ShardStreams.create = function create(properties) { + return new ShardStreams(properties); + }; + + /** + * Encodes the specified ShardStreams message. Does not implicitly {@link vtctldata.WorkflowStatusResponse.ShardStreams.verify|verify} messages. + * @function encode + * @memberof vtctldata.WorkflowStatusResponse.ShardStreams + * @static + * @param {vtctldata.WorkflowStatusResponse.IShardStreams} message ShardStreams message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ShardStreams.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.streams != null && message.streams.length) + for (let i = 0; i < message.streams.length; ++i) + $root.vtctldata.WorkflowStatusResponse.ShardStreamState.encode(message.streams[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified ShardStreams message, length delimited. Does not implicitly {@link vtctldata.WorkflowStatusResponse.ShardStreams.verify|verify} messages. + * @function encodeDelimited + * @memberof vtctldata.WorkflowStatusResponse.ShardStreams + * @static + * @param {vtctldata.WorkflowStatusResponse.IShardStreams} message ShardStreams message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ShardStreams.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a ShardStreams message from the specified reader or buffer. + * @function decode + * @memberof vtctldata.WorkflowStatusResponse.ShardStreams + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {vtctldata.WorkflowStatusResponse.ShardStreams} ShardStreams + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ShardStreams.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.WorkflowStatusResponse.ShardStreams(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 2: { + if (!(message.streams && message.streams.length)) + message.streams = []; + message.streams.push($root.vtctldata.WorkflowStatusResponse.ShardStreamState.decode(reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a ShardStreams message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof vtctldata.WorkflowStatusResponse.ShardStreams + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {vtctldata.WorkflowStatusResponse.ShardStreams} ShardStreams + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ShardStreams.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a ShardStreams message. + * @function verify + * @memberof vtctldata.WorkflowStatusResponse.ShardStreams + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + ShardStreams.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.streams != null && message.hasOwnProperty("streams")) { + if (!Array.isArray(message.streams)) + return "streams: array expected"; + for (let i = 0; i < message.streams.length; ++i) { + let error = $root.vtctldata.WorkflowStatusResponse.ShardStreamState.verify(message.streams[i]); + if (error) + return "streams." + error; + } + } + return null; + }; + + /** + * Creates a ShardStreams message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof vtctldata.WorkflowStatusResponse.ShardStreams + * @static + * @param {Object.} object Plain object + * @returns {vtctldata.WorkflowStatusResponse.ShardStreams} ShardStreams + */ + ShardStreams.fromObject = function fromObject(object) { + if (object instanceof $root.vtctldata.WorkflowStatusResponse.ShardStreams) + return object; + let message = new $root.vtctldata.WorkflowStatusResponse.ShardStreams(); + if (object.streams) { + if (!Array.isArray(object.streams)) + throw TypeError(".vtctldata.WorkflowStatusResponse.ShardStreams.streams: array expected"); + message.streams = []; + for (let i = 0; i < object.streams.length; ++i) { + if (typeof object.streams[i] !== "object") + throw TypeError(".vtctldata.WorkflowStatusResponse.ShardStreams.streams: object expected"); + message.streams[i] = $root.vtctldata.WorkflowStatusResponse.ShardStreamState.fromObject(object.streams[i]); + } + } + return message; + }; + + /** + * Creates a plain object from a ShardStreams message. Also converts values to other types if specified. + * @function toObject + * @memberof vtctldata.WorkflowStatusResponse.ShardStreams + * @static + * @param {vtctldata.WorkflowStatusResponse.ShardStreams} message ShardStreams + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + ShardStreams.toObject = function toObject(message, options) { + if (!options) + options = {}; + let object = {}; + if (options.arrays || options.defaults) + object.streams = []; + if (message.streams && message.streams.length) { + object.streams = []; + for (let j = 0; j < message.streams.length; ++j) + object.streams[j] = $root.vtctldata.WorkflowStatusResponse.ShardStreamState.toObject(message.streams[j], options); + } + return object; + }; + + /** + * Converts this ShardStreams to JSON. + * @function toJSON + * @memberof vtctldata.WorkflowStatusResponse.ShardStreams + * @instance + * @returns {Object.} JSON object + */ + ShardStreams.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for ShardStreams + * @function getTypeUrl + * @memberof vtctldata.WorkflowStatusResponse.ShardStreams + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + ShardStreams.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/vtctldata.WorkflowStatusResponse.ShardStreams"; + }; + + return ShardStreams; + })(); + + return WorkflowStatusResponse; + })(); + + vtctldata.WorkflowSwitchTrafficRequest = (function() { + + /** + * Properties of a WorkflowSwitchTrafficRequest. + * @memberof vtctldata + * @interface IWorkflowSwitchTrafficRequest + * @property {string|null} [keyspace] WorkflowSwitchTrafficRequest keyspace + * @property {string|null} [workflow] WorkflowSwitchTrafficRequest workflow + * @property {Array.|null} [cells] WorkflowSwitchTrafficRequest cells + * @property {Array.|null} [tablet_types] WorkflowSwitchTrafficRequest tablet_types + * @property {vttime.IDuration|null} [max_replication_lag_allowed] WorkflowSwitchTrafficRequest max_replication_lag_allowed + * @property {boolean|null} [enable_reverse_replication] WorkflowSwitchTrafficRequest enable_reverse_replication + * @property {number|null} [direction] WorkflowSwitchTrafficRequest direction + * @property {vttime.IDuration|null} [timeout] WorkflowSwitchTrafficRequest timeout + * @property {boolean|null} [dry_run] WorkflowSwitchTrafficRequest dry_run + * @property {boolean|null} [initialize_target_sequences] WorkflowSwitchTrafficRequest initialize_target_sequences + * @property {Array.|null} [shards] WorkflowSwitchTrafficRequest shards + */ + + /** + * Constructs a new WorkflowSwitchTrafficRequest. + * @memberof vtctldata + * @classdesc Represents a WorkflowSwitchTrafficRequest. + * @implements IWorkflowSwitchTrafficRequest + * @constructor + * @param {vtctldata.IWorkflowSwitchTrafficRequest=} [properties] Properties to set + */ + function WorkflowSwitchTrafficRequest(properties) { + this.cells = []; + this.tablet_types = []; + this.shards = []; + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * WorkflowSwitchTrafficRequest keyspace. + * @member {string} keyspace + * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @instance + */ + WorkflowSwitchTrafficRequest.prototype.keyspace = ""; + + /** + * WorkflowSwitchTrafficRequest workflow. + * @member {string} workflow + * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @instance + */ + WorkflowSwitchTrafficRequest.prototype.workflow = ""; + + /** + * WorkflowSwitchTrafficRequest cells. + * @member {Array.} cells + * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @instance + */ + WorkflowSwitchTrafficRequest.prototype.cells = $util.emptyArray; + + /** + * WorkflowSwitchTrafficRequest tablet_types. + * @member {Array.} tablet_types + * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @instance + */ + WorkflowSwitchTrafficRequest.prototype.tablet_types = $util.emptyArray; + + /** + * WorkflowSwitchTrafficRequest max_replication_lag_allowed. + * @member {vttime.IDuration|null|undefined} max_replication_lag_allowed + * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @instance + */ + WorkflowSwitchTrafficRequest.prototype.max_replication_lag_allowed = null; + + /** + * WorkflowSwitchTrafficRequest enable_reverse_replication. + * @member {boolean} enable_reverse_replication + * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @instance + */ + WorkflowSwitchTrafficRequest.prototype.enable_reverse_replication = false; + + /** + * WorkflowSwitchTrafficRequest direction. + * @member {number} direction + * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @instance + */ + WorkflowSwitchTrafficRequest.prototype.direction = 0; + + /** + * WorkflowSwitchTrafficRequest timeout. + * @member {vttime.IDuration|null|undefined} timeout + * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @instance + */ + WorkflowSwitchTrafficRequest.prototype.timeout = null; + + /** + * WorkflowSwitchTrafficRequest dry_run. + * @member {boolean} dry_run + * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @instance + */ + WorkflowSwitchTrafficRequest.prototype.dry_run = false; + + /** + * WorkflowSwitchTrafficRequest initialize_target_sequences. + * @member {boolean} initialize_target_sequences + * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @instance + */ + WorkflowSwitchTrafficRequest.prototype.initialize_target_sequences = false; + + /** + * WorkflowSwitchTrafficRequest shards. + * @member {Array.} shards + * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @instance + */ + WorkflowSwitchTrafficRequest.prototype.shards = $util.emptyArray; + + /** + * Creates a new WorkflowSwitchTrafficRequest instance using the specified properties. + * @function create + * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @static + * @param {vtctldata.IWorkflowSwitchTrafficRequest=} [properties] Properties to set + * @returns {vtctldata.WorkflowSwitchTrafficRequest} WorkflowSwitchTrafficRequest instance + */ + WorkflowSwitchTrafficRequest.create = function create(properties) { + return new WorkflowSwitchTrafficRequest(properties); + }; + + /** + * Encodes the specified WorkflowSwitchTrafficRequest message. Does not implicitly {@link vtctldata.WorkflowSwitchTrafficRequest.verify|verify} messages. + * @function encode + * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @static + * @param {vtctldata.IWorkflowSwitchTrafficRequest} message WorkflowSwitchTrafficRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + WorkflowSwitchTrafficRequest.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.keyspace != null && Object.hasOwnProperty.call(message, "keyspace")) + writer.uint32(/* id 1, wireType 2 =*/10).string(message.keyspace); + if (message.workflow != null && Object.hasOwnProperty.call(message, "workflow")) + writer.uint32(/* id 2, wireType 2 =*/18).string(message.workflow); + if (message.cells != null && message.cells.length) + for (let i = 0; i < message.cells.length; ++i) + writer.uint32(/* id 3, wireType 2 =*/26).string(message.cells[i]); + if (message.tablet_types != null && message.tablet_types.length) { + writer.uint32(/* id 4, wireType 2 =*/34).fork(); + for (let i = 0; i < message.tablet_types.length; ++i) + writer.int32(message.tablet_types[i]); + writer.ldelim(); + } + if (message.max_replication_lag_allowed != null && Object.hasOwnProperty.call(message, "max_replication_lag_allowed")) + $root.vttime.Duration.encode(message.max_replication_lag_allowed, writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim(); + if (message.enable_reverse_replication != null && Object.hasOwnProperty.call(message, "enable_reverse_replication")) + writer.uint32(/* id 6, wireType 0 =*/48).bool(message.enable_reverse_replication); + if (message.direction != null && Object.hasOwnProperty.call(message, "direction")) + writer.uint32(/* id 7, wireType 0 =*/56).int32(message.direction); + if (message.timeout != null && Object.hasOwnProperty.call(message, "timeout")) + $root.vttime.Duration.encode(message.timeout, writer.uint32(/* id 8, wireType 2 =*/66).fork()).ldelim(); + if (message.dry_run != null && Object.hasOwnProperty.call(message, "dry_run")) + writer.uint32(/* id 9, wireType 0 =*/72).bool(message.dry_run); + if (message.initialize_target_sequences != null && Object.hasOwnProperty.call(message, "initialize_target_sequences")) + writer.uint32(/* id 10, wireType 0 =*/80).bool(message.initialize_target_sequences); + if (message.shards != null && message.shards.length) + for (let i = 0; i < message.shards.length; ++i) + writer.uint32(/* id 11, wireType 2 =*/90).string(message.shards[i]); + return writer; + }; + + /** + * Encodes the specified WorkflowSwitchTrafficRequest message, length delimited. Does not implicitly {@link vtctldata.WorkflowSwitchTrafficRequest.verify|verify} messages. + * @function encodeDelimited + * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @static + * @param {vtctldata.IWorkflowSwitchTrafficRequest} message WorkflowSwitchTrafficRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + WorkflowSwitchTrafficRequest.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a WorkflowSwitchTrafficRequest message from the specified reader or buffer. + * @function decode + * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {vtctldata.WorkflowSwitchTrafficRequest} WorkflowSwitchTrafficRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + WorkflowSwitchTrafficRequest.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.WorkflowSwitchTrafficRequest(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.keyspace = reader.string(); + break; + } + case 2: { + message.workflow = reader.string(); + break; + } + case 3: { + if (!(message.cells && message.cells.length)) + message.cells = []; + message.cells.push(reader.string()); + break; + } + case 4: { + if (!(message.tablet_types && message.tablet_types.length)) + message.tablet_types = []; + if ((tag & 7) === 2) { + let end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) + message.tablet_types.push(reader.int32()); + } else + message.tablet_types.push(reader.int32()); + break; + } + case 5: { + message.max_replication_lag_allowed = $root.vttime.Duration.decode(reader, reader.uint32()); + break; + } + case 6: { + message.enable_reverse_replication = reader.bool(); + break; + } + case 7: { + message.direction = reader.int32(); + break; + } + case 8: { + message.timeout = $root.vttime.Duration.decode(reader, reader.uint32()); + break; + } + case 9: { + message.dry_run = reader.bool(); + break; + } + case 10: { + message.initialize_target_sequences = reader.bool(); + break; + } + case 11: { + if (!(message.shards && message.shards.length)) + message.shards = []; + message.shards.push(reader.string()); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a WorkflowSwitchTrafficRequest message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {vtctldata.WorkflowSwitchTrafficRequest} WorkflowSwitchTrafficRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + WorkflowSwitchTrafficRequest.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a WorkflowSwitchTrafficRequest message. + * @function verify + * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + WorkflowSwitchTrafficRequest.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.keyspace != null && message.hasOwnProperty("keyspace")) + if (!$util.isString(message.keyspace)) + return "keyspace: string expected"; + if (message.workflow != null && message.hasOwnProperty("workflow")) + if (!$util.isString(message.workflow)) + return "workflow: string expected"; + if (message.cells != null && message.hasOwnProperty("cells")) { + if (!Array.isArray(message.cells)) + return "cells: array expected"; + for (let i = 0; i < message.cells.length; ++i) + if (!$util.isString(message.cells[i])) + return "cells: string[] expected"; + } + if (message.tablet_types != null && message.hasOwnProperty("tablet_types")) { + if (!Array.isArray(message.tablet_types)) + return "tablet_types: array expected"; + for (let i = 0; i < message.tablet_types.length; ++i) + switch (message.tablet_types[i]) { + default: + return "tablet_types: enum value[] expected"; + case 0: + case 1: + case 1: + case 2: + case 3: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + break; + } + } + if (message.max_replication_lag_allowed != null && message.hasOwnProperty("max_replication_lag_allowed")) { + let error = $root.vttime.Duration.verify(message.max_replication_lag_allowed); + if (error) + return "max_replication_lag_allowed." + error; + } + if (message.enable_reverse_replication != null && message.hasOwnProperty("enable_reverse_replication")) + if (typeof message.enable_reverse_replication !== "boolean") + return "enable_reverse_replication: boolean expected"; + if (message.direction != null && message.hasOwnProperty("direction")) + if (!$util.isInteger(message.direction)) + return "direction: integer expected"; + if (message.timeout != null && message.hasOwnProperty("timeout")) { + let error = $root.vttime.Duration.verify(message.timeout); + if (error) + return "timeout." + error; + } + if (message.dry_run != null && message.hasOwnProperty("dry_run")) + if (typeof message.dry_run !== "boolean") + return "dry_run: boolean expected"; + if (message.initialize_target_sequences != null && message.hasOwnProperty("initialize_target_sequences")) + if (typeof message.initialize_target_sequences !== "boolean") + return "initialize_target_sequences: boolean expected"; + if (message.shards != null && message.hasOwnProperty("shards")) { + if (!Array.isArray(message.shards)) + return "shards: array expected"; + for (let i = 0; i < message.shards.length; ++i) + if (!$util.isString(message.shards[i])) + return "shards: string[] expected"; + } + return null; + }; + + /** + * Creates a WorkflowSwitchTrafficRequest message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @static + * @param {Object.} object Plain object + * @returns {vtctldata.WorkflowSwitchTrafficRequest} WorkflowSwitchTrafficRequest + */ + WorkflowSwitchTrafficRequest.fromObject = function fromObject(object) { + if (object instanceof $root.vtctldata.WorkflowSwitchTrafficRequest) + return object; + let message = new $root.vtctldata.WorkflowSwitchTrafficRequest(); + if (object.keyspace != null) + message.keyspace = String(object.keyspace); + if (object.workflow != null) + message.workflow = String(object.workflow); + if (object.cells) { + if (!Array.isArray(object.cells)) + throw TypeError(".vtctldata.WorkflowSwitchTrafficRequest.cells: array expected"); + message.cells = []; + for (let i = 0; i < object.cells.length; ++i) + message.cells[i] = String(object.cells[i]); + } + if (object.tablet_types) { + if (!Array.isArray(object.tablet_types)) + throw TypeError(".vtctldata.WorkflowSwitchTrafficRequest.tablet_types: array expected"); + message.tablet_types = []; + for (let i = 0; i < object.tablet_types.length; ++i) + switch (object.tablet_types[i]) { + default: + if (typeof object.tablet_types[i] === "number") { + message.tablet_types[i] = object.tablet_types[i]; + break; + } + case "UNKNOWN": + case 0: + message.tablet_types[i] = 0; + break; + case "PRIMARY": + case 1: + message.tablet_types[i] = 1; + break; + case "MASTER": + case 1: + message.tablet_types[i] = 1; + break; + case "REPLICA": + case 2: + message.tablet_types[i] = 2; + break; + case "RDONLY": + case 3: + message.tablet_types[i] = 3; + break; + case "BATCH": + case 3: + message.tablet_types[i] = 3; + break; + case "SPARE": + case 4: + message.tablet_types[i] = 4; + break; + case "EXPERIMENTAL": + case 5: + message.tablet_types[i] = 5; + break; + case "BACKUP": + case 6: + message.tablet_types[i] = 6; + break; + case "RESTORE": + case 7: + message.tablet_types[i] = 7; + break; + case "DRAINED": + case 8: + message.tablet_types[i] = 8; + break; + } + } + if (object.max_replication_lag_allowed != null) { + if (typeof object.max_replication_lag_allowed !== "object") + throw TypeError(".vtctldata.WorkflowSwitchTrafficRequest.max_replication_lag_allowed: object expected"); + message.max_replication_lag_allowed = $root.vttime.Duration.fromObject(object.max_replication_lag_allowed); + } + if (object.enable_reverse_replication != null) + message.enable_reverse_replication = Boolean(object.enable_reverse_replication); + if (object.direction != null) + message.direction = object.direction | 0; + if (object.timeout != null) { + if (typeof object.timeout !== "object") + throw TypeError(".vtctldata.WorkflowSwitchTrafficRequest.timeout: object expected"); + message.timeout = $root.vttime.Duration.fromObject(object.timeout); + } + if (object.dry_run != null) + message.dry_run = Boolean(object.dry_run); + if (object.initialize_target_sequences != null) + message.initialize_target_sequences = Boolean(object.initialize_target_sequences); + if (object.shards) { + if (!Array.isArray(object.shards)) + throw TypeError(".vtctldata.WorkflowSwitchTrafficRequest.shards: array expected"); + message.shards = []; + for (let i = 0; i < object.shards.length; ++i) + message.shards[i] = String(object.shards[i]); + } + return message; + }; + + /** + * Creates a plain object from a WorkflowSwitchTrafficRequest message. Also converts values to other types if specified. + * @function toObject + * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @static + * @param {vtctldata.WorkflowSwitchTrafficRequest} message WorkflowSwitchTrafficRequest + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + WorkflowSwitchTrafficRequest.toObject = function toObject(message, options) { + if (!options) + options = {}; + let object = {}; + if (options.arrays || options.defaults) { + object.cells = []; + object.tablet_types = []; + object.shards = []; + } + if (options.defaults) { + object.keyspace = ""; + object.workflow = ""; + object.max_replication_lag_allowed = null; + object.enable_reverse_replication = false; + object.direction = 0; + object.timeout = null; + object.dry_run = false; + object.initialize_target_sequences = false; + } + if (message.keyspace != null && message.hasOwnProperty("keyspace")) + object.keyspace = message.keyspace; + if (message.workflow != null && message.hasOwnProperty("workflow")) + object.workflow = message.workflow; + if (message.cells && message.cells.length) { + object.cells = []; + for (let j = 0; j < message.cells.length; ++j) + object.cells[j] = message.cells[j]; + } + if (message.tablet_types && message.tablet_types.length) { + object.tablet_types = []; + for (let j = 0; j < message.tablet_types.length; ++j) + object.tablet_types[j] = options.enums === String ? $root.topodata.TabletType[message.tablet_types[j]] === undefined ? message.tablet_types[j] : $root.topodata.TabletType[message.tablet_types[j]] : message.tablet_types[j]; + } + if (message.max_replication_lag_allowed != null && message.hasOwnProperty("max_replication_lag_allowed")) + object.max_replication_lag_allowed = $root.vttime.Duration.toObject(message.max_replication_lag_allowed, options); + if (message.enable_reverse_replication != null && message.hasOwnProperty("enable_reverse_replication")) + object.enable_reverse_replication = message.enable_reverse_replication; + if (message.direction != null && message.hasOwnProperty("direction")) + object.direction = message.direction; + if (message.timeout != null && message.hasOwnProperty("timeout")) + object.timeout = $root.vttime.Duration.toObject(message.timeout, options); + if (message.dry_run != null && message.hasOwnProperty("dry_run")) + object.dry_run = message.dry_run; + if (message.initialize_target_sequences != null && message.hasOwnProperty("initialize_target_sequences")) + object.initialize_target_sequences = message.initialize_target_sequences; + if (message.shards && message.shards.length) { + object.shards = []; + for (let j = 0; j < message.shards.length; ++j) + object.shards[j] = message.shards[j]; + } + return object; + }; + + /** + * Converts this WorkflowSwitchTrafficRequest to JSON. + * @function toJSON + * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @instance + * @returns {Object.} JSON object + */ + WorkflowSwitchTrafficRequest.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for WorkflowSwitchTrafficRequest + * @function getTypeUrl + * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + WorkflowSwitchTrafficRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/vtctldata.WorkflowSwitchTrafficRequest"; + }; + + return WorkflowSwitchTrafficRequest; + })(); + + vtctldata.WorkflowSwitchTrafficResponse = (function() { + + /** + * Properties of a WorkflowSwitchTrafficResponse. + * @memberof vtctldata + * @interface IWorkflowSwitchTrafficResponse + * @property {string|null} [summary] WorkflowSwitchTrafficResponse summary + * @property {string|null} [start_state] WorkflowSwitchTrafficResponse start_state + * @property {string|null} [current_state] WorkflowSwitchTrafficResponse current_state + * @property {Array.|null} [dry_run_results] WorkflowSwitchTrafficResponse dry_run_results + */ + + /** + * Constructs a new WorkflowSwitchTrafficResponse. + * @memberof vtctldata + * @classdesc Represents a WorkflowSwitchTrafficResponse. + * @implements IWorkflowSwitchTrafficResponse + * @constructor + * @param {vtctldata.IWorkflowSwitchTrafficResponse=} [properties] Properties to set + */ + function WorkflowSwitchTrafficResponse(properties) { + this.dry_run_results = []; + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * WorkflowSwitchTrafficResponse summary. + * @member {string} summary + * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @instance + */ + WorkflowSwitchTrafficResponse.prototype.summary = ""; + + /** + * WorkflowSwitchTrafficResponse start_state. + * @member {string} start_state + * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @instance + */ + WorkflowSwitchTrafficResponse.prototype.start_state = ""; + + /** + * WorkflowSwitchTrafficResponse current_state. + * @member {string} current_state + * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @instance + */ + WorkflowSwitchTrafficResponse.prototype.current_state = ""; + + /** + * WorkflowSwitchTrafficResponse dry_run_results. + * @member {Array.} dry_run_results + * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @instance + */ + WorkflowSwitchTrafficResponse.prototype.dry_run_results = $util.emptyArray; + + /** + * Creates a new WorkflowSwitchTrafficResponse instance using the specified properties. + * @function create + * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @static + * @param {vtctldata.IWorkflowSwitchTrafficResponse=} [properties] Properties to set + * @returns {vtctldata.WorkflowSwitchTrafficResponse} WorkflowSwitchTrafficResponse instance + */ + WorkflowSwitchTrafficResponse.create = function create(properties) { + return new WorkflowSwitchTrafficResponse(properties); + }; + + /** + * Encodes the specified WorkflowSwitchTrafficResponse message. Does not implicitly {@link vtctldata.WorkflowSwitchTrafficResponse.verify|verify} messages. + * @function encode + * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @static + * @param {vtctldata.IWorkflowSwitchTrafficResponse} message WorkflowSwitchTrafficResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + WorkflowSwitchTrafficResponse.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.summary != null && Object.hasOwnProperty.call(message, "summary")) + writer.uint32(/* id 1, wireType 2 =*/10).string(message.summary); + if (message.start_state != null && Object.hasOwnProperty.call(message, "start_state")) + writer.uint32(/* id 2, wireType 2 =*/18).string(message.start_state); + if (message.current_state != null && Object.hasOwnProperty.call(message, "current_state")) + writer.uint32(/* id 3, wireType 2 =*/26).string(message.current_state); + if (message.dry_run_results != null && message.dry_run_results.length) + for (let i = 0; i < message.dry_run_results.length; ++i) + writer.uint32(/* id 4, wireType 2 =*/34).string(message.dry_run_results[i]); + return writer; + }; + + /** + * Encodes the specified WorkflowSwitchTrafficResponse message, length delimited. Does not implicitly {@link vtctldata.WorkflowSwitchTrafficResponse.verify|verify} messages. + * @function encodeDelimited + * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @static + * @param {vtctldata.IWorkflowSwitchTrafficResponse} message WorkflowSwitchTrafficResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + WorkflowSwitchTrafficResponse.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a WorkflowSwitchTrafficResponse message from the specified reader or buffer. + * @function decode + * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {vtctldata.WorkflowSwitchTrafficResponse} WorkflowSwitchTrafficResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + WorkflowSwitchTrafficResponse.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.WorkflowSwitchTrafficResponse(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.summary = reader.string(); + break; + } + case 2: { + message.start_state = reader.string(); + break; + } + case 3: { + message.current_state = reader.string(); + break; + } + case 4: { + if (!(message.dry_run_results && message.dry_run_results.length)) + message.dry_run_results = []; + message.dry_run_results.push(reader.string()); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a WorkflowSwitchTrafficResponse message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {vtctldata.WorkflowSwitchTrafficResponse} WorkflowSwitchTrafficResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + WorkflowSwitchTrafficResponse.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a WorkflowSwitchTrafficResponse message. + * @function verify + * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + WorkflowSwitchTrafficResponse.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.summary != null && message.hasOwnProperty("summary")) + if (!$util.isString(message.summary)) + return "summary: string expected"; + if (message.start_state != null && message.hasOwnProperty("start_state")) + if (!$util.isString(message.start_state)) + return "start_state: string expected"; + if (message.current_state != null && message.hasOwnProperty("current_state")) + if (!$util.isString(message.current_state)) + return "current_state: string expected"; + if (message.dry_run_results != null && message.hasOwnProperty("dry_run_results")) { + if (!Array.isArray(message.dry_run_results)) + return "dry_run_results: array expected"; + for (let i = 0; i < message.dry_run_results.length; ++i) + if (!$util.isString(message.dry_run_results[i])) + return "dry_run_results: string[] expected"; + } + return null; + }; + + /** + * Creates a WorkflowSwitchTrafficResponse message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @static + * @param {Object.} object Plain object + * @returns {vtctldata.WorkflowSwitchTrafficResponse} WorkflowSwitchTrafficResponse + */ + WorkflowSwitchTrafficResponse.fromObject = function fromObject(object) { + if (object instanceof $root.vtctldata.WorkflowSwitchTrafficResponse) + return object; + let message = new $root.vtctldata.WorkflowSwitchTrafficResponse(); + if (object.summary != null) + message.summary = String(object.summary); + if (object.start_state != null) + message.start_state = String(object.start_state); + if (object.current_state != null) + message.current_state = String(object.current_state); + if (object.dry_run_results) { + if (!Array.isArray(object.dry_run_results)) + throw TypeError(".vtctldata.WorkflowSwitchTrafficResponse.dry_run_results: array expected"); + message.dry_run_results = []; + for (let i = 0; i < object.dry_run_results.length; ++i) + message.dry_run_results[i] = String(object.dry_run_results[i]); + } + return message; + }; + + /** + * Creates a plain object from a WorkflowSwitchTrafficResponse message. Also converts values to other types if specified. + * @function toObject + * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @static + * @param {vtctldata.WorkflowSwitchTrafficResponse} message WorkflowSwitchTrafficResponse + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + WorkflowSwitchTrafficResponse.toObject = function toObject(message, options) { + if (!options) + options = {}; + let object = {}; + if (options.arrays || options.defaults) + object.dry_run_results = []; + if (options.defaults) { + object.summary = ""; + object.start_state = ""; + object.current_state = ""; + } + if (message.summary != null && message.hasOwnProperty("summary")) + object.summary = message.summary; + if (message.start_state != null && message.hasOwnProperty("start_state")) + object.start_state = message.start_state; + if (message.current_state != null && message.hasOwnProperty("current_state")) + object.current_state = message.current_state; + if (message.dry_run_results && message.dry_run_results.length) { + object.dry_run_results = []; + for (let j = 0; j < message.dry_run_results.length; ++j) + object.dry_run_results[j] = message.dry_run_results[j]; + } + return object; + }; + + /** + * Converts this WorkflowSwitchTrafficResponse to JSON. + * @function toJSON + * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @instance + * @returns {Object.} JSON object + */ + WorkflowSwitchTrafficResponse.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for WorkflowSwitchTrafficResponse + * @function getTypeUrl + * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + WorkflowSwitchTrafficResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/vtctldata.WorkflowSwitchTrafficResponse"; + }; + + return WorkflowSwitchTrafficResponse; + })(); + + vtctldata.WorkflowUpdateRequest = (function() { + + /** + * Properties of a WorkflowUpdateRequest. + * @memberof vtctldata + * @interface IWorkflowUpdateRequest + * @property {string|null} [keyspace] WorkflowUpdateRequest keyspace + * @property {tabletmanagerdata.IUpdateVReplicationWorkflowRequest|null} [tablet_request] WorkflowUpdateRequest tablet_request + */ + + /** + * Constructs a new WorkflowUpdateRequest. + * @memberof vtctldata + * @classdesc Represents a WorkflowUpdateRequest. + * @implements IWorkflowUpdateRequest + * @constructor + * @param {vtctldata.IWorkflowUpdateRequest=} [properties] Properties to set + */ + function WorkflowUpdateRequest(properties) { + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * WorkflowUpdateRequest keyspace. + * @member {string} keyspace + * @memberof vtctldata.WorkflowUpdateRequest + * @instance + */ + WorkflowUpdateRequest.prototype.keyspace = ""; + + /** + * WorkflowUpdateRequest tablet_request. + * @member {tabletmanagerdata.IUpdateVReplicationWorkflowRequest|null|undefined} tablet_request + * @memberof vtctldata.WorkflowUpdateRequest + * @instance + */ + WorkflowUpdateRequest.prototype.tablet_request = null; + + /** + * Creates a new WorkflowUpdateRequest instance using the specified properties. + * @function create + * @memberof vtctldata.WorkflowUpdateRequest + * @static + * @param {vtctldata.IWorkflowUpdateRequest=} [properties] Properties to set + * @returns {vtctldata.WorkflowUpdateRequest} WorkflowUpdateRequest instance + */ + WorkflowUpdateRequest.create = function create(properties) { + return new WorkflowUpdateRequest(properties); + }; + + /** + * Encodes the specified WorkflowUpdateRequest message. Does not implicitly {@link vtctldata.WorkflowUpdateRequest.verify|verify} messages. + * @function encode + * @memberof vtctldata.WorkflowUpdateRequest + * @static + * @param {vtctldata.IWorkflowUpdateRequest} message WorkflowUpdateRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + WorkflowUpdateRequest.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.keyspace != null && Object.hasOwnProperty.call(message, "keyspace")) + writer.uint32(/* id 1, wireType 2 =*/10).string(message.keyspace); + if (message.tablet_request != null && Object.hasOwnProperty.call(message, "tablet_request")) + $root.tabletmanagerdata.UpdateVReplicationWorkflowRequest.encode(message.tablet_request, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified WorkflowUpdateRequest message, length delimited. Does not implicitly {@link vtctldata.WorkflowUpdateRequest.verify|verify} messages. + * @function encodeDelimited + * @memberof vtctldata.WorkflowUpdateRequest + * @static + * @param {vtctldata.IWorkflowUpdateRequest} message WorkflowUpdateRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + WorkflowUpdateRequest.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a WorkflowUpdateRequest message from the specified reader or buffer. + * @function decode + * @memberof vtctldata.WorkflowUpdateRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {vtctldata.WorkflowUpdateRequest} WorkflowUpdateRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + WorkflowUpdateRequest.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.WorkflowUpdateRequest(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.keyspace = reader.string(); + break; + } + case 2: { + message.tablet_request = $root.tabletmanagerdata.UpdateVReplicationWorkflowRequest.decode(reader, reader.uint32()); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a WorkflowUpdateRequest message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof vtctldata.WorkflowUpdateRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {vtctldata.WorkflowUpdateRequest} WorkflowUpdateRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + WorkflowUpdateRequest.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a WorkflowUpdateRequest message. + * @function verify + * @memberof vtctldata.WorkflowUpdateRequest + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + WorkflowUpdateRequest.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.keyspace != null && message.hasOwnProperty("keyspace")) + if (!$util.isString(message.keyspace)) + return "keyspace: string expected"; + if (message.tablet_request != null && message.hasOwnProperty("tablet_request")) { + let error = $root.tabletmanagerdata.UpdateVReplicationWorkflowRequest.verify(message.tablet_request); + if (error) + return "tablet_request." + error; + } + return null; + }; + + /** + * Creates a WorkflowUpdateRequest message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof vtctldata.WorkflowUpdateRequest + * @static + * @param {Object.} object Plain object + * @returns {vtctldata.WorkflowUpdateRequest} WorkflowUpdateRequest + */ + WorkflowUpdateRequest.fromObject = function fromObject(object) { + if (object instanceof $root.vtctldata.WorkflowUpdateRequest) + return object; + let message = new $root.vtctldata.WorkflowUpdateRequest(); + if (object.keyspace != null) + message.keyspace = String(object.keyspace); + if (object.tablet_request != null) { + if (typeof object.tablet_request !== "object") + throw TypeError(".vtctldata.WorkflowUpdateRequest.tablet_request: object expected"); + message.tablet_request = $root.tabletmanagerdata.UpdateVReplicationWorkflowRequest.fromObject(object.tablet_request); + } + return message; + }; + + /** + * Creates a plain object from a WorkflowUpdateRequest message. Also converts values to other types if specified. + * @function toObject + * @memberof vtctldata.WorkflowUpdateRequest + * @static + * @param {vtctldata.WorkflowUpdateRequest} message WorkflowUpdateRequest + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + WorkflowUpdateRequest.toObject = function toObject(message, options) { + if (!options) + options = {}; + let object = {}; + if (options.defaults) { + object.keyspace = ""; + object.tablet_request = null; + } + if (message.keyspace != null && message.hasOwnProperty("keyspace")) + object.keyspace = message.keyspace; + if (message.tablet_request != null && message.hasOwnProperty("tablet_request")) + object.tablet_request = $root.tabletmanagerdata.UpdateVReplicationWorkflowRequest.toObject(message.tablet_request, options); + return object; + }; + + /** + * Converts this WorkflowUpdateRequest to JSON. + * @function toJSON + * @memberof vtctldata.WorkflowUpdateRequest + * @instance + * @returns {Object.} JSON object + */ + WorkflowUpdateRequest.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for WorkflowUpdateRequest + * @function getTypeUrl + * @memberof vtctldata.WorkflowUpdateRequest + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + WorkflowUpdateRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/vtctldata.WorkflowUpdateRequest"; + }; + + return WorkflowUpdateRequest; + })(); + + vtctldata.WorkflowUpdateResponse = (function() { + + /** + * Properties of a WorkflowUpdateResponse. + * @memberof vtctldata + * @interface IWorkflowUpdateResponse + * @property {string|null} [summary] WorkflowUpdateResponse summary + * @property {Array.|null} [details] WorkflowUpdateResponse details + */ + + /** + * Constructs a new WorkflowUpdateResponse. + * @memberof vtctldata + * @classdesc Represents a WorkflowUpdateResponse. + * @implements IWorkflowUpdateResponse + * @constructor + * @param {vtctldata.IWorkflowUpdateResponse=} [properties] Properties to set + */ + function WorkflowUpdateResponse(properties) { + this.details = []; + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * WorkflowUpdateResponse summary. + * @member {string} summary + * @memberof vtctldata.WorkflowUpdateResponse + * @instance + */ + WorkflowUpdateResponse.prototype.summary = ""; + + /** + * WorkflowUpdateResponse details. + * @member {Array.} details + * @memberof vtctldata.WorkflowUpdateResponse + * @instance + */ + WorkflowUpdateResponse.prototype.details = $util.emptyArray; + + /** + * Creates a new WorkflowUpdateResponse instance using the specified properties. + * @function create + * @memberof vtctldata.WorkflowUpdateResponse + * @static + * @param {vtctldata.IWorkflowUpdateResponse=} [properties] Properties to set + * @returns {vtctldata.WorkflowUpdateResponse} WorkflowUpdateResponse instance + */ + WorkflowUpdateResponse.create = function create(properties) { + return new WorkflowUpdateResponse(properties); + }; + + /** + * Encodes the specified WorkflowUpdateResponse message. Does not implicitly {@link vtctldata.WorkflowUpdateResponse.verify|verify} messages. + * @function encode + * @memberof vtctldata.WorkflowUpdateResponse + * @static + * @param {vtctldata.IWorkflowUpdateResponse} message WorkflowUpdateResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + WorkflowUpdateResponse.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.summary != null && Object.hasOwnProperty.call(message, "summary")) + writer.uint32(/* id 1, wireType 2 =*/10).string(message.summary); + if (message.details != null && message.details.length) + for (let i = 0; i < message.details.length; ++i) + $root.vtctldata.WorkflowUpdateResponse.TabletInfo.encode(message.details[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified WorkflowUpdateResponse message, length delimited. Does not implicitly {@link vtctldata.WorkflowUpdateResponse.verify|verify} messages. + * @function encodeDelimited + * @memberof vtctldata.WorkflowUpdateResponse + * @static + * @param {vtctldata.IWorkflowUpdateResponse} message WorkflowUpdateResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + WorkflowUpdateResponse.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a WorkflowUpdateResponse message from the specified reader or buffer. + * @function decode + * @memberof vtctldata.WorkflowUpdateResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {vtctldata.WorkflowUpdateResponse} WorkflowUpdateResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + WorkflowUpdateResponse.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.WorkflowUpdateResponse(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.summary = reader.string(); + break; + } + case 2: { + if (!(message.details && message.details.length)) + message.details = []; + message.details.push($root.vtctldata.WorkflowUpdateResponse.TabletInfo.decode(reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a WorkflowUpdateResponse message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof vtctldata.WorkflowUpdateResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {vtctldata.WorkflowUpdateResponse} WorkflowUpdateResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + WorkflowUpdateResponse.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a WorkflowUpdateResponse message. + * @function verify + * @memberof vtctldata.WorkflowUpdateResponse + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + WorkflowUpdateResponse.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.summary != null && message.hasOwnProperty("summary")) + if (!$util.isString(message.summary)) + return "summary: string expected"; + if (message.details != null && message.hasOwnProperty("details")) { + if (!Array.isArray(message.details)) + return "details: array expected"; + for (let i = 0; i < message.details.length; ++i) { + let error = $root.vtctldata.WorkflowUpdateResponse.TabletInfo.verify(message.details[i]); + if (error) + return "details." + error; } - if (message.id != null && message.hasOwnProperty("id")) - object.id = message.id; - if (message.tablet != null && message.hasOwnProperty("tablet")) - object.tablet = $root.topodata.TabletAlias.toObject(message.tablet, options); - if (message.source_shard != null && message.hasOwnProperty("source_shard")) - object.source_shard = message.source_shard; - if (message.position != null && message.hasOwnProperty("position")) - object.position = message.position; - if (message.status != null && message.hasOwnProperty("status")) - object.status = message.status; - if (message.info != null && message.hasOwnProperty("info")) - object.info = message.info; + } + return null; + }; + + /** + * Creates a WorkflowUpdateResponse message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof vtctldata.WorkflowUpdateResponse + * @static + * @param {Object.} object Plain object + * @returns {vtctldata.WorkflowUpdateResponse} WorkflowUpdateResponse + */ + WorkflowUpdateResponse.fromObject = function fromObject(object) { + if (object instanceof $root.vtctldata.WorkflowUpdateResponse) return object; - }; + let message = new $root.vtctldata.WorkflowUpdateResponse(); + if (object.summary != null) + message.summary = String(object.summary); + if (object.details) { + if (!Array.isArray(object.details)) + throw TypeError(".vtctldata.WorkflowUpdateResponse.details: array expected"); + message.details = []; + for (let i = 0; i < object.details.length; ++i) { + if (typeof object.details[i] !== "object") + throw TypeError(".vtctldata.WorkflowUpdateResponse.details: object expected"); + message.details[i] = $root.vtctldata.WorkflowUpdateResponse.TabletInfo.fromObject(object.details[i]); + } + } + return message; + }; - /** - * Converts this ShardStreamState to JSON. - * @function toJSON - * @memberof vtctldata.WorkflowStatusResponse.ShardStreamState - * @instance - * @returns {Object.} JSON object - */ - ShardStreamState.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; + /** + * Creates a plain object from a WorkflowUpdateResponse message. Also converts values to other types if specified. + * @function toObject + * @memberof vtctldata.WorkflowUpdateResponse + * @static + * @param {vtctldata.WorkflowUpdateResponse} message WorkflowUpdateResponse + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + WorkflowUpdateResponse.toObject = function toObject(message, options) { + if (!options) + options = {}; + let object = {}; + if (options.arrays || options.defaults) + object.details = []; + if (options.defaults) + object.summary = ""; + if (message.summary != null && message.hasOwnProperty("summary")) + object.summary = message.summary; + if (message.details && message.details.length) { + object.details = []; + for (let j = 0; j < message.details.length; ++j) + object.details[j] = $root.vtctldata.WorkflowUpdateResponse.TabletInfo.toObject(message.details[j], options); + } + return object; + }; - /** - * Gets the default type url for ShardStreamState - * @function getTypeUrl - * @memberof vtctldata.WorkflowStatusResponse.ShardStreamState - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - ShardStreamState.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/vtctldata.WorkflowStatusResponse.ShardStreamState"; - }; + /** + * Converts this WorkflowUpdateResponse to JSON. + * @function toJSON + * @memberof vtctldata.WorkflowUpdateResponse + * @instance + * @returns {Object.} JSON object + */ + WorkflowUpdateResponse.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; - return ShardStreamState; - })(); + /** + * Gets the default type url for WorkflowUpdateResponse + * @function getTypeUrl + * @memberof vtctldata.WorkflowUpdateResponse + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + WorkflowUpdateResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/vtctldata.WorkflowUpdateResponse"; + }; - WorkflowStatusResponse.ShardStreams = (function() { + WorkflowUpdateResponse.TabletInfo = (function() { /** - * Properties of a ShardStreams. - * @memberof vtctldata.WorkflowStatusResponse - * @interface IShardStreams - * @property {Array.|null} [streams] ShardStreams streams + * Properties of a TabletInfo. + * @memberof vtctldata.WorkflowUpdateResponse + * @interface ITabletInfo + * @property {topodata.ITabletAlias|null} [tablet] TabletInfo tablet + * @property {boolean|null} [changed] TabletInfo changed */ /** - * Constructs a new ShardStreams. - * @memberof vtctldata.WorkflowStatusResponse - * @classdesc Represents a ShardStreams. - * @implements IShardStreams + * Constructs a new TabletInfo. + * @memberof vtctldata.WorkflowUpdateResponse + * @classdesc Represents a TabletInfo. + * @implements ITabletInfo * @constructor - * @param {vtctldata.WorkflowStatusResponse.IShardStreams=} [properties] Properties to set + * @param {vtctldata.WorkflowUpdateResponse.ITabletInfo=} [properties] Properties to set */ - function ShardStreams(properties) { - this.streams = []; + function TabletInfo(properties) { if (properties) for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) @@ -179578,78 +180367,89 @@ export const vtctldata = $root.vtctldata = (() => { } /** - * ShardStreams streams. - * @member {Array.} streams - * @memberof vtctldata.WorkflowStatusResponse.ShardStreams + * TabletInfo tablet. + * @member {topodata.ITabletAlias|null|undefined} tablet + * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo * @instance */ - ShardStreams.prototype.streams = $util.emptyArray; + TabletInfo.prototype.tablet = null; /** - * Creates a new ShardStreams instance using the specified properties. + * TabletInfo changed. + * @member {boolean} changed + * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo + * @instance + */ + TabletInfo.prototype.changed = false; + + /** + * Creates a new TabletInfo instance using the specified properties. * @function create - * @memberof vtctldata.WorkflowStatusResponse.ShardStreams + * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo * @static - * @param {vtctldata.WorkflowStatusResponse.IShardStreams=} [properties] Properties to set - * @returns {vtctldata.WorkflowStatusResponse.ShardStreams} ShardStreams instance + * @param {vtctldata.WorkflowUpdateResponse.ITabletInfo=} [properties] Properties to set + * @returns {vtctldata.WorkflowUpdateResponse.TabletInfo} TabletInfo instance */ - ShardStreams.create = function create(properties) { - return new ShardStreams(properties); + TabletInfo.create = function create(properties) { + return new TabletInfo(properties); }; /** - * Encodes the specified ShardStreams message. Does not implicitly {@link vtctldata.WorkflowStatusResponse.ShardStreams.verify|verify} messages. + * Encodes the specified TabletInfo message. Does not implicitly {@link vtctldata.WorkflowUpdateResponse.TabletInfo.verify|verify} messages. * @function encode - * @memberof vtctldata.WorkflowStatusResponse.ShardStreams + * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo * @static - * @param {vtctldata.WorkflowStatusResponse.IShardStreams} message ShardStreams message or plain object to encode + * @param {vtctldata.WorkflowUpdateResponse.ITabletInfo} message TabletInfo message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - ShardStreams.encode = function encode(message, writer) { + TabletInfo.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.streams != null && message.streams.length) - for (let i = 0; i < message.streams.length; ++i) - $root.vtctldata.WorkflowStatusResponse.ShardStreamState.encode(message.streams[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); + if (message.tablet != null && Object.hasOwnProperty.call(message, "tablet")) + $root.topodata.TabletAlias.encode(message.tablet, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + if (message.changed != null && Object.hasOwnProperty.call(message, "changed")) + writer.uint32(/* id 2, wireType 0 =*/16).bool(message.changed); return writer; }; /** - * Encodes the specified ShardStreams message, length delimited. Does not implicitly {@link vtctldata.WorkflowStatusResponse.ShardStreams.verify|verify} messages. + * Encodes the specified TabletInfo message, length delimited. Does not implicitly {@link vtctldata.WorkflowUpdateResponse.TabletInfo.verify|verify} messages. * @function encodeDelimited - * @memberof vtctldata.WorkflowStatusResponse.ShardStreams + * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo * @static - * @param {vtctldata.WorkflowStatusResponse.IShardStreams} message ShardStreams message or plain object to encode + * @param {vtctldata.WorkflowUpdateResponse.ITabletInfo} message TabletInfo message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - ShardStreams.encodeDelimited = function encodeDelimited(message, writer) { + TabletInfo.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a ShardStreams message from the specified reader or buffer. + * Decodes a TabletInfo message from the specified reader or buffer. * @function decode - * @memberof vtctldata.WorkflowStatusResponse.ShardStreams + * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from * @param {number} [length] Message length if known beforehand - * @returns {vtctldata.WorkflowStatusResponse.ShardStreams} ShardStreams + * @returns {vtctldata.WorkflowUpdateResponse.TabletInfo} TabletInfo * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - ShardStreams.decode = function decode(reader, length) { + TabletInfo.decode = function decode(reader, length) { if (!(reader instanceof $Reader)) reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.WorkflowStatusResponse.ShardStreams(); + let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.WorkflowUpdateResponse.TabletInfo(); while (reader.pos < end) { let tag = reader.uint32(); switch (tag >>> 3) { + case 1: { + message.tablet = $root.topodata.TabletAlias.decode(reader, reader.uint32()); + break; + } case 2: { - if (!(message.streams && message.streams.length)) - message.streams = []; - message.streams.push($root.vtctldata.WorkflowStatusResponse.ShardStreamState.decode(reader, reader.uint32())); + message.changed = reader.bool(); break; } default: @@ -179661,155 +180461,138 @@ export const vtctldata = $root.vtctldata = (() => { }; /** - * Decodes a ShardStreams message from the specified reader or buffer, length delimited. + * Decodes a TabletInfo message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof vtctldata.WorkflowStatusResponse.ShardStreams + * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {vtctldata.WorkflowStatusResponse.ShardStreams} ShardStreams + * @returns {vtctldata.WorkflowUpdateResponse.TabletInfo} TabletInfo * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - ShardStreams.decodeDelimited = function decodeDelimited(reader) { + TabletInfo.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; /** - * Verifies a ShardStreams message. + * Verifies a TabletInfo message. * @function verify - * @memberof vtctldata.WorkflowStatusResponse.ShardStreams + * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo * @static * @param {Object.} message Plain object to verify * @returns {string|null} `null` if valid, otherwise the reason why it is not */ - ShardStreams.verify = function verify(message) { + TabletInfo.verify = function verify(message) { if (typeof message !== "object" || message === null) return "object expected"; - if (message.streams != null && message.hasOwnProperty("streams")) { - if (!Array.isArray(message.streams)) - return "streams: array expected"; - for (let i = 0; i < message.streams.length; ++i) { - let error = $root.vtctldata.WorkflowStatusResponse.ShardStreamState.verify(message.streams[i]); - if (error) - return "streams." + error; - } + if (message.tablet != null && message.hasOwnProperty("tablet")) { + let error = $root.topodata.TabletAlias.verify(message.tablet); + if (error) + return "tablet." + error; } + if (message.changed != null && message.hasOwnProperty("changed")) + if (typeof message.changed !== "boolean") + return "changed: boolean expected"; return null; }; /** - * Creates a ShardStreams message from a plain object. Also converts values to their respective internal types. + * Creates a TabletInfo message from a plain object. Also converts values to their respective internal types. * @function fromObject - * @memberof vtctldata.WorkflowStatusResponse.ShardStreams + * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo * @static * @param {Object.} object Plain object - * @returns {vtctldata.WorkflowStatusResponse.ShardStreams} ShardStreams + * @returns {vtctldata.WorkflowUpdateResponse.TabletInfo} TabletInfo */ - ShardStreams.fromObject = function fromObject(object) { - if (object instanceof $root.vtctldata.WorkflowStatusResponse.ShardStreams) + TabletInfo.fromObject = function fromObject(object) { + if (object instanceof $root.vtctldata.WorkflowUpdateResponse.TabletInfo) return object; - let message = new $root.vtctldata.WorkflowStatusResponse.ShardStreams(); - if (object.streams) { - if (!Array.isArray(object.streams)) - throw TypeError(".vtctldata.WorkflowStatusResponse.ShardStreams.streams: array expected"); - message.streams = []; - for (let i = 0; i < object.streams.length; ++i) { - if (typeof object.streams[i] !== "object") - throw TypeError(".vtctldata.WorkflowStatusResponse.ShardStreams.streams: object expected"); - message.streams[i] = $root.vtctldata.WorkflowStatusResponse.ShardStreamState.fromObject(object.streams[i]); - } + let message = new $root.vtctldata.WorkflowUpdateResponse.TabletInfo(); + if (object.tablet != null) { + if (typeof object.tablet !== "object") + throw TypeError(".vtctldata.WorkflowUpdateResponse.TabletInfo.tablet: object expected"); + message.tablet = $root.topodata.TabletAlias.fromObject(object.tablet); } + if (object.changed != null) + message.changed = Boolean(object.changed); return message; }; /** - * Creates a plain object from a ShardStreams message. Also converts values to other types if specified. + * Creates a plain object from a TabletInfo message. Also converts values to other types if specified. * @function toObject - * @memberof vtctldata.WorkflowStatusResponse.ShardStreams + * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo * @static - * @param {vtctldata.WorkflowStatusResponse.ShardStreams} message ShardStreams + * @param {vtctldata.WorkflowUpdateResponse.TabletInfo} message TabletInfo * @param {$protobuf.IConversionOptions} [options] Conversion options * @returns {Object.} Plain object */ - ShardStreams.toObject = function toObject(message, options) { + TabletInfo.toObject = function toObject(message, options) { if (!options) options = {}; let object = {}; - if (options.arrays || options.defaults) - object.streams = []; - if (message.streams && message.streams.length) { - object.streams = []; - for (let j = 0; j < message.streams.length; ++j) - object.streams[j] = $root.vtctldata.WorkflowStatusResponse.ShardStreamState.toObject(message.streams[j], options); + if (options.defaults) { + object.tablet = null; + object.changed = false; } + if (message.tablet != null && message.hasOwnProperty("tablet")) + object.tablet = $root.topodata.TabletAlias.toObject(message.tablet, options); + if (message.changed != null && message.hasOwnProperty("changed")) + object.changed = message.changed; return object; }; /** - * Converts this ShardStreams to JSON. + * Converts this TabletInfo to JSON. * @function toJSON - * @memberof vtctldata.WorkflowStatusResponse.ShardStreams + * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo * @instance * @returns {Object.} JSON object */ - ShardStreams.prototype.toJSON = function toJSON() { + TabletInfo.prototype.toJSON = function toJSON() { return this.constructor.toObject(this, $protobuf.util.toJSONOptions); }; /** - * Gets the default type url for ShardStreams + * Gets the default type url for TabletInfo * @function getTypeUrl - * @memberof vtctldata.WorkflowStatusResponse.ShardStreams + * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo * @static * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") * @returns {string} The default type url */ - ShardStreams.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + TabletInfo.getTypeUrl = function getTypeUrl(typeUrlPrefix) { if (typeUrlPrefix === undefined) { typeUrlPrefix = "type.googleapis.com"; } - return typeUrlPrefix + "/vtctldata.WorkflowStatusResponse.ShardStreams"; + return typeUrlPrefix + "/vtctldata.WorkflowUpdateResponse.TabletInfo"; }; - return ShardStreams; + return TabletInfo; })(); - return WorkflowStatusResponse; + return WorkflowUpdateResponse; })(); - vtctldata.WorkflowSwitchTrafficRequest = (function() { + vtctldata.GetMirrorRulesRequest = (function() { /** - * Properties of a WorkflowSwitchTrafficRequest. + * Properties of a GetMirrorRulesRequest. * @memberof vtctldata - * @interface IWorkflowSwitchTrafficRequest - * @property {string|null} [keyspace] WorkflowSwitchTrafficRequest keyspace - * @property {string|null} [workflow] WorkflowSwitchTrafficRequest workflow - * @property {Array.|null} [cells] WorkflowSwitchTrafficRequest cells - * @property {Array.|null} [tablet_types] WorkflowSwitchTrafficRequest tablet_types - * @property {vttime.IDuration|null} [max_replication_lag_allowed] WorkflowSwitchTrafficRequest max_replication_lag_allowed - * @property {boolean|null} [enable_reverse_replication] WorkflowSwitchTrafficRequest enable_reverse_replication - * @property {number|null} [direction] WorkflowSwitchTrafficRequest direction - * @property {vttime.IDuration|null} [timeout] WorkflowSwitchTrafficRequest timeout - * @property {boolean|null} [dry_run] WorkflowSwitchTrafficRequest dry_run - * @property {boolean|null} [initialize_target_sequences] WorkflowSwitchTrafficRequest initialize_target_sequences - * @property {Array.|null} [shards] WorkflowSwitchTrafficRequest shards + * @interface IGetMirrorRulesRequest */ /** - * Constructs a new WorkflowSwitchTrafficRequest. + * Constructs a new GetMirrorRulesRequest. * @memberof vtctldata - * @classdesc Represents a WorkflowSwitchTrafficRequest. - * @implements IWorkflowSwitchTrafficRequest + * @classdesc Represents a GetMirrorRulesRequest. + * @implements IGetMirrorRulesRequest * @constructor - * @param {vtctldata.IWorkflowSwitchTrafficRequest=} [properties] Properties to set + * @param {vtctldata.IGetMirrorRulesRequest=} [properties] Properties to set */ - function WorkflowSwitchTrafficRequest(properties) { - this.cells = []; - this.tablet_types = []; - this.shards = []; + function GetMirrorRulesRequest(properties) { if (properties) for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) @@ -179817,234 +180600,63 @@ export const vtctldata = $root.vtctldata = (() => { } /** - * WorkflowSwitchTrafficRequest keyspace. - * @member {string} keyspace - * @memberof vtctldata.WorkflowSwitchTrafficRequest - * @instance - */ - WorkflowSwitchTrafficRequest.prototype.keyspace = ""; - - /** - * WorkflowSwitchTrafficRequest workflow. - * @member {string} workflow - * @memberof vtctldata.WorkflowSwitchTrafficRequest - * @instance - */ - WorkflowSwitchTrafficRequest.prototype.workflow = ""; - - /** - * WorkflowSwitchTrafficRequest cells. - * @member {Array.} cells - * @memberof vtctldata.WorkflowSwitchTrafficRequest - * @instance - */ - WorkflowSwitchTrafficRequest.prototype.cells = $util.emptyArray; - - /** - * WorkflowSwitchTrafficRequest tablet_types. - * @member {Array.} tablet_types - * @memberof vtctldata.WorkflowSwitchTrafficRequest - * @instance - */ - WorkflowSwitchTrafficRequest.prototype.tablet_types = $util.emptyArray; - - /** - * WorkflowSwitchTrafficRequest max_replication_lag_allowed. - * @member {vttime.IDuration|null|undefined} max_replication_lag_allowed - * @memberof vtctldata.WorkflowSwitchTrafficRequest - * @instance - */ - WorkflowSwitchTrafficRequest.prototype.max_replication_lag_allowed = null; - - /** - * WorkflowSwitchTrafficRequest enable_reverse_replication. - * @member {boolean} enable_reverse_replication - * @memberof vtctldata.WorkflowSwitchTrafficRequest - * @instance - */ - WorkflowSwitchTrafficRequest.prototype.enable_reverse_replication = false; - - /** - * WorkflowSwitchTrafficRequest direction. - * @member {number} direction - * @memberof vtctldata.WorkflowSwitchTrafficRequest - * @instance - */ - WorkflowSwitchTrafficRequest.prototype.direction = 0; - - /** - * WorkflowSwitchTrafficRequest timeout. - * @member {vttime.IDuration|null|undefined} timeout - * @memberof vtctldata.WorkflowSwitchTrafficRequest - * @instance - */ - WorkflowSwitchTrafficRequest.prototype.timeout = null; - - /** - * WorkflowSwitchTrafficRequest dry_run. - * @member {boolean} dry_run - * @memberof vtctldata.WorkflowSwitchTrafficRequest - * @instance - */ - WorkflowSwitchTrafficRequest.prototype.dry_run = false; - - /** - * WorkflowSwitchTrafficRequest initialize_target_sequences. - * @member {boolean} initialize_target_sequences - * @memberof vtctldata.WorkflowSwitchTrafficRequest - * @instance - */ - WorkflowSwitchTrafficRequest.prototype.initialize_target_sequences = false; - - /** - * WorkflowSwitchTrafficRequest shards. - * @member {Array.} shards - * @memberof vtctldata.WorkflowSwitchTrafficRequest - * @instance - */ - WorkflowSwitchTrafficRequest.prototype.shards = $util.emptyArray; - - /** - * Creates a new WorkflowSwitchTrafficRequest instance using the specified properties. + * Creates a new GetMirrorRulesRequest instance using the specified properties. * @function create - * @memberof vtctldata.WorkflowSwitchTrafficRequest - * @static - * @param {vtctldata.IWorkflowSwitchTrafficRequest=} [properties] Properties to set - * @returns {vtctldata.WorkflowSwitchTrafficRequest} WorkflowSwitchTrafficRequest instance - */ - WorkflowSwitchTrafficRequest.create = function create(properties) { - return new WorkflowSwitchTrafficRequest(properties); - }; - - /** - * Encodes the specified WorkflowSwitchTrafficRequest message. Does not implicitly {@link vtctldata.WorkflowSwitchTrafficRequest.verify|verify} messages. - * @function encode - * @memberof vtctldata.WorkflowSwitchTrafficRequest - * @static - * @param {vtctldata.IWorkflowSwitchTrafficRequest} message WorkflowSwitchTrafficRequest message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - WorkflowSwitchTrafficRequest.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.keyspace != null && Object.hasOwnProperty.call(message, "keyspace")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.keyspace); - if (message.workflow != null && Object.hasOwnProperty.call(message, "workflow")) - writer.uint32(/* id 2, wireType 2 =*/18).string(message.workflow); - if (message.cells != null && message.cells.length) - for (let i = 0; i < message.cells.length; ++i) - writer.uint32(/* id 3, wireType 2 =*/26).string(message.cells[i]); - if (message.tablet_types != null && message.tablet_types.length) { - writer.uint32(/* id 4, wireType 2 =*/34).fork(); - for (let i = 0; i < message.tablet_types.length; ++i) - writer.int32(message.tablet_types[i]); - writer.ldelim(); - } - if (message.max_replication_lag_allowed != null && Object.hasOwnProperty.call(message, "max_replication_lag_allowed")) - $root.vttime.Duration.encode(message.max_replication_lag_allowed, writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim(); - if (message.enable_reverse_replication != null && Object.hasOwnProperty.call(message, "enable_reverse_replication")) - writer.uint32(/* id 6, wireType 0 =*/48).bool(message.enable_reverse_replication); - if (message.direction != null && Object.hasOwnProperty.call(message, "direction")) - writer.uint32(/* id 7, wireType 0 =*/56).int32(message.direction); - if (message.timeout != null && Object.hasOwnProperty.call(message, "timeout")) - $root.vttime.Duration.encode(message.timeout, writer.uint32(/* id 8, wireType 2 =*/66).fork()).ldelim(); - if (message.dry_run != null && Object.hasOwnProperty.call(message, "dry_run")) - writer.uint32(/* id 9, wireType 0 =*/72).bool(message.dry_run); - if (message.initialize_target_sequences != null && Object.hasOwnProperty.call(message, "initialize_target_sequences")) - writer.uint32(/* id 10, wireType 0 =*/80).bool(message.initialize_target_sequences); - if (message.shards != null && message.shards.length) - for (let i = 0; i < message.shards.length; ++i) - writer.uint32(/* id 11, wireType 2 =*/90).string(message.shards[i]); + * @memberof vtctldata.GetMirrorRulesRequest + * @static + * @param {vtctldata.IGetMirrorRulesRequest=} [properties] Properties to set + * @returns {vtctldata.GetMirrorRulesRequest} GetMirrorRulesRequest instance + */ + GetMirrorRulesRequest.create = function create(properties) { + return new GetMirrorRulesRequest(properties); + }; + + /** + * Encodes the specified GetMirrorRulesRequest message. Does not implicitly {@link vtctldata.GetMirrorRulesRequest.verify|verify} messages. + * @function encode + * @memberof vtctldata.GetMirrorRulesRequest + * @static + * @param {vtctldata.IGetMirrorRulesRequest} message GetMirrorRulesRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetMirrorRulesRequest.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); return writer; }; /** - * Encodes the specified WorkflowSwitchTrafficRequest message, length delimited. Does not implicitly {@link vtctldata.WorkflowSwitchTrafficRequest.verify|verify} messages. + * Encodes the specified GetMirrorRulesRequest message, length delimited. Does not implicitly {@link vtctldata.GetMirrorRulesRequest.verify|verify} messages. * @function encodeDelimited - * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @memberof vtctldata.GetMirrorRulesRequest * @static - * @param {vtctldata.IWorkflowSwitchTrafficRequest} message WorkflowSwitchTrafficRequest message or plain object to encode + * @param {vtctldata.IGetMirrorRulesRequest} message GetMirrorRulesRequest message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - WorkflowSwitchTrafficRequest.encodeDelimited = function encodeDelimited(message, writer) { + GetMirrorRulesRequest.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a WorkflowSwitchTrafficRequest message from the specified reader or buffer. + * Decodes a GetMirrorRulesRequest message from the specified reader or buffer. * @function decode - * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @memberof vtctldata.GetMirrorRulesRequest * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from * @param {number} [length] Message length if known beforehand - * @returns {vtctldata.WorkflowSwitchTrafficRequest} WorkflowSwitchTrafficRequest + * @returns {vtctldata.GetMirrorRulesRequest} GetMirrorRulesRequest * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - WorkflowSwitchTrafficRequest.decode = function decode(reader, length) { + GetMirrorRulesRequest.decode = function decode(reader, length) { if (!(reader instanceof $Reader)) reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.WorkflowSwitchTrafficRequest(); + let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.GetMirrorRulesRequest(); while (reader.pos < end) { let tag = reader.uint32(); switch (tag >>> 3) { - case 1: { - message.keyspace = reader.string(); - break; - } - case 2: { - message.workflow = reader.string(); - break; - } - case 3: { - if (!(message.cells && message.cells.length)) - message.cells = []; - message.cells.push(reader.string()); - break; - } - case 4: { - if (!(message.tablet_types && message.tablet_types.length)) - message.tablet_types = []; - if ((tag & 7) === 2) { - let end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.tablet_types.push(reader.int32()); - } else - message.tablet_types.push(reader.int32()); - break; - } - case 5: { - message.max_replication_lag_allowed = $root.vttime.Duration.decode(reader, reader.uint32()); - break; - } - case 6: { - message.enable_reverse_replication = reader.bool(); - break; - } - case 7: { - message.direction = reader.int32(); - break; - } - case 8: { - message.timeout = $root.vttime.Duration.decode(reader, reader.uint32()); - break; - } - case 9: { - message.dry_run = reader.bool(); - break; - } - case 10: { - message.initialize_target_sequences = reader.bool(); - break; - } - case 11: { - if (!(message.shards && message.shards.length)) - message.shards = []; - message.shards.push(reader.string()); - break; - } default: reader.skipType(tag & 7); break; @@ -180054,319 +180666,109 @@ export const vtctldata = $root.vtctldata = (() => { }; /** - * Decodes a WorkflowSwitchTrafficRequest message from the specified reader or buffer, length delimited. + * Decodes a GetMirrorRulesRequest message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @memberof vtctldata.GetMirrorRulesRequest * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {vtctldata.WorkflowSwitchTrafficRequest} WorkflowSwitchTrafficRequest + * @returns {vtctldata.GetMirrorRulesRequest} GetMirrorRulesRequest * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - WorkflowSwitchTrafficRequest.decodeDelimited = function decodeDelimited(reader) { + GetMirrorRulesRequest.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; /** - * Verifies a WorkflowSwitchTrafficRequest message. + * Verifies a GetMirrorRulesRequest message. * @function verify - * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @memberof vtctldata.GetMirrorRulesRequest * @static * @param {Object.} message Plain object to verify * @returns {string|null} `null` if valid, otherwise the reason why it is not */ - WorkflowSwitchTrafficRequest.verify = function verify(message) { + GetMirrorRulesRequest.verify = function verify(message) { if (typeof message !== "object" || message === null) return "object expected"; - if (message.keyspace != null && message.hasOwnProperty("keyspace")) - if (!$util.isString(message.keyspace)) - return "keyspace: string expected"; - if (message.workflow != null && message.hasOwnProperty("workflow")) - if (!$util.isString(message.workflow)) - return "workflow: string expected"; - if (message.cells != null && message.hasOwnProperty("cells")) { - if (!Array.isArray(message.cells)) - return "cells: array expected"; - for (let i = 0; i < message.cells.length; ++i) - if (!$util.isString(message.cells[i])) - return "cells: string[] expected"; - } - if (message.tablet_types != null && message.hasOwnProperty("tablet_types")) { - if (!Array.isArray(message.tablet_types)) - return "tablet_types: array expected"; - for (let i = 0; i < message.tablet_types.length; ++i) - switch (message.tablet_types[i]) { - default: - return "tablet_types: enum value[] expected"; - case 0: - case 1: - case 1: - case 2: - case 3: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - break; - } - } - if (message.max_replication_lag_allowed != null && message.hasOwnProperty("max_replication_lag_allowed")) { - let error = $root.vttime.Duration.verify(message.max_replication_lag_allowed); - if (error) - return "max_replication_lag_allowed." + error; - } - if (message.enable_reverse_replication != null && message.hasOwnProperty("enable_reverse_replication")) - if (typeof message.enable_reverse_replication !== "boolean") - return "enable_reverse_replication: boolean expected"; - if (message.direction != null && message.hasOwnProperty("direction")) - if (!$util.isInteger(message.direction)) - return "direction: integer expected"; - if (message.timeout != null && message.hasOwnProperty("timeout")) { - let error = $root.vttime.Duration.verify(message.timeout); - if (error) - return "timeout." + error; - } - if (message.dry_run != null && message.hasOwnProperty("dry_run")) - if (typeof message.dry_run !== "boolean") - return "dry_run: boolean expected"; - if (message.initialize_target_sequences != null && message.hasOwnProperty("initialize_target_sequences")) - if (typeof message.initialize_target_sequences !== "boolean") - return "initialize_target_sequences: boolean expected"; - if (message.shards != null && message.hasOwnProperty("shards")) { - if (!Array.isArray(message.shards)) - return "shards: array expected"; - for (let i = 0; i < message.shards.length; ++i) - if (!$util.isString(message.shards[i])) - return "shards: string[] expected"; - } return null; }; /** - * Creates a WorkflowSwitchTrafficRequest message from a plain object. Also converts values to their respective internal types. + * Creates a GetMirrorRulesRequest message from a plain object. Also converts values to their respective internal types. * @function fromObject - * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @memberof vtctldata.GetMirrorRulesRequest * @static * @param {Object.} object Plain object - * @returns {vtctldata.WorkflowSwitchTrafficRequest} WorkflowSwitchTrafficRequest + * @returns {vtctldata.GetMirrorRulesRequest} GetMirrorRulesRequest */ - WorkflowSwitchTrafficRequest.fromObject = function fromObject(object) { - if (object instanceof $root.vtctldata.WorkflowSwitchTrafficRequest) + GetMirrorRulesRequest.fromObject = function fromObject(object) { + if (object instanceof $root.vtctldata.GetMirrorRulesRequest) return object; - let message = new $root.vtctldata.WorkflowSwitchTrafficRequest(); - if (object.keyspace != null) - message.keyspace = String(object.keyspace); - if (object.workflow != null) - message.workflow = String(object.workflow); - if (object.cells) { - if (!Array.isArray(object.cells)) - throw TypeError(".vtctldata.WorkflowSwitchTrafficRequest.cells: array expected"); - message.cells = []; - for (let i = 0; i < object.cells.length; ++i) - message.cells[i] = String(object.cells[i]); - } - if (object.tablet_types) { - if (!Array.isArray(object.tablet_types)) - throw TypeError(".vtctldata.WorkflowSwitchTrafficRequest.tablet_types: array expected"); - message.tablet_types = []; - for (let i = 0; i < object.tablet_types.length; ++i) - switch (object.tablet_types[i]) { - default: - if (typeof object.tablet_types[i] === "number") { - message.tablet_types[i] = object.tablet_types[i]; - break; - } - case "UNKNOWN": - case 0: - message.tablet_types[i] = 0; - break; - case "PRIMARY": - case 1: - message.tablet_types[i] = 1; - break; - case "MASTER": - case 1: - message.tablet_types[i] = 1; - break; - case "REPLICA": - case 2: - message.tablet_types[i] = 2; - break; - case "RDONLY": - case 3: - message.tablet_types[i] = 3; - break; - case "BATCH": - case 3: - message.tablet_types[i] = 3; - break; - case "SPARE": - case 4: - message.tablet_types[i] = 4; - break; - case "EXPERIMENTAL": - case 5: - message.tablet_types[i] = 5; - break; - case "BACKUP": - case 6: - message.tablet_types[i] = 6; - break; - case "RESTORE": - case 7: - message.tablet_types[i] = 7; - break; - case "DRAINED": - case 8: - message.tablet_types[i] = 8; - break; - } - } - if (object.max_replication_lag_allowed != null) { - if (typeof object.max_replication_lag_allowed !== "object") - throw TypeError(".vtctldata.WorkflowSwitchTrafficRequest.max_replication_lag_allowed: object expected"); - message.max_replication_lag_allowed = $root.vttime.Duration.fromObject(object.max_replication_lag_allowed); - } - if (object.enable_reverse_replication != null) - message.enable_reverse_replication = Boolean(object.enable_reverse_replication); - if (object.direction != null) - message.direction = object.direction | 0; - if (object.timeout != null) { - if (typeof object.timeout !== "object") - throw TypeError(".vtctldata.WorkflowSwitchTrafficRequest.timeout: object expected"); - message.timeout = $root.vttime.Duration.fromObject(object.timeout); - } - if (object.dry_run != null) - message.dry_run = Boolean(object.dry_run); - if (object.initialize_target_sequences != null) - message.initialize_target_sequences = Boolean(object.initialize_target_sequences); - if (object.shards) { - if (!Array.isArray(object.shards)) - throw TypeError(".vtctldata.WorkflowSwitchTrafficRequest.shards: array expected"); - message.shards = []; - for (let i = 0; i < object.shards.length; ++i) - message.shards[i] = String(object.shards[i]); - } - return message; + return new $root.vtctldata.GetMirrorRulesRequest(); }; /** - * Creates a plain object from a WorkflowSwitchTrafficRequest message. Also converts values to other types if specified. + * Creates a plain object from a GetMirrorRulesRequest message. Also converts values to other types if specified. * @function toObject - * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @memberof vtctldata.GetMirrorRulesRequest * @static - * @param {vtctldata.WorkflowSwitchTrafficRequest} message WorkflowSwitchTrafficRequest + * @param {vtctldata.GetMirrorRulesRequest} message GetMirrorRulesRequest * @param {$protobuf.IConversionOptions} [options] Conversion options * @returns {Object.} Plain object */ - WorkflowSwitchTrafficRequest.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (options.arrays || options.defaults) { - object.cells = []; - object.tablet_types = []; - object.shards = []; - } - if (options.defaults) { - object.keyspace = ""; - object.workflow = ""; - object.max_replication_lag_allowed = null; - object.enable_reverse_replication = false; - object.direction = 0; - object.timeout = null; - object.dry_run = false; - object.initialize_target_sequences = false; - } - if (message.keyspace != null && message.hasOwnProperty("keyspace")) - object.keyspace = message.keyspace; - if (message.workflow != null && message.hasOwnProperty("workflow")) - object.workflow = message.workflow; - if (message.cells && message.cells.length) { - object.cells = []; - for (let j = 0; j < message.cells.length; ++j) - object.cells[j] = message.cells[j]; - } - if (message.tablet_types && message.tablet_types.length) { - object.tablet_types = []; - for (let j = 0; j < message.tablet_types.length; ++j) - object.tablet_types[j] = options.enums === String ? $root.topodata.TabletType[message.tablet_types[j]] === undefined ? message.tablet_types[j] : $root.topodata.TabletType[message.tablet_types[j]] : message.tablet_types[j]; - } - if (message.max_replication_lag_allowed != null && message.hasOwnProperty("max_replication_lag_allowed")) - object.max_replication_lag_allowed = $root.vttime.Duration.toObject(message.max_replication_lag_allowed, options); - if (message.enable_reverse_replication != null && message.hasOwnProperty("enable_reverse_replication")) - object.enable_reverse_replication = message.enable_reverse_replication; - if (message.direction != null && message.hasOwnProperty("direction")) - object.direction = message.direction; - if (message.timeout != null && message.hasOwnProperty("timeout")) - object.timeout = $root.vttime.Duration.toObject(message.timeout, options); - if (message.dry_run != null && message.hasOwnProperty("dry_run")) - object.dry_run = message.dry_run; - if (message.initialize_target_sequences != null && message.hasOwnProperty("initialize_target_sequences")) - object.initialize_target_sequences = message.initialize_target_sequences; - if (message.shards && message.shards.length) { - object.shards = []; - for (let j = 0; j < message.shards.length; ++j) - object.shards[j] = message.shards[j]; - } - return object; + GetMirrorRulesRequest.toObject = function toObject() { + return {}; }; /** - * Converts this WorkflowSwitchTrafficRequest to JSON. + * Converts this GetMirrorRulesRequest to JSON. * @function toJSON - * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @memberof vtctldata.GetMirrorRulesRequest * @instance * @returns {Object.} JSON object */ - WorkflowSwitchTrafficRequest.prototype.toJSON = function toJSON() { + GetMirrorRulesRequest.prototype.toJSON = function toJSON() { return this.constructor.toObject(this, $protobuf.util.toJSONOptions); }; /** - * Gets the default type url for WorkflowSwitchTrafficRequest + * Gets the default type url for GetMirrorRulesRequest * @function getTypeUrl - * @memberof vtctldata.WorkflowSwitchTrafficRequest + * @memberof vtctldata.GetMirrorRulesRequest * @static * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") * @returns {string} The default type url */ - WorkflowSwitchTrafficRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + GetMirrorRulesRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { if (typeUrlPrefix === undefined) { typeUrlPrefix = "type.googleapis.com"; } - return typeUrlPrefix + "/vtctldata.WorkflowSwitchTrafficRequest"; + return typeUrlPrefix + "/vtctldata.GetMirrorRulesRequest"; }; - return WorkflowSwitchTrafficRequest; + return GetMirrorRulesRequest; })(); - vtctldata.WorkflowSwitchTrafficResponse = (function() { + vtctldata.GetMirrorRulesResponse = (function() { /** - * Properties of a WorkflowSwitchTrafficResponse. + * Properties of a GetMirrorRulesResponse. * @memberof vtctldata - * @interface IWorkflowSwitchTrafficResponse - * @property {string|null} [summary] WorkflowSwitchTrafficResponse summary - * @property {string|null} [start_state] WorkflowSwitchTrafficResponse start_state - * @property {string|null} [current_state] WorkflowSwitchTrafficResponse current_state - * @property {Array.|null} [dry_run_results] WorkflowSwitchTrafficResponse dry_run_results + * @interface IGetMirrorRulesResponse + * @property {vschema.IMirrorRules|null} [mirror_rules] GetMirrorRulesResponse mirror_rules */ /** - * Constructs a new WorkflowSwitchTrafficResponse. + * Constructs a new GetMirrorRulesResponse. * @memberof vtctldata - * @classdesc Represents a WorkflowSwitchTrafficResponse. - * @implements IWorkflowSwitchTrafficResponse + * @classdesc Represents a GetMirrorRulesResponse. + * @implements IGetMirrorRulesResponse * @constructor - * @param {vtctldata.IWorkflowSwitchTrafficResponse=} [properties] Properties to set + * @param {vtctldata.IGetMirrorRulesResponse=} [properties] Properties to set */ - function WorkflowSwitchTrafficResponse(properties) { - this.dry_run_results = []; + function GetMirrorRulesResponse(properties) { if (properties) for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) @@ -180374,120 +180776,75 @@ export const vtctldata = $root.vtctldata = (() => { } /** - * WorkflowSwitchTrafficResponse summary. - * @member {string} summary - * @memberof vtctldata.WorkflowSwitchTrafficResponse - * @instance - */ - WorkflowSwitchTrafficResponse.prototype.summary = ""; - - /** - * WorkflowSwitchTrafficResponse start_state. - * @member {string} start_state - * @memberof vtctldata.WorkflowSwitchTrafficResponse - * @instance - */ - WorkflowSwitchTrafficResponse.prototype.start_state = ""; - - /** - * WorkflowSwitchTrafficResponse current_state. - * @member {string} current_state - * @memberof vtctldata.WorkflowSwitchTrafficResponse - * @instance - */ - WorkflowSwitchTrafficResponse.prototype.current_state = ""; - - /** - * WorkflowSwitchTrafficResponse dry_run_results. - * @member {Array.} dry_run_results - * @memberof vtctldata.WorkflowSwitchTrafficResponse + * GetMirrorRulesResponse mirror_rules. + * @member {vschema.IMirrorRules|null|undefined} mirror_rules + * @memberof vtctldata.GetMirrorRulesResponse * @instance */ - WorkflowSwitchTrafficResponse.prototype.dry_run_results = $util.emptyArray; + GetMirrorRulesResponse.prototype.mirror_rules = null; /** - * Creates a new WorkflowSwitchTrafficResponse instance using the specified properties. + * Creates a new GetMirrorRulesResponse instance using the specified properties. * @function create - * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @memberof vtctldata.GetMirrorRulesResponse * @static - * @param {vtctldata.IWorkflowSwitchTrafficResponse=} [properties] Properties to set - * @returns {vtctldata.WorkflowSwitchTrafficResponse} WorkflowSwitchTrafficResponse instance + * @param {vtctldata.IGetMirrorRulesResponse=} [properties] Properties to set + * @returns {vtctldata.GetMirrorRulesResponse} GetMirrorRulesResponse instance */ - WorkflowSwitchTrafficResponse.create = function create(properties) { - return new WorkflowSwitchTrafficResponse(properties); + GetMirrorRulesResponse.create = function create(properties) { + return new GetMirrorRulesResponse(properties); }; /** - * Encodes the specified WorkflowSwitchTrafficResponse message. Does not implicitly {@link vtctldata.WorkflowSwitchTrafficResponse.verify|verify} messages. + * Encodes the specified GetMirrorRulesResponse message. Does not implicitly {@link vtctldata.GetMirrorRulesResponse.verify|verify} messages. * @function encode - * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @memberof vtctldata.GetMirrorRulesResponse * @static - * @param {vtctldata.IWorkflowSwitchTrafficResponse} message WorkflowSwitchTrafficResponse message or plain object to encode + * @param {vtctldata.IGetMirrorRulesResponse} message GetMirrorRulesResponse message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - WorkflowSwitchTrafficResponse.encode = function encode(message, writer) { + GetMirrorRulesResponse.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.summary != null && Object.hasOwnProperty.call(message, "summary")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.summary); - if (message.start_state != null && Object.hasOwnProperty.call(message, "start_state")) - writer.uint32(/* id 2, wireType 2 =*/18).string(message.start_state); - if (message.current_state != null && Object.hasOwnProperty.call(message, "current_state")) - writer.uint32(/* id 3, wireType 2 =*/26).string(message.current_state); - if (message.dry_run_results != null && message.dry_run_results.length) - for (let i = 0; i < message.dry_run_results.length; ++i) - writer.uint32(/* id 4, wireType 2 =*/34).string(message.dry_run_results[i]); + if (message.mirror_rules != null && Object.hasOwnProperty.call(message, "mirror_rules")) + $root.vschema.MirrorRules.encode(message.mirror_rules, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); return writer; }; /** - * Encodes the specified WorkflowSwitchTrafficResponse message, length delimited. Does not implicitly {@link vtctldata.WorkflowSwitchTrafficResponse.verify|verify} messages. + * Encodes the specified GetMirrorRulesResponse message, length delimited. Does not implicitly {@link vtctldata.GetMirrorRulesResponse.verify|verify} messages. * @function encodeDelimited - * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @memberof vtctldata.GetMirrorRulesResponse * @static - * @param {vtctldata.IWorkflowSwitchTrafficResponse} message WorkflowSwitchTrafficResponse message or plain object to encode + * @param {vtctldata.IGetMirrorRulesResponse} message GetMirrorRulesResponse message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - WorkflowSwitchTrafficResponse.encodeDelimited = function encodeDelimited(message, writer) { + GetMirrorRulesResponse.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a WorkflowSwitchTrafficResponse message from the specified reader or buffer. + * Decodes a GetMirrorRulesResponse message from the specified reader or buffer. * @function decode - * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @memberof vtctldata.GetMirrorRulesResponse * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from * @param {number} [length] Message length if known beforehand - * @returns {vtctldata.WorkflowSwitchTrafficResponse} WorkflowSwitchTrafficResponse + * @returns {vtctldata.GetMirrorRulesResponse} GetMirrorRulesResponse * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - WorkflowSwitchTrafficResponse.decode = function decode(reader, length) { + GetMirrorRulesResponse.decode = function decode(reader, length) { if (!(reader instanceof $Reader)) reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.WorkflowSwitchTrafficResponse(); + let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.GetMirrorRulesResponse(); while (reader.pos < end) { let tag = reader.uint32(); switch (tag >>> 3) { case 1: { - message.summary = reader.string(); - break; - } - case 2: { - message.start_state = reader.string(); - break; - } - case 3: { - message.current_state = reader.string(); - break; - } - case 4: { - if (!(message.dry_run_results && message.dry_run_results.length)) - message.dry_run_results = []; - message.dry_run_results.push(reader.string()); + message.mirror_rules = $root.vschema.MirrorRules.decode(reader, reader.uint32()); break; } default: @@ -180499,161 +180856,131 @@ export const vtctldata = $root.vtctldata = (() => { }; /** - * Decodes a WorkflowSwitchTrafficResponse message from the specified reader or buffer, length delimited. + * Decodes a GetMirrorRulesResponse message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @memberof vtctldata.GetMirrorRulesResponse * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {vtctldata.WorkflowSwitchTrafficResponse} WorkflowSwitchTrafficResponse + * @returns {vtctldata.GetMirrorRulesResponse} GetMirrorRulesResponse * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - WorkflowSwitchTrafficResponse.decodeDelimited = function decodeDelimited(reader) { + GetMirrorRulesResponse.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; /** - * Verifies a WorkflowSwitchTrafficResponse message. + * Verifies a GetMirrorRulesResponse message. * @function verify - * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @memberof vtctldata.GetMirrorRulesResponse * @static * @param {Object.} message Plain object to verify * @returns {string|null} `null` if valid, otherwise the reason why it is not */ - WorkflowSwitchTrafficResponse.verify = function verify(message) { + GetMirrorRulesResponse.verify = function verify(message) { if (typeof message !== "object" || message === null) return "object expected"; - if (message.summary != null && message.hasOwnProperty("summary")) - if (!$util.isString(message.summary)) - return "summary: string expected"; - if (message.start_state != null && message.hasOwnProperty("start_state")) - if (!$util.isString(message.start_state)) - return "start_state: string expected"; - if (message.current_state != null && message.hasOwnProperty("current_state")) - if (!$util.isString(message.current_state)) - return "current_state: string expected"; - if (message.dry_run_results != null && message.hasOwnProperty("dry_run_results")) { - if (!Array.isArray(message.dry_run_results)) - return "dry_run_results: array expected"; - for (let i = 0; i < message.dry_run_results.length; ++i) - if (!$util.isString(message.dry_run_results[i])) - return "dry_run_results: string[] expected"; + if (message.mirror_rules != null && message.hasOwnProperty("mirror_rules")) { + let error = $root.vschema.MirrorRules.verify(message.mirror_rules); + if (error) + return "mirror_rules." + error; } return null; }; /** - * Creates a WorkflowSwitchTrafficResponse message from a plain object. Also converts values to their respective internal types. + * Creates a GetMirrorRulesResponse message from a plain object. Also converts values to their respective internal types. * @function fromObject - * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @memberof vtctldata.GetMirrorRulesResponse * @static * @param {Object.} object Plain object - * @returns {vtctldata.WorkflowSwitchTrafficResponse} WorkflowSwitchTrafficResponse + * @returns {vtctldata.GetMirrorRulesResponse} GetMirrorRulesResponse */ - WorkflowSwitchTrafficResponse.fromObject = function fromObject(object) { - if (object instanceof $root.vtctldata.WorkflowSwitchTrafficResponse) + GetMirrorRulesResponse.fromObject = function fromObject(object) { + if (object instanceof $root.vtctldata.GetMirrorRulesResponse) return object; - let message = new $root.vtctldata.WorkflowSwitchTrafficResponse(); - if (object.summary != null) - message.summary = String(object.summary); - if (object.start_state != null) - message.start_state = String(object.start_state); - if (object.current_state != null) - message.current_state = String(object.current_state); - if (object.dry_run_results) { - if (!Array.isArray(object.dry_run_results)) - throw TypeError(".vtctldata.WorkflowSwitchTrafficResponse.dry_run_results: array expected"); - message.dry_run_results = []; - for (let i = 0; i < object.dry_run_results.length; ++i) - message.dry_run_results[i] = String(object.dry_run_results[i]); + let message = new $root.vtctldata.GetMirrorRulesResponse(); + if (object.mirror_rules != null) { + if (typeof object.mirror_rules !== "object") + throw TypeError(".vtctldata.GetMirrorRulesResponse.mirror_rules: object expected"); + message.mirror_rules = $root.vschema.MirrorRules.fromObject(object.mirror_rules); } return message; }; /** - * Creates a plain object from a WorkflowSwitchTrafficResponse message. Also converts values to other types if specified. + * Creates a plain object from a GetMirrorRulesResponse message. Also converts values to other types if specified. * @function toObject - * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @memberof vtctldata.GetMirrorRulesResponse * @static - * @param {vtctldata.WorkflowSwitchTrafficResponse} message WorkflowSwitchTrafficResponse + * @param {vtctldata.GetMirrorRulesResponse} message GetMirrorRulesResponse * @param {$protobuf.IConversionOptions} [options] Conversion options * @returns {Object.} Plain object */ - WorkflowSwitchTrafficResponse.toObject = function toObject(message, options) { + GetMirrorRulesResponse.toObject = function toObject(message, options) { if (!options) options = {}; let object = {}; - if (options.arrays || options.defaults) - object.dry_run_results = []; - if (options.defaults) { - object.summary = ""; - object.start_state = ""; - object.current_state = ""; - } - if (message.summary != null && message.hasOwnProperty("summary")) - object.summary = message.summary; - if (message.start_state != null && message.hasOwnProperty("start_state")) - object.start_state = message.start_state; - if (message.current_state != null && message.hasOwnProperty("current_state")) - object.current_state = message.current_state; - if (message.dry_run_results && message.dry_run_results.length) { - object.dry_run_results = []; - for (let j = 0; j < message.dry_run_results.length; ++j) - object.dry_run_results[j] = message.dry_run_results[j]; - } + if (options.defaults) + object.mirror_rules = null; + if (message.mirror_rules != null && message.hasOwnProperty("mirror_rules")) + object.mirror_rules = $root.vschema.MirrorRules.toObject(message.mirror_rules, options); return object; }; /** - * Converts this WorkflowSwitchTrafficResponse to JSON. + * Converts this GetMirrorRulesResponse to JSON. * @function toJSON - * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @memberof vtctldata.GetMirrorRulesResponse * @instance * @returns {Object.} JSON object */ - WorkflowSwitchTrafficResponse.prototype.toJSON = function toJSON() { + GetMirrorRulesResponse.prototype.toJSON = function toJSON() { return this.constructor.toObject(this, $protobuf.util.toJSONOptions); }; /** - * Gets the default type url for WorkflowSwitchTrafficResponse + * Gets the default type url for GetMirrorRulesResponse * @function getTypeUrl - * @memberof vtctldata.WorkflowSwitchTrafficResponse + * @memberof vtctldata.GetMirrorRulesResponse * @static * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") * @returns {string} The default type url */ - WorkflowSwitchTrafficResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + GetMirrorRulesResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { if (typeUrlPrefix === undefined) { typeUrlPrefix = "type.googleapis.com"; } - return typeUrlPrefix + "/vtctldata.WorkflowSwitchTrafficResponse"; + return typeUrlPrefix + "/vtctldata.GetMirrorRulesResponse"; }; - return WorkflowSwitchTrafficResponse; + return GetMirrorRulesResponse; })(); - vtctldata.WorkflowUpdateRequest = (function() { + vtctldata.WorkflowMirrorTrafficRequest = (function() { /** - * Properties of a WorkflowUpdateRequest. + * Properties of a WorkflowMirrorTrafficRequest. * @memberof vtctldata - * @interface IWorkflowUpdateRequest - * @property {string|null} [keyspace] WorkflowUpdateRequest keyspace - * @property {tabletmanagerdata.IUpdateVReplicationWorkflowRequest|null} [tablet_request] WorkflowUpdateRequest tablet_request + * @interface IWorkflowMirrorTrafficRequest + * @property {string|null} [keyspace] WorkflowMirrorTrafficRequest keyspace + * @property {string|null} [workflow] WorkflowMirrorTrafficRequest workflow + * @property {Array.|null} [tablet_types] WorkflowMirrorTrafficRequest tablet_types + * @property {number|null} [percent] WorkflowMirrorTrafficRequest percent */ /** - * Constructs a new WorkflowUpdateRequest. + * Constructs a new WorkflowMirrorTrafficRequest. * @memberof vtctldata - * @classdesc Represents a WorkflowUpdateRequest. - * @implements IWorkflowUpdateRequest + * @classdesc Represents a WorkflowMirrorTrafficRequest. + * @implements IWorkflowMirrorTrafficRequest * @constructor - * @param {vtctldata.IWorkflowUpdateRequest=} [properties] Properties to set + * @param {vtctldata.IWorkflowMirrorTrafficRequest=} [properties] Properties to set */ - function WorkflowUpdateRequest(properties) { + function WorkflowMirrorTrafficRequest(properties) { + this.tablet_types = []; if (properties) for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) @@ -180661,80 +180988,104 @@ export const vtctldata = $root.vtctldata = (() => { } /** - * WorkflowUpdateRequest keyspace. + * WorkflowMirrorTrafficRequest keyspace. * @member {string} keyspace - * @memberof vtctldata.WorkflowUpdateRequest + * @memberof vtctldata.WorkflowMirrorTrafficRequest * @instance */ - WorkflowUpdateRequest.prototype.keyspace = ""; + WorkflowMirrorTrafficRequest.prototype.keyspace = ""; /** - * WorkflowUpdateRequest tablet_request. - * @member {tabletmanagerdata.IUpdateVReplicationWorkflowRequest|null|undefined} tablet_request - * @memberof vtctldata.WorkflowUpdateRequest + * WorkflowMirrorTrafficRequest workflow. + * @member {string} workflow + * @memberof vtctldata.WorkflowMirrorTrafficRequest * @instance */ - WorkflowUpdateRequest.prototype.tablet_request = null; + WorkflowMirrorTrafficRequest.prototype.workflow = ""; /** - * Creates a new WorkflowUpdateRequest instance using the specified properties. + * WorkflowMirrorTrafficRequest tablet_types. + * @member {Array.} tablet_types + * @memberof vtctldata.WorkflowMirrorTrafficRequest + * @instance + */ + WorkflowMirrorTrafficRequest.prototype.tablet_types = $util.emptyArray; + + /** + * WorkflowMirrorTrafficRequest percent. + * @member {number} percent + * @memberof vtctldata.WorkflowMirrorTrafficRequest + * @instance + */ + WorkflowMirrorTrafficRequest.prototype.percent = 0; + + /** + * Creates a new WorkflowMirrorTrafficRequest instance using the specified properties. * @function create - * @memberof vtctldata.WorkflowUpdateRequest + * @memberof vtctldata.WorkflowMirrorTrafficRequest * @static - * @param {vtctldata.IWorkflowUpdateRequest=} [properties] Properties to set - * @returns {vtctldata.WorkflowUpdateRequest} WorkflowUpdateRequest instance + * @param {vtctldata.IWorkflowMirrorTrafficRequest=} [properties] Properties to set + * @returns {vtctldata.WorkflowMirrorTrafficRequest} WorkflowMirrorTrafficRequest instance */ - WorkflowUpdateRequest.create = function create(properties) { - return new WorkflowUpdateRequest(properties); + WorkflowMirrorTrafficRequest.create = function create(properties) { + return new WorkflowMirrorTrafficRequest(properties); }; /** - * Encodes the specified WorkflowUpdateRequest message. Does not implicitly {@link vtctldata.WorkflowUpdateRequest.verify|verify} messages. + * Encodes the specified WorkflowMirrorTrafficRequest message. Does not implicitly {@link vtctldata.WorkflowMirrorTrafficRequest.verify|verify} messages. * @function encode - * @memberof vtctldata.WorkflowUpdateRequest + * @memberof vtctldata.WorkflowMirrorTrafficRequest * @static - * @param {vtctldata.IWorkflowUpdateRequest} message WorkflowUpdateRequest message or plain object to encode + * @param {vtctldata.IWorkflowMirrorTrafficRequest} message WorkflowMirrorTrafficRequest message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - WorkflowUpdateRequest.encode = function encode(message, writer) { + WorkflowMirrorTrafficRequest.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); if (message.keyspace != null && Object.hasOwnProperty.call(message, "keyspace")) writer.uint32(/* id 1, wireType 2 =*/10).string(message.keyspace); - if (message.tablet_request != null && Object.hasOwnProperty.call(message, "tablet_request")) - $root.tabletmanagerdata.UpdateVReplicationWorkflowRequest.encode(message.tablet_request, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); + if (message.workflow != null && Object.hasOwnProperty.call(message, "workflow")) + writer.uint32(/* id 2, wireType 2 =*/18).string(message.workflow); + if (message.tablet_types != null && message.tablet_types.length) { + writer.uint32(/* id 3, wireType 2 =*/26).fork(); + for (let i = 0; i < message.tablet_types.length; ++i) + writer.int32(message.tablet_types[i]); + writer.ldelim(); + } + if (message.percent != null && Object.hasOwnProperty.call(message, "percent")) + writer.uint32(/* id 4, wireType 5 =*/37).float(message.percent); return writer; }; /** - * Encodes the specified WorkflowUpdateRequest message, length delimited. Does not implicitly {@link vtctldata.WorkflowUpdateRequest.verify|verify} messages. + * Encodes the specified WorkflowMirrorTrafficRequest message, length delimited. Does not implicitly {@link vtctldata.WorkflowMirrorTrafficRequest.verify|verify} messages. * @function encodeDelimited - * @memberof vtctldata.WorkflowUpdateRequest + * @memberof vtctldata.WorkflowMirrorTrafficRequest * @static - * @param {vtctldata.IWorkflowUpdateRequest} message WorkflowUpdateRequest message or plain object to encode + * @param {vtctldata.IWorkflowMirrorTrafficRequest} message WorkflowMirrorTrafficRequest message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - WorkflowUpdateRequest.encodeDelimited = function encodeDelimited(message, writer) { + WorkflowMirrorTrafficRequest.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a WorkflowUpdateRequest message from the specified reader or buffer. + * Decodes a WorkflowMirrorTrafficRequest message from the specified reader or buffer. * @function decode - * @memberof vtctldata.WorkflowUpdateRequest + * @memberof vtctldata.WorkflowMirrorTrafficRequest * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from * @param {number} [length] Message length if known beforehand - * @returns {vtctldata.WorkflowUpdateRequest} WorkflowUpdateRequest + * @returns {vtctldata.WorkflowMirrorTrafficRequest} WorkflowMirrorTrafficRequest * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - WorkflowUpdateRequest.decode = function decode(reader, length) { + WorkflowMirrorTrafficRequest.decode = function decode(reader, length) { if (!(reader instanceof $Reader)) reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.WorkflowUpdateRequest(); + let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.WorkflowMirrorTrafficRequest(); while (reader.pos < end) { let tag = reader.uint32(); switch (tag >>> 3) { @@ -180743,7 +181094,22 @@ export const vtctldata = $root.vtctldata = (() => { break; } case 2: { - message.tablet_request = $root.tabletmanagerdata.UpdateVReplicationWorkflowRequest.decode(reader, reader.uint32()); + message.workflow = reader.string(); + break; + } + case 3: { + if (!(message.tablet_types && message.tablet_types.length)) + message.tablet_types = []; + if ((tag & 7) === 2) { + let end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) + message.tablet_types.push(reader.int32()); + } else + message.tablet_types.push(reader.int32()); + break; + } + case 4: { + message.percent = reader.float(); break; } default: @@ -180755,138 +181121,226 @@ export const vtctldata = $root.vtctldata = (() => { }; /** - * Decodes a WorkflowUpdateRequest message from the specified reader or buffer, length delimited. + * Decodes a WorkflowMirrorTrafficRequest message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof vtctldata.WorkflowUpdateRequest + * @memberof vtctldata.WorkflowMirrorTrafficRequest * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {vtctldata.WorkflowUpdateRequest} WorkflowUpdateRequest + * @returns {vtctldata.WorkflowMirrorTrafficRequest} WorkflowMirrorTrafficRequest * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - WorkflowUpdateRequest.decodeDelimited = function decodeDelimited(reader) { + WorkflowMirrorTrafficRequest.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; /** - * Verifies a WorkflowUpdateRequest message. + * Verifies a WorkflowMirrorTrafficRequest message. * @function verify - * @memberof vtctldata.WorkflowUpdateRequest + * @memberof vtctldata.WorkflowMirrorTrafficRequest * @static * @param {Object.} message Plain object to verify * @returns {string|null} `null` if valid, otherwise the reason why it is not */ - WorkflowUpdateRequest.verify = function verify(message) { + WorkflowMirrorTrafficRequest.verify = function verify(message) { if (typeof message !== "object" || message === null) return "object expected"; if (message.keyspace != null && message.hasOwnProperty("keyspace")) if (!$util.isString(message.keyspace)) return "keyspace: string expected"; - if (message.tablet_request != null && message.hasOwnProperty("tablet_request")) { - let error = $root.tabletmanagerdata.UpdateVReplicationWorkflowRequest.verify(message.tablet_request); - if (error) - return "tablet_request." + error; + if (message.workflow != null && message.hasOwnProperty("workflow")) + if (!$util.isString(message.workflow)) + return "workflow: string expected"; + if (message.tablet_types != null && message.hasOwnProperty("tablet_types")) { + if (!Array.isArray(message.tablet_types)) + return "tablet_types: array expected"; + for (let i = 0; i < message.tablet_types.length; ++i) + switch (message.tablet_types[i]) { + default: + return "tablet_types: enum value[] expected"; + case 0: + case 1: + case 1: + case 2: + case 3: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + break; + } } + if (message.percent != null && message.hasOwnProperty("percent")) + if (typeof message.percent !== "number") + return "percent: number expected"; return null; }; /** - * Creates a WorkflowUpdateRequest message from a plain object. Also converts values to their respective internal types. + * Creates a WorkflowMirrorTrafficRequest message from a plain object. Also converts values to their respective internal types. * @function fromObject - * @memberof vtctldata.WorkflowUpdateRequest + * @memberof vtctldata.WorkflowMirrorTrafficRequest * @static * @param {Object.} object Plain object - * @returns {vtctldata.WorkflowUpdateRequest} WorkflowUpdateRequest + * @returns {vtctldata.WorkflowMirrorTrafficRequest} WorkflowMirrorTrafficRequest */ - WorkflowUpdateRequest.fromObject = function fromObject(object) { - if (object instanceof $root.vtctldata.WorkflowUpdateRequest) + WorkflowMirrorTrafficRequest.fromObject = function fromObject(object) { + if (object instanceof $root.vtctldata.WorkflowMirrorTrafficRequest) return object; - let message = new $root.vtctldata.WorkflowUpdateRequest(); + let message = new $root.vtctldata.WorkflowMirrorTrafficRequest(); if (object.keyspace != null) message.keyspace = String(object.keyspace); - if (object.tablet_request != null) { - if (typeof object.tablet_request !== "object") - throw TypeError(".vtctldata.WorkflowUpdateRequest.tablet_request: object expected"); - message.tablet_request = $root.tabletmanagerdata.UpdateVReplicationWorkflowRequest.fromObject(object.tablet_request); + if (object.workflow != null) + message.workflow = String(object.workflow); + if (object.tablet_types) { + if (!Array.isArray(object.tablet_types)) + throw TypeError(".vtctldata.WorkflowMirrorTrafficRequest.tablet_types: array expected"); + message.tablet_types = []; + for (let i = 0; i < object.tablet_types.length; ++i) + switch (object.tablet_types[i]) { + default: + if (typeof object.tablet_types[i] === "number") { + message.tablet_types[i] = object.tablet_types[i]; + break; + } + case "UNKNOWN": + case 0: + message.tablet_types[i] = 0; + break; + case "PRIMARY": + case 1: + message.tablet_types[i] = 1; + break; + case "MASTER": + case 1: + message.tablet_types[i] = 1; + break; + case "REPLICA": + case 2: + message.tablet_types[i] = 2; + break; + case "RDONLY": + case 3: + message.tablet_types[i] = 3; + break; + case "BATCH": + case 3: + message.tablet_types[i] = 3; + break; + case "SPARE": + case 4: + message.tablet_types[i] = 4; + break; + case "EXPERIMENTAL": + case 5: + message.tablet_types[i] = 5; + break; + case "BACKUP": + case 6: + message.tablet_types[i] = 6; + break; + case "RESTORE": + case 7: + message.tablet_types[i] = 7; + break; + case "DRAINED": + case 8: + message.tablet_types[i] = 8; + break; + } } + if (object.percent != null) + message.percent = Number(object.percent); return message; }; /** - * Creates a plain object from a WorkflowUpdateRequest message. Also converts values to other types if specified. + * Creates a plain object from a WorkflowMirrorTrafficRequest message. Also converts values to other types if specified. * @function toObject - * @memberof vtctldata.WorkflowUpdateRequest + * @memberof vtctldata.WorkflowMirrorTrafficRequest * @static - * @param {vtctldata.WorkflowUpdateRequest} message WorkflowUpdateRequest + * @param {vtctldata.WorkflowMirrorTrafficRequest} message WorkflowMirrorTrafficRequest * @param {$protobuf.IConversionOptions} [options] Conversion options * @returns {Object.} Plain object */ - WorkflowUpdateRequest.toObject = function toObject(message, options) { + WorkflowMirrorTrafficRequest.toObject = function toObject(message, options) { if (!options) options = {}; let object = {}; + if (options.arrays || options.defaults) + object.tablet_types = []; if (options.defaults) { object.keyspace = ""; - object.tablet_request = null; + object.workflow = ""; + object.percent = 0; } if (message.keyspace != null && message.hasOwnProperty("keyspace")) object.keyspace = message.keyspace; - if (message.tablet_request != null && message.hasOwnProperty("tablet_request")) - object.tablet_request = $root.tabletmanagerdata.UpdateVReplicationWorkflowRequest.toObject(message.tablet_request, options); + if (message.workflow != null && message.hasOwnProperty("workflow")) + object.workflow = message.workflow; + if (message.tablet_types && message.tablet_types.length) { + object.tablet_types = []; + for (let j = 0; j < message.tablet_types.length; ++j) + object.tablet_types[j] = options.enums === String ? $root.topodata.TabletType[message.tablet_types[j]] === undefined ? message.tablet_types[j] : $root.topodata.TabletType[message.tablet_types[j]] : message.tablet_types[j]; + } + if (message.percent != null && message.hasOwnProperty("percent")) + object.percent = options.json && !isFinite(message.percent) ? String(message.percent) : message.percent; return object; }; /** - * Converts this WorkflowUpdateRequest to JSON. + * Converts this WorkflowMirrorTrafficRequest to JSON. * @function toJSON - * @memberof vtctldata.WorkflowUpdateRequest + * @memberof vtctldata.WorkflowMirrorTrafficRequest * @instance * @returns {Object.} JSON object */ - WorkflowUpdateRequest.prototype.toJSON = function toJSON() { + WorkflowMirrorTrafficRequest.prototype.toJSON = function toJSON() { return this.constructor.toObject(this, $protobuf.util.toJSONOptions); }; /** - * Gets the default type url for WorkflowUpdateRequest + * Gets the default type url for WorkflowMirrorTrafficRequest * @function getTypeUrl - * @memberof vtctldata.WorkflowUpdateRequest + * @memberof vtctldata.WorkflowMirrorTrafficRequest * @static * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") * @returns {string} The default type url */ - WorkflowUpdateRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + WorkflowMirrorTrafficRequest.getTypeUrl = function getTypeUrl(typeUrlPrefix) { if (typeUrlPrefix === undefined) { typeUrlPrefix = "type.googleapis.com"; } - return typeUrlPrefix + "/vtctldata.WorkflowUpdateRequest"; + return typeUrlPrefix + "/vtctldata.WorkflowMirrorTrafficRequest"; }; - return WorkflowUpdateRequest; + return WorkflowMirrorTrafficRequest; })(); - vtctldata.WorkflowUpdateResponse = (function() { + vtctldata.WorkflowMirrorTrafficResponse = (function() { /** - * Properties of a WorkflowUpdateResponse. + * Properties of a WorkflowMirrorTrafficResponse. * @memberof vtctldata - * @interface IWorkflowUpdateResponse - * @property {string|null} [summary] WorkflowUpdateResponse summary - * @property {Array.|null} [details] WorkflowUpdateResponse details + * @interface IWorkflowMirrorTrafficResponse + * @property {string|null} [summary] WorkflowMirrorTrafficResponse summary + * @property {string|null} [start_state] WorkflowMirrorTrafficResponse start_state + * @property {string|null} [current_state] WorkflowMirrorTrafficResponse current_state */ /** - * Constructs a new WorkflowUpdateResponse. + * Constructs a new WorkflowMirrorTrafficResponse. * @memberof vtctldata - * @classdesc Represents a WorkflowUpdateResponse. - * @implements IWorkflowUpdateResponse + * @classdesc Represents a WorkflowMirrorTrafficResponse. + * @implements IWorkflowMirrorTrafficResponse * @constructor - * @param {vtctldata.IWorkflowUpdateResponse=} [properties] Properties to set + * @param {vtctldata.IWorkflowMirrorTrafficResponse=} [properties] Properties to set */ - function WorkflowUpdateResponse(properties) { - this.details = []; + function WorkflowMirrorTrafficResponse(properties) { if (properties) for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) @@ -180894,81 +181348,90 @@ export const vtctldata = $root.vtctldata = (() => { } /** - * WorkflowUpdateResponse summary. + * WorkflowMirrorTrafficResponse summary. * @member {string} summary - * @memberof vtctldata.WorkflowUpdateResponse + * @memberof vtctldata.WorkflowMirrorTrafficResponse * @instance */ - WorkflowUpdateResponse.prototype.summary = ""; + WorkflowMirrorTrafficResponse.prototype.summary = ""; /** - * WorkflowUpdateResponse details. - * @member {Array.} details - * @memberof vtctldata.WorkflowUpdateResponse + * WorkflowMirrorTrafficResponse start_state. + * @member {string} start_state + * @memberof vtctldata.WorkflowMirrorTrafficResponse * @instance */ - WorkflowUpdateResponse.prototype.details = $util.emptyArray; + WorkflowMirrorTrafficResponse.prototype.start_state = ""; /** - * Creates a new WorkflowUpdateResponse instance using the specified properties. + * WorkflowMirrorTrafficResponse current_state. + * @member {string} current_state + * @memberof vtctldata.WorkflowMirrorTrafficResponse + * @instance + */ + WorkflowMirrorTrafficResponse.prototype.current_state = ""; + + /** + * Creates a new WorkflowMirrorTrafficResponse instance using the specified properties. * @function create - * @memberof vtctldata.WorkflowUpdateResponse + * @memberof vtctldata.WorkflowMirrorTrafficResponse * @static - * @param {vtctldata.IWorkflowUpdateResponse=} [properties] Properties to set - * @returns {vtctldata.WorkflowUpdateResponse} WorkflowUpdateResponse instance + * @param {vtctldata.IWorkflowMirrorTrafficResponse=} [properties] Properties to set + * @returns {vtctldata.WorkflowMirrorTrafficResponse} WorkflowMirrorTrafficResponse instance */ - WorkflowUpdateResponse.create = function create(properties) { - return new WorkflowUpdateResponse(properties); + WorkflowMirrorTrafficResponse.create = function create(properties) { + return new WorkflowMirrorTrafficResponse(properties); }; /** - * Encodes the specified WorkflowUpdateResponse message. Does not implicitly {@link vtctldata.WorkflowUpdateResponse.verify|verify} messages. + * Encodes the specified WorkflowMirrorTrafficResponse message. Does not implicitly {@link vtctldata.WorkflowMirrorTrafficResponse.verify|verify} messages. * @function encode - * @memberof vtctldata.WorkflowUpdateResponse + * @memberof vtctldata.WorkflowMirrorTrafficResponse * @static - * @param {vtctldata.IWorkflowUpdateResponse} message WorkflowUpdateResponse message or plain object to encode + * @param {vtctldata.IWorkflowMirrorTrafficResponse} message WorkflowMirrorTrafficResponse message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - WorkflowUpdateResponse.encode = function encode(message, writer) { + WorkflowMirrorTrafficResponse.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); if (message.summary != null && Object.hasOwnProperty.call(message, "summary")) writer.uint32(/* id 1, wireType 2 =*/10).string(message.summary); - if (message.details != null && message.details.length) - for (let i = 0; i < message.details.length; ++i) - $root.vtctldata.WorkflowUpdateResponse.TabletInfo.encode(message.details[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); + if (message.start_state != null && Object.hasOwnProperty.call(message, "start_state")) + writer.uint32(/* id 2, wireType 2 =*/18).string(message.start_state); + if (message.current_state != null && Object.hasOwnProperty.call(message, "current_state")) + writer.uint32(/* id 3, wireType 2 =*/26).string(message.current_state); return writer; }; /** - * Encodes the specified WorkflowUpdateResponse message, length delimited. Does not implicitly {@link vtctldata.WorkflowUpdateResponse.verify|verify} messages. + * Encodes the specified WorkflowMirrorTrafficResponse message, length delimited. Does not implicitly {@link vtctldata.WorkflowMirrorTrafficResponse.verify|verify} messages. * @function encodeDelimited - * @memberof vtctldata.WorkflowUpdateResponse + * @memberof vtctldata.WorkflowMirrorTrafficResponse * @static - * @param {vtctldata.IWorkflowUpdateResponse} message WorkflowUpdateResponse message or plain object to encode + * @param {vtctldata.IWorkflowMirrorTrafficResponse} message WorkflowMirrorTrafficResponse message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - WorkflowUpdateResponse.encodeDelimited = function encodeDelimited(message, writer) { + WorkflowMirrorTrafficResponse.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a WorkflowUpdateResponse message from the specified reader or buffer. + * Decodes a WorkflowMirrorTrafficResponse message from the specified reader or buffer. * @function decode - * @memberof vtctldata.WorkflowUpdateResponse + * @memberof vtctldata.WorkflowMirrorTrafficResponse * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from * @param {number} [length] Message length if known beforehand - * @returns {vtctldata.WorkflowUpdateResponse} WorkflowUpdateResponse + * @returns {vtctldata.WorkflowMirrorTrafficResponse} WorkflowMirrorTrafficResponse * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - WorkflowUpdateResponse.decode = function decode(reader, length) { + WorkflowMirrorTrafficResponse.decode = function decode(reader, length) { if (!(reader instanceof $Reader)) reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.WorkflowUpdateResponse(); + let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.WorkflowMirrorTrafficResponse(); while (reader.pos < end) { let tag = reader.uint32(); switch (tag >>> 3) { @@ -180977,9 +181440,11 @@ export const vtctldata = $root.vtctldata = (() => { break; } case 2: { - if (!(message.details && message.details.length)) - message.details = []; - message.details.push($root.vtctldata.WorkflowUpdateResponse.TabletInfo.decode(reader, reader.uint32())); + message.start_state = reader.string(); + break; + } + case 3: { + message.current_state = reader.string(); break; } default: @@ -180991,360 +181456,119 @@ export const vtctldata = $root.vtctldata = (() => { }; /** - * Decodes a WorkflowUpdateResponse message from the specified reader or buffer, length delimited. + * Decodes a WorkflowMirrorTrafficResponse message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof vtctldata.WorkflowUpdateResponse + * @memberof vtctldata.WorkflowMirrorTrafficResponse * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {vtctldata.WorkflowUpdateResponse} WorkflowUpdateResponse + * @returns {vtctldata.WorkflowMirrorTrafficResponse} WorkflowMirrorTrafficResponse * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - WorkflowUpdateResponse.decodeDelimited = function decodeDelimited(reader) { + WorkflowMirrorTrafficResponse.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; /** - * Verifies a WorkflowUpdateResponse message. + * Verifies a WorkflowMirrorTrafficResponse message. * @function verify - * @memberof vtctldata.WorkflowUpdateResponse + * @memberof vtctldata.WorkflowMirrorTrafficResponse * @static * @param {Object.} message Plain object to verify * @returns {string|null} `null` if valid, otherwise the reason why it is not */ - WorkflowUpdateResponse.verify = function verify(message) { + WorkflowMirrorTrafficResponse.verify = function verify(message) { if (typeof message !== "object" || message === null) return "object expected"; if (message.summary != null && message.hasOwnProperty("summary")) if (!$util.isString(message.summary)) return "summary: string expected"; - if (message.details != null && message.hasOwnProperty("details")) { - if (!Array.isArray(message.details)) - return "details: array expected"; - for (let i = 0; i < message.details.length; ++i) { - let error = $root.vtctldata.WorkflowUpdateResponse.TabletInfo.verify(message.details[i]); - if (error) - return "details." + error; - } - } + if (message.start_state != null && message.hasOwnProperty("start_state")) + if (!$util.isString(message.start_state)) + return "start_state: string expected"; + if (message.current_state != null && message.hasOwnProperty("current_state")) + if (!$util.isString(message.current_state)) + return "current_state: string expected"; return null; }; /** - * Creates a WorkflowUpdateResponse message from a plain object. Also converts values to their respective internal types. + * Creates a WorkflowMirrorTrafficResponse message from a plain object. Also converts values to their respective internal types. * @function fromObject - * @memberof vtctldata.WorkflowUpdateResponse + * @memberof vtctldata.WorkflowMirrorTrafficResponse * @static * @param {Object.} object Plain object - * @returns {vtctldata.WorkflowUpdateResponse} WorkflowUpdateResponse + * @returns {vtctldata.WorkflowMirrorTrafficResponse} WorkflowMirrorTrafficResponse */ - WorkflowUpdateResponse.fromObject = function fromObject(object) { - if (object instanceof $root.vtctldata.WorkflowUpdateResponse) + WorkflowMirrorTrafficResponse.fromObject = function fromObject(object) { + if (object instanceof $root.vtctldata.WorkflowMirrorTrafficResponse) return object; - let message = new $root.vtctldata.WorkflowUpdateResponse(); + let message = new $root.vtctldata.WorkflowMirrorTrafficResponse(); if (object.summary != null) message.summary = String(object.summary); - if (object.details) { - if (!Array.isArray(object.details)) - throw TypeError(".vtctldata.WorkflowUpdateResponse.details: array expected"); - message.details = []; - for (let i = 0; i < object.details.length; ++i) { - if (typeof object.details[i] !== "object") - throw TypeError(".vtctldata.WorkflowUpdateResponse.details: object expected"); - message.details[i] = $root.vtctldata.WorkflowUpdateResponse.TabletInfo.fromObject(object.details[i]); - } - } + if (object.start_state != null) + message.start_state = String(object.start_state); + if (object.current_state != null) + message.current_state = String(object.current_state); return message; }; /** - * Creates a plain object from a WorkflowUpdateResponse message. Also converts values to other types if specified. + * Creates a plain object from a WorkflowMirrorTrafficResponse message. Also converts values to other types if specified. * @function toObject - * @memberof vtctldata.WorkflowUpdateResponse + * @memberof vtctldata.WorkflowMirrorTrafficResponse * @static - * @param {vtctldata.WorkflowUpdateResponse} message WorkflowUpdateResponse + * @param {vtctldata.WorkflowMirrorTrafficResponse} message WorkflowMirrorTrafficResponse * @param {$protobuf.IConversionOptions} [options] Conversion options * @returns {Object.} Plain object */ - WorkflowUpdateResponse.toObject = function toObject(message, options) { + WorkflowMirrorTrafficResponse.toObject = function toObject(message, options) { if (!options) options = {}; let object = {}; - if (options.arrays || options.defaults) - object.details = []; - if (options.defaults) + if (options.defaults) { object.summary = ""; + object.start_state = ""; + object.current_state = ""; + } if (message.summary != null && message.hasOwnProperty("summary")) object.summary = message.summary; - if (message.details && message.details.length) { - object.details = []; - for (let j = 0; j < message.details.length; ++j) - object.details[j] = $root.vtctldata.WorkflowUpdateResponse.TabletInfo.toObject(message.details[j], options); - } + if (message.start_state != null && message.hasOwnProperty("start_state")) + object.start_state = message.start_state; + if (message.current_state != null && message.hasOwnProperty("current_state")) + object.current_state = message.current_state; return object; }; /** - * Converts this WorkflowUpdateResponse to JSON. + * Converts this WorkflowMirrorTrafficResponse to JSON. * @function toJSON - * @memberof vtctldata.WorkflowUpdateResponse + * @memberof vtctldata.WorkflowMirrorTrafficResponse * @instance * @returns {Object.} JSON object */ - WorkflowUpdateResponse.prototype.toJSON = function toJSON() { + WorkflowMirrorTrafficResponse.prototype.toJSON = function toJSON() { return this.constructor.toObject(this, $protobuf.util.toJSONOptions); }; /** - * Gets the default type url for WorkflowUpdateResponse + * Gets the default type url for WorkflowMirrorTrafficResponse * @function getTypeUrl - * @memberof vtctldata.WorkflowUpdateResponse + * @memberof vtctldata.WorkflowMirrorTrafficResponse * @static * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") * @returns {string} The default type url */ - WorkflowUpdateResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + WorkflowMirrorTrafficResponse.getTypeUrl = function getTypeUrl(typeUrlPrefix) { if (typeUrlPrefix === undefined) { typeUrlPrefix = "type.googleapis.com"; } - return typeUrlPrefix + "/vtctldata.WorkflowUpdateResponse"; + return typeUrlPrefix + "/vtctldata.WorkflowMirrorTrafficResponse"; }; - WorkflowUpdateResponse.TabletInfo = (function() { - - /** - * Properties of a TabletInfo. - * @memberof vtctldata.WorkflowUpdateResponse - * @interface ITabletInfo - * @property {topodata.ITabletAlias|null} [tablet] TabletInfo tablet - * @property {boolean|null} [changed] TabletInfo changed - */ - - /** - * Constructs a new TabletInfo. - * @memberof vtctldata.WorkflowUpdateResponse - * @classdesc Represents a TabletInfo. - * @implements ITabletInfo - * @constructor - * @param {vtctldata.WorkflowUpdateResponse.ITabletInfo=} [properties] Properties to set - */ - function TabletInfo(properties) { - if (properties) - for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * TabletInfo tablet. - * @member {topodata.ITabletAlias|null|undefined} tablet - * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo - * @instance - */ - TabletInfo.prototype.tablet = null; - - /** - * TabletInfo changed. - * @member {boolean} changed - * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo - * @instance - */ - TabletInfo.prototype.changed = false; - - /** - * Creates a new TabletInfo instance using the specified properties. - * @function create - * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo - * @static - * @param {vtctldata.WorkflowUpdateResponse.ITabletInfo=} [properties] Properties to set - * @returns {vtctldata.WorkflowUpdateResponse.TabletInfo} TabletInfo instance - */ - TabletInfo.create = function create(properties) { - return new TabletInfo(properties); - }; - - /** - * Encodes the specified TabletInfo message. Does not implicitly {@link vtctldata.WorkflowUpdateResponse.TabletInfo.verify|verify} messages. - * @function encode - * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo - * @static - * @param {vtctldata.WorkflowUpdateResponse.ITabletInfo} message TabletInfo message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TabletInfo.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.tablet != null && Object.hasOwnProperty.call(message, "tablet")) - $root.topodata.TabletAlias.encode(message.tablet, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - if (message.changed != null && Object.hasOwnProperty.call(message, "changed")) - writer.uint32(/* id 2, wireType 0 =*/16).bool(message.changed); - return writer; - }; - - /** - * Encodes the specified TabletInfo message, length delimited. Does not implicitly {@link vtctldata.WorkflowUpdateResponse.TabletInfo.verify|verify} messages. - * @function encodeDelimited - * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo - * @static - * @param {vtctldata.WorkflowUpdateResponse.ITabletInfo} message TabletInfo message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TabletInfo.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a TabletInfo message from the specified reader or buffer. - * @function decode - * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {vtctldata.WorkflowUpdateResponse.TabletInfo} TabletInfo - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TabletInfo.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.vtctldata.WorkflowUpdateResponse.TabletInfo(); - while (reader.pos < end) { - let tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.tablet = $root.topodata.TabletAlias.decode(reader, reader.uint32()); - break; - } - case 2: { - message.changed = reader.bool(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a TabletInfo message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {vtctldata.WorkflowUpdateResponse.TabletInfo} TabletInfo - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TabletInfo.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a TabletInfo message. - * @function verify - * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - TabletInfo.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.tablet != null && message.hasOwnProperty("tablet")) { - let error = $root.topodata.TabletAlias.verify(message.tablet); - if (error) - return "tablet." + error; - } - if (message.changed != null && message.hasOwnProperty("changed")) - if (typeof message.changed !== "boolean") - return "changed: boolean expected"; - return null; - }; - - /** - * Creates a TabletInfo message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo - * @static - * @param {Object.} object Plain object - * @returns {vtctldata.WorkflowUpdateResponse.TabletInfo} TabletInfo - */ - TabletInfo.fromObject = function fromObject(object) { - if (object instanceof $root.vtctldata.WorkflowUpdateResponse.TabletInfo) - return object; - let message = new $root.vtctldata.WorkflowUpdateResponse.TabletInfo(); - if (object.tablet != null) { - if (typeof object.tablet !== "object") - throw TypeError(".vtctldata.WorkflowUpdateResponse.TabletInfo.tablet: object expected"); - message.tablet = $root.topodata.TabletAlias.fromObject(object.tablet); - } - if (object.changed != null) - message.changed = Boolean(object.changed); - return message; - }; - - /** - * Creates a plain object from a TabletInfo message. Also converts values to other types if specified. - * @function toObject - * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo - * @static - * @param {vtctldata.WorkflowUpdateResponse.TabletInfo} message TabletInfo - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - TabletInfo.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (options.defaults) { - object.tablet = null; - object.changed = false; - } - if (message.tablet != null && message.hasOwnProperty("tablet")) - object.tablet = $root.topodata.TabletAlias.toObject(message.tablet, options); - if (message.changed != null && message.hasOwnProperty("changed")) - object.changed = message.changed; - return object; - }; - - /** - * Converts this TabletInfo to JSON. - * @function toJSON - * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo - * @instance - * @returns {Object.} JSON object - */ - TabletInfo.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for TabletInfo - * @function getTypeUrl - * @memberof vtctldata.WorkflowUpdateResponse.TabletInfo - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - TabletInfo.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/vtctldata.WorkflowUpdateResponse.TabletInfo"; - }; - - return TabletInfo; - })(); - - return WorkflowUpdateResponse; + return WorkflowMirrorTrafficResponse; })(); return vtctldata;